mirror of
https://github.com/rajnandan1/kener.git
synced 2026-06-23 04:10:22 +00:00
fix(confirmation): exclude NO_DATA from lookback to prevent stuck confirmation under neutral-dense history (#756)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -333,8 +333,8 @@ export class MonitoringRepository extends BaseRepository {
|
||||
* Recent samples the Confirmation Threshold resolver needs, newest first: scheduled-check
|
||||
* observations (REALTIME/TIMEOUT/ERROR) plus incident/maintenance overlays. MANUAL pushes
|
||||
* and DEFAULT fill are excluded — they stay transparent to the counter. Returns `type` so
|
||||
* the resolver can stop at overlay rows (freeze); observations whose status is NO_DATA are
|
||||
* skipped as neutral by the resolver.
|
||||
* the resolver can stop at overlay rows (freeze). Observations whose status is NO_DATA are
|
||||
* excluded entirely (neutral — they neither advance nor reset the count and must not consume lookback slots).
|
||||
*/
|
||||
async getRecentSamplesForConfirmation(
|
||||
monitor_tag: string,
|
||||
@@ -346,6 +346,7 @@ export class MonitoringRepository extends BaseRepository {
|
||||
.where("monitor_tag", monitor_tag)
|
||||
.where("timestamp", "<", beforeTs)
|
||||
.whereIn("type", [...OBSERVED_CHECK_TYPES, ...OVERLAY_TYPES])
|
||||
.whereNot("status", GC.NO_DATA)
|
||||
.orderBy("timestamp", "desc")
|
||||
.limit(limit);
|
||||
}
|
||||
|
||||
@@ -32,8 +32,9 @@ export interface ConfirmationDeps {
|
||||
|
||||
// Overlay sample types that freeze the count (must match OVERLAY_TYPES in the monitoring repository).
|
||||
const OVERLAY_TYPES: string[] = [GC.INCIDENT, GC.MAINTENANCE];
|
||||
// Extra lookback rows beyond the threshold, to tolerate neutral (NO_DATA) rows that are skipped
|
||||
// rather than counted. Pathologically neutral-dense histories may delay confirmation by a check.
|
||||
// Extra lookback rows beyond the threshold: headroom for the anchor row and any interleaved
|
||||
// overlay rows. NO_DATA observations are excluded by the query (neutral), so they never
|
||||
// consume slots — the buffer does not need to scale with NO_DATA density.
|
||||
const LOOKBACK_BUFFER = 10;
|
||||
|
||||
/**
|
||||
@@ -90,7 +91,7 @@ export async function resolveConfirmedStatus(
|
||||
for (const row of recent) {
|
||||
if (row.type !== null && OVERLAY_TYPES.indexOf(row.type) !== -1) break; // freeze boundary
|
||||
const rawSide = sideOf(row.raw_status);
|
||||
if (rawSide === null) continue; // NO_DATA: neutral — neither advance nor reset
|
||||
if (rawSide === null) continue; // NO_DATA: neutral (excluded by the query; this is a defensive guard)
|
||||
if (rawSide === observedSide && sideOf(row.status) === confirmedSide) {
|
||||
pendingRun++;
|
||||
pendingTimestamps.push(row.timestamp);
|
||||
@@ -119,5 +120,6 @@ function confirmedSideStatus(
|
||||
if (row.type !== null && OVERLAY_TYPES.indexOf(row.type) !== -1) continue;
|
||||
if (sideOf(row.status) === confirmedSide && row.status) return row.status;
|
||||
}
|
||||
// Defensive fallback (unreachable when an anchor was found above); side is correct, severity may coarsen.
|
||||
return confirmedSide === "UP" ? GC.UP : GC.DOWN;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user