feat(monitoring): widen confirmation lookback to include overlays + type (#756)

Replaces getRecentObservedSamples with getRecentSamplesForConfirmation, which adds
INCIDENT/MAINTENANCE overlay rows and the `type` column to the result set so the
Confirmation Threshold resolver can detect freeze boundaries. MANUAL and DEFAULT
rows remain excluded (transparent). Adds OVERLAY_TYPES constant alongside the
existing OBSERVED_CHECK_TYPES. Updates dbimpl.ts declaration and binding to match.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Raj Nandan Sharma
2026-06-13 19:35:16 +05:30
parent 87fc3081df
commit a363079695
2 changed files with 19 additions and 9 deletions
+2 -2
View File
@@ -64,7 +64,7 @@ class DbImpl {
consecutivelyStatusFor!: MonitoringRepository["consecutivelyStatusFor"];
consecutivelyLatencyGreaterThan!: MonitoringRepository["consecutivelyLatencyGreaterThan"];
consecutivelyLatencyLessThan!: MonitoringRepository["consecutivelyLatencyLessThan"];
getRecentObservedSamples!: MonitoringRepository["getRecentObservedSamples"];
getRecentSamplesForConfirmation!: MonitoringRepository["getRecentSamplesForConfirmation"];
backfillConfirmedStatus!: MonitoringRepository["backfillConfirmedStatus"];
updateMonitoringData!: MonitoringRepository["updateMonitoringData"];
deleteMonitorDataByTag!: MonitoringRepository["deleteMonitorDataByTag"];
@@ -426,7 +426,7 @@ class DbImpl {
this.consecutivelyStatusFor = this.monitoring.consecutivelyStatusFor.bind(this.monitoring);
this.consecutivelyLatencyGreaterThan = this.monitoring.consecutivelyLatencyGreaterThan.bind(this.monitoring);
this.consecutivelyLatencyLessThan = this.monitoring.consecutivelyLatencyLessThan.bind(this.monitoring);
this.getRecentObservedSamples = this.monitoring.getRecentObservedSamples.bind(this.monitoring);
this.getRecentSamplesForConfirmation = this.monitoring.getRecentSamplesForConfirmation.bind(this.monitoring);
this.backfillConfirmedStatus = this.monitoring.backfillConfirmedStatus.bind(this.monitoring);
this.updateMonitoringData = this.monitoring.updateMonitoringData.bind(this.monitoring);
this.deleteMonitorDataByTag = this.monitoring.deleteMonitorDataByTag.bind(this.monitoring);
+17 -7
View File
@@ -26,6 +26,14 @@ const ALERT_VISIBLE_TYPES = [GC.REALTIME, GC.ERROR, GC.TIMEOUT, GC.MANUAL, GC.DE
*/
const OBSERVED_CHECK_TYPES = [GC.REALTIME, GC.TIMEOUT, GC.ERROR];
/**
* Overlay sample types that FREEZE Confirmation Threshold counting (issue #712 / ADR 0009):
* while one is active the count does not advance, and it acts as a hard boundary the
* pending run cannot cross. Included in the confirmation lookback (unlike MANUAL/DEFAULT,
* which stay transparent) so the resolver can detect the boundary.
*/
const OVERLAY_TYPES = [GC.INCIDENT, GC.MAINTENANCE];
/**
* Repository for monitoring data operations
*/
@@ -322,20 +330,22 @@ export class MonitoringRepository extends BaseRepository {
}
/**
* Most recent scheduled-check observations before `beforeTs`, newest first.
* Only REALTIME/TIMEOUT/ERROR rows — overlays, MANUAL, and DEFAULT are excluded so they
* stay transparent to Confirmation Threshold counting (issue #712 / ADR 0009).
* 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.
*/
async getRecentObservedSamples(
async getRecentSamplesForConfirmation(
monitor_tag: string,
beforeTs: number,
limit: number,
): Promise<Array<{ timestamp: number; status: string | null; raw_status: string | null }>> {
): Promise<Array<{ timestamp: number; status: string | null; raw_status: string | null; type: string | null }>> {
return await this.knex("monitoring_data")
.select("timestamp", "status", "raw_status")
.select("timestamp", "status", "raw_status", "type")
.where("monitor_tag", monitor_tag)
.where("timestamp", "<", beforeTs)
.whereIn("type", OBSERVED_CHECK_TYPES)
.whereIn("type", [...OBSERVED_CHECK_TYPES, ...OVERLAY_TYPES])
.orderBy("timestamp", "desc")
.limit(limit);
}