@@ -317,6 +317,104 @@ func TestMemoryResourceMonitor(t *testing.T) {
317317 }
318318}
319319
320+ func TestMemoryResourceMonitorMissingData (t * testing.T ) {
321+ t .Parallel ()
322+
323+ t .Run ("UnknownPreventsMovingIntoAlertState" , func (t * testing.T ) {
324+ t .Parallel ()
325+
326+ api , _ , clock , notifyEnq := resourceMonitorAPI (t )
327+ api .ConsecutiveNOKsToAlert = 2
328+ api .MinimumNOKsToAlert = 10
329+
330+ // Given: A monitor in an OK state.
331+ dbgen .WorkspaceAgentMemoryResourceMonitor (t , api .Database , database.WorkspaceAgentMemoryResourceMonitor {
332+ AgentID : api .AgentID ,
333+ State : database .WorkspaceAgentMonitorStateOK ,
334+ Threshold : 80 ,
335+ })
336+
337+ // When: A datapoint is missing, surrounded by two NOK datapoints.
338+ _ , err := api .PushResourcesMonitoringUsage (context .Background (), & agentproto.PushResourcesMonitoringUsageRequest {
339+ Datapoints : []* agentproto.PushResourcesMonitoringUsageRequest_Datapoint {
340+ {
341+ CollectedAt : timestamppb .New (clock .Now ()),
342+ Memory : & agentproto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage {
343+ Used : 10 ,
344+ Total : 10 ,
345+ },
346+ },
347+ {
348+ CollectedAt : timestamppb .New (clock .Now ().Add (10 * time .Second )),
349+ Memory : nil ,
350+ },
351+ {
352+ CollectedAt : timestamppb .New (clock .Now ().Add (20 * time .Second )),
353+ Memory : & agentproto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage {
354+ Used : 10 ,
355+ Total : 10 ,
356+ },
357+ },
358+ },
359+ })
360+ require .NoError (t , err )
361+
362+ // Then: We expect no notifications, as this unknown prevents us knowing we should alert.
363+ sent := notifyEnq .Sent (notificationstest .WithTemplateID (notifications .TemplateWorkspaceOutOfMemory ))
364+ require .Len (t , sent , 0 )
365+
366+ // Then: We expect the monitor to still be in an OK state.
367+ monitor , err := api .Database .FetchMemoryResourceMonitorsByAgentID (context .Background (), api .AgentID )
368+ require .NoError (t , err )
369+ require .Equal (t , database .WorkspaceAgentMonitorStateOK , monitor .State )
370+ })
371+
372+ t .Run ("UnknownPreventsMovingOutOfAlertState" , func (t * testing.T ) {
373+ t .Parallel ()
374+
375+ api , _ , clock , _ := resourceMonitorAPI (t )
376+ api .ConsecutiveNOKsToAlert = 2
377+ api .MinimumNOKsToAlert = 10
378+
379+ // Given: A monitor in a NOK state.
380+ dbgen .WorkspaceAgentMemoryResourceMonitor (t , api .Database , database.WorkspaceAgentMemoryResourceMonitor {
381+ AgentID : api .AgentID ,
382+ State : database .WorkspaceAgentMonitorStateNOK ,
383+ Threshold : 80 ,
384+ })
385+
386+ // When: A datapoint is missing, surrounded by two OK datapoints.
387+ _ , err := api .PushResourcesMonitoringUsage (context .Background (), & agentproto.PushResourcesMonitoringUsageRequest {
388+ Datapoints : []* agentproto.PushResourcesMonitoringUsageRequest_Datapoint {
389+ {
390+ CollectedAt : timestamppb .New (clock .Now ()),
391+ Memory : & agentproto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage {
392+ Used : 1 ,
393+ Total : 10 ,
394+ },
395+ },
396+ {
397+ CollectedAt : timestamppb .New (clock .Now ().Add (10 * time .Second )),
398+ Memory : nil ,
399+ },
400+ {
401+ CollectedAt : timestamppb .New (clock .Now ().Add (20 * time .Second )),
402+ Memory : & agentproto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage {
403+ Used : 1 ,
404+ Total : 10 ,
405+ },
406+ },
407+ },
408+ })
409+ require .NoError (t , err )
410+
411+ // Then: We expect the monitor to still be in a NOK state.
412+ monitor , err := api .Database .FetchMemoryResourceMonitorsByAgentID (context .Background (), api .AgentID )
413+ require .NoError (t , err )
414+ require .Equal (t , database .WorkspaceAgentMonitorStateNOK , monitor .State )
415+ })
416+ }
417+
320418func TestVolumeResourceMonitorDebounce (t * testing.T ) {
321419 t .Parallel ()
322420
0 commit comments