@@ -102,14 +102,6 @@ export class StatusService implements IStatusService {
102102 }
103103 } ;
104104
105- private appendToWindow = ( monitor : Monitor , status : boolean ) => {
106- monitor . statusWindow = monitor . statusWindow || [ ] ;
107- monitor . statusWindow . push ( status ) ;
108- while ( monitor . statusWindow . length > monitor . statusWindowSize ) {
109- monitor . statusWindow . shift ( ) ;
110- }
111- } ;
112-
113105 private toCheckSnapshot = ( check : Check ) : CheckSnapshot => {
114106 return {
115107 id : check . id ,
@@ -134,15 +126,6 @@ export class StatusService implements IStatusService {
134126 } ;
135127 } ;
136128
137- private appendToRecentChecks = ( monitor : Monitor , check : Check ) => {
138- monitor . recentChecks = monitor . recentChecks || [ ] ;
139- const checkSnapshot = this . toCheckSnapshot ( check ) ;
140- monitor . recentChecks . push ( checkSnapshot ) ;
141- while ( monitor . recentChecks . length > MAX_RECENT_CHECKS ) {
142- monitor . recentChecks . shift ( ) ;
143- }
144- } ;
145-
146129 private computeReachability = (
147130 currentStatus : MonitorStatus ,
148131 window : Array < boolean > ,
@@ -229,7 +212,7 @@ export class StatusService implements IStatusService {
229212 ) ;
230213 } ;
231214
232- newUpdateMonitorStatus = async (
215+ updateMonitorStatus = async (
233216 statusResponse : MonitorStatusResponse <
234217 | PingStatusPayload
235218 | HttpStatusPayload
@@ -315,121 +298,17 @@ export class StatusService implements IStatusService {
315298 }
316299 }
317300
318- // Apply the final status
319- updatedMonitor . status = newStatus ;
320-
321- const updated = await this . monitorsRepository . updateById ( updatedMonitor . id , updatedMonitor . teamId , updatedMonitor ) ;
322-
323- return {
324- monitor : updated ,
325- statusChanged,
326- prevStatus,
327- code,
328- timestamp : new Date ( ) . getTime ( ) ,
329- thresholdBreaches,
330- } ;
331- } catch ( error : unknown ) {
332- throw new AppError ( {
333- message : `Failed to update monitor with id ${ check . metadata . monitorId } with status: ${ error instanceof Error ? error . message : "Unknown error" } ` ,
334- service : SERVICE_NAME ,
335- method : "updateMonitorStatus" ,
336- } ) ;
337- }
338- } ;
339- updateMonitorStatus = async (
340- statusResponse : MonitorStatusResponse <
341- | PingStatusPayload
342- | HttpStatusPayload
343- | PageSpeedStatusPayload
344- | HardwareStatusPayload
345- | DockerStatusPayload
346- | PortStatusPayload
347- | GameStatusPayload
348- | GrpcStatusPayload
349- | undefined
350- > ,
351- check : Check
352- ) : Promise < StatusChangeResult > => {
353- try {
354- const { monitorId, teamId, status, code } = statusResponse ;
355- const monitor = await this . monitorsRepository . findById ( monitorId , teamId ) ;
356-
357- // Update running stats
358- await this . tryUpdateRunningStats ( monitor , statusResponse ) ;
359-
360- // Update the sliding window and recent checks
361- this . appendToWindow ( monitor , status ) ;
362- this . appendToRecentChecks ( monitor , check ) ;
363-
364- const prevStatus = monitor . status ;
365-
366- // Return early if not enough data points
367- if ( monitor . statusWindow . length < monitor . statusWindowSize ) {
368- monitor . status = status === true ? "up" : "down" ;
369- const updated = await this . monitorsRepository . updateById ( monitor . id , monitor . teamId , monitor ) ;
370- return {
371- monitor : updated ,
372- statusChanged : false ,
373- prevStatus,
374- code,
375- timestamp : Date . now ( ) ,
376- } ;
377- }
378-
379- // With a full window, a single raw check must not change UNLESS we are initializing. Otherwise, only the sliding-window threshold can trigger a transition.
380- let newStatus : MonitorStatus ;
381- if ( monitor . status === "initializing" ) {
382- newStatus = status === true ? "up" : "down" ;
383- } else {
384- newStatus = monitor . status ;
385- }
386-
387- let statusChanged = false ;
388-
389- // First evaluate reachability-based status changes, which apply to all monitor types and take precedence over hardware breaches.
390- const reachabilityResult = this . computeReachability ( newStatus , monitor . statusWindow , monitor . statusWindowThreshold ) ;
391- if ( reachabilityResult . transitioned ) {
392- newStatus = reachabilityResult . nextStatus ;
393- statusChanged = true ;
394- }
395-
396- // Evaluate hardware threshold breaches (only for hardware monitors with metrics payload)
397- let thresholdBreaches : HardwareBreaches | undefined ;
398- const hardwarePayload = statusResponse . payload as HardwareStatusPayload | undefined ;
399- if ( monitor . type === "hardware" && hardwarePayload ?. data ) {
400- const hardware = this . computeHardwareStatus ( {
401- currentStatus : newStatus ,
402- reachabilityDown : newStatus === "down" ,
403- metrics : hardwarePayload . data ,
404- thresholds : {
405- cpu : monitor . cpuAlertThreshold ,
406- memory : monitor . memoryAlertThreshold ,
407- disk : monitor . diskAlertThreshold ,
408- temp : monitor . tempAlertThreshold ,
409- } ,
410- counters : {
411- cpu : monitor . cpuAlertCounter ,
412- memory : monitor . memoryAlertCounter ,
413- disk : monitor . diskAlertCounter ,
414- temp : monitor . tempAlertCounter ,
415- } ,
416- } ) ;
417-
418- monitor . cpuAlertCounter = hardware . nextCounters . cpu ;
419- monitor . memoryAlertCounter = hardware . nextCounters . memory ;
420- monitor . diskAlertCounter = hardware . nextCounters . disk ;
421- monitor . tempAlertCounter = hardware . nextCounters . temp ;
422- thresholdBreaches = hardware . breaches ;
423- if ( hardware . transitioned ) {
424- newStatus = hardware . nextStatus ;
425- statusChanged = true ;
426- }
301+ // Apply the final status — only write fields computed by application logic,
302+ // not statusWindow/recentChecks which are owned by the atomic push.
303+ const patch : Partial < Monitor > = { status : newStatus } ;
304+ if ( updatedMonitor . type === "hardware" && hardwarePayload ?. data ) {
305+ patch . cpuAlertCounter = updatedMonitor . cpuAlertCounter ;
306+ patch . memoryAlertCounter = updatedMonitor . memoryAlertCounter ;
307+ patch . diskAlertCounter = updatedMonitor . diskAlertCounter ;
308+ patch . tempAlertCounter = updatedMonitor . tempAlertCounter ;
427309 }
428310
429- // Apply the final status
430- monitor . status = newStatus ;
431-
432- const updated = await this . monitorsRepository . updateById ( monitor . id , monitor . teamId , monitor ) ;
311+ const updated = await this . monitorsRepository . updateById ( updatedMonitor . id , updatedMonitor . teamId , patch ) ;
433312
434313 return {
435314 monitor : updated ,
0 commit comments