(ctx context.Context, datapoints []*proto.PushResourcesMonitoringUsageRequest_Datapoint)
| 110 | } |
| 111 | |
| 112 | func (a *ResourcesMonitoringAPI) monitorMemory(ctx context.Context, datapoints []*proto.PushResourcesMonitoringUsageRequest_Datapoint) error { |
| 113 | if !a.memoryMonitor.Enabled { |
| 114 | return nil |
| 115 | } |
| 116 | |
| 117 | usageDatapoints := make([]*proto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage, 0, len(datapoints)) |
| 118 | for _, datapoint := range datapoints { |
| 119 | usageDatapoints = append(usageDatapoints, datapoint.Memory) |
| 120 | } |
| 121 | |
| 122 | usageStates := resourcesmonitor.CalculateMemoryUsageStates(a.memoryMonitor, usageDatapoints) |
| 123 | |
| 124 | oldState := a.memoryMonitor.State |
| 125 | newState := resourcesmonitor.NextState(a.Config, oldState, usageStates) |
| 126 | |
| 127 | debouncedUntil, shouldNotify := a.memoryMonitor.Debounce(a.Debounce, a.Clock.Now(), oldState, newState) |
| 128 | |
| 129 | //nolint:gocritic // We need to be able to update the resource monitor here. |
| 130 | err := a.Database.UpdateMemoryResourceMonitor(dbauthz.AsResourceMonitor(ctx), database.UpdateMemoryResourceMonitorParams{ |
| 131 | AgentID: a.AgentID, |
| 132 | State: newState, |
| 133 | UpdatedAt: dbtime.Time(a.Clock.Now()), |
| 134 | DebouncedUntil: dbtime.Time(debouncedUntil), |
| 135 | }) |
| 136 | if err != nil { |
| 137 | return xerrors.Errorf("update workspace monitor: %w", err) |
| 138 | } |
| 139 | |
| 140 | // Update cached state |
| 141 | a.memoryMonitor.State = newState |
| 142 | a.memoryMonitor.DebouncedUntil = dbtime.Time(debouncedUntil) |
| 143 | a.memoryMonitor.UpdatedAt = dbtime.Time(a.Clock.Now()) |
| 144 | |
| 145 | if !shouldNotify { |
| 146 | return nil |
| 147 | } |
| 148 | |
| 149 | workspace, err := a.Database.GetWorkspaceByID(ctx, a.WorkspaceID) |
| 150 | if err != nil { |
| 151 | return xerrors.Errorf("get workspace by id: %w", err) |
| 152 | } |
| 153 | |
| 154 | _, err = a.NotificationsEnqueuer.EnqueueWithData( |
| 155 | // nolint:gocritic // We need to be able to send the notification. |
| 156 | dbauthz.AsNotifier(ctx), |
| 157 | workspace.OwnerID, |
| 158 | notifications.TemplateWorkspaceOutOfMemory, |
| 159 | map[string]string{ |
| 160 | "workspace": workspace.Name, |
| 161 | "threshold": fmt.Sprintf("%d%%", a.memoryMonitor.Threshold), |
| 162 | }, |
| 163 | map[string]any{ |
| 164 | // NOTE(DanielleMaywood): |
| 165 | // When notifications are enqueued, they are checked to be |
| 166 | // unique within a single day. This means that if we attempt |
| 167 | // to send two OOM notifications for the same workspace on |
| 168 | // the same day, the enqueuer will prevent us from sending |
| 169 | // a second one. We are inject a timestamp to make the |
no test coverage detected