@@ -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 > ,
@@ -238,16 +221,31 @@ export class StatusService implements IStatusService {
238221 // Update running stats
239222 await this . tryUpdateRunningStats ( monitor , statusResponse ) ;
240223
241- // Update the sliding window and recent checks
242- this . appendToWindow ( monitor , status ) ;
243- this . appendToRecentChecks ( monitor , check ) ;
244-
245224 const prevStatus = monitor . status ;
225+ const checkSnapshot = this . toCheckSnapshot ( check ) ;
226+
227+ // Project the window as it will look after updating DB
228+ // This is done because we need the updated status window to compute new status, but we don't
229+ // want an an extra DB write just to get the window.
230+ const projectedWindow = [ ...( monitor . statusWindow || [ ] ) , check . status ] . slice ( - monitor . statusWindowSize ) ;
231+
232+ // Build the status patch — computed against the projected window
233+ const patch : Partial < Monitor > = { } ;
234+
235+ // Not enough data points yet
236+ if ( projectedWindow . length < monitor . statusWindowSize ) {
237+ patch . status = status === true ? "up" : "down" ;
238+
239+ const updated = await this . monitorsRepository . updateStatusWindowAndChecks (
240+ monitor . id ,
241+ monitor . teamId ,
242+ check . status ,
243+ checkSnapshot ,
244+ monitor . statusWindowSize ,
245+ MAX_RECENT_CHECKS ,
246+ patch
247+ ) ;
246248
247- // Return early if not enough data points
248- if ( monitor . statusWindow . length < monitor . statusWindowSize ) {
249- monitor . status = status === true ? "up" : "down" ;
250- const updated = await this . monitorsRepository . updateById ( monitor . id , monitor . teamId , monitor ) ;
251249 return {
252250 monitor : updated ,
253251 statusChanged : false ,
@@ -257,7 +255,8 @@ export class StatusService implements IStatusService {
257255 } ;
258256 }
259257
260- // 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.
258+ // With a full window, a single raw check must not change UNLESS we are initializing.
259+ // Otherwise, only the sliding-window threshold can trigger a transition.
261260 let newStatus : MonitorStatus ;
262261 if ( monitor . status === "initializing" ) {
263262 newStatus = status === true ? "up" : "down" ;
@@ -267,8 +266,9 @@ export class StatusService implements IStatusService {
267266
268267 let statusChanged = false ;
269268
270- // First evaluate reachability-based status changes, which apply to all monitor types and take precedence over hardware breaches.
271- const reachabilityResult = this . computeReachability ( newStatus , monitor . statusWindow , monitor . statusWindowThreshold ) ;
269+ // First evaluate reachability-based status changes, which apply to all monitor types
270+ // and take precedence over hardware breaches.
271+ const reachabilityResult = this . computeReachability ( newStatus , projectedWindow , monitor . statusWindowThreshold ) ;
272272 if ( reachabilityResult . transitioned ) {
273273 newStatus = reachabilityResult . nextStatus ;
274274 statusChanged = true ;
@@ -296,21 +296,29 @@ export class StatusService implements IStatusService {
296296 } ,
297297 } ) ;
298298
299- monitor . cpuAlertCounter = hardware . nextCounters . cpu ;
300- monitor . memoryAlertCounter = hardware . nextCounters . memory ;
301- monitor . diskAlertCounter = hardware . nextCounters . disk ;
302- monitor . tempAlertCounter = hardware . nextCounters . temp ;
299+ patch . cpuAlertCounter = hardware . nextCounters . cpu ;
300+ patch . memoryAlertCounter = hardware . nextCounters . memory ;
301+ patch . diskAlertCounter = hardware . nextCounters . disk ;
302+ patch . tempAlertCounter = hardware . nextCounters . temp ;
303303 thresholdBreaches = hardware . breaches ;
304304 if ( hardware . transitioned ) {
305305 newStatus = hardware . nextStatus ;
306306 statusChanged = true ;
307307 }
308308 }
309309
310- // Apply the final status
311- monitor . status = newStatus ;
312-
313- const updated = await this . monitorsRepository . updateById ( monitor . id , monitor . teamId , monitor ) ;
310+ patch . status = newStatus ;
311+
312+ // Single atomic write: push arrays + set status/counters
313+ const updated = await this . monitorsRepository . updateStatusWindowAndChecks (
314+ monitor . id ,
315+ monitor . teamId ,
316+ check . status ,
317+ checkSnapshot ,
318+ monitor . statusWindowSize ,
319+ MAX_RECENT_CHECKS ,
320+ patch
321+ ) ;
314322
315323 return {
316324 monitor : updated ,
0 commit comments