@@ -256,6 +256,9 @@ func (c *StoreReconciler) ReconcileAll(ctx context.Context) error {
256
256
if err != nil {
257
257
return xerrors .Errorf ("determine current snapshot: %w" , err )
258
258
}
259
+
260
+ c .reportHardLimitedPresets (snapshot )
261
+
259
262
if len (snapshot .Presets ) == 0 {
260
263
logger .Debug (ctx , "no templates found with prebuilds configured" )
261
264
return nil
@@ -296,6 +299,41 @@ func (c *StoreReconciler) ReconcileAll(ctx context.Context) error {
296
299
return err
297
300
}
298
301
302
+ func (c * StoreReconciler ) reportHardLimitedPresets (snapshot * prebuilds.GlobalSnapshot ) {
303
+ // presetsMap is a map from key (orgName:templateName:presetName) to list of corresponding presets.
304
+ // Multiple versions of a preset can exist with the same orgName, templateName, and presetName,
305
+ // because templates can have multiple versions — or deleted templates can share the same name.
306
+ presetsMap := make (map [hardLimitedPresetKey ][]database.GetTemplatePresetsWithPrebuildsRow )
307
+ for _ , preset := range snapshot .Presets {
308
+ key := hardLimitedPresetKey {
309
+ orgName : preset .OrganizationName ,
310
+ templateName : preset .TemplateName ,
311
+ presetName : preset .Name ,
312
+ }
313
+
314
+ presetsMap [key ] = append (presetsMap [key ], preset )
315
+ }
316
+
317
+ // Report a preset as hard-limited only if all the following conditions are met:
318
+ // - The preset is marked as hard-limited
319
+ // - The preset is using the active version of its template, and the template has not been deleted
320
+ //
321
+ // The second condition is important because a hard-limited preset that has become outdated is no longer relevant.
322
+ // Its associated prebuilt workspaces were likely deleted, and it's not meaningful to continue reporting it
323
+ // as hard-limited to the admin.
324
+ isPresetHardLimited := make (map [hardLimitedPresetKey ]bool )
325
+ for key , presets := range presetsMap {
326
+ for _ , preset := range presets {
327
+ if preset .UsingActiveVersion && ! preset .Deleted && snapshot .IsHardLimited (preset .ID ) {
328
+ isPresetHardLimited [key ] = true
329
+ break
330
+ }
331
+ }
332
+ }
333
+
334
+ c .metrics .registerHardLimitedPresets (isPresetHardLimited )
335
+ }
336
+
299
337
// SnapshotState captures the current state of all prebuilds across templates.
300
338
func (c * StoreReconciler ) SnapshotState (ctx context.Context , store database.Store ) (* prebuilds.GlobalSnapshot , error ) {
301
339
if err := ctx .Err (); err != nil {
@@ -361,24 +399,6 @@ func (c *StoreReconciler) ReconcilePreset(ctx context.Context, ps prebuilds.Pres
361
399
slog .F ("preset_name" , ps .Preset .Name ),
362
400
)
363
401
364
- // Report a metric only if the preset uses the latest version of the template and the template is not deleted.
365
- // This avoids conflicts between metrics from old and new template versions.
366
- //
367
- // NOTE: Multiple versions of a preset can exist with the same orgName, templateName, and presetName,
368
- // because templates can have multiple versions — or deleted templates can share the same name.
369
- //
370
- // The safest approach is to report the metric only for the latest version of the preset.
371
- // When a new template version is released, the metric for the new preset should overwrite
372
- // the old value in Prometheus.
373
- //
374
- // However, there’s one edge case: if an admin creates a template, it becomes hard-limited,
375
- // then deletes the template and never creates another with the same name,
376
- // the old preset will continue to be reported as hard-limited —
377
- // even though it’s deleted. This will persist until `coderd` is restarted.
378
- if ps .Preset .UsingActiveVersion && ! ps .Preset .Deleted {
379
- c .metrics .trackHardLimitedStatus (ps .Preset .OrganizationName , ps .Preset .TemplateName , ps .Preset .Name , ps .IsHardLimited )
380
- }
381
-
382
402
// If the preset reached the hard failure limit for the first time during this iteration:
383
403
// - Mark it as hard-limited in the database
384
404
// - Send notifications to template admins
0 commit comments