@@ -72,7 +72,8 @@ func TestNoReconciliationActionsIfNoPresets(t *testing.T) {
7272 require .Equal (t , templateVersion , gotTemplateVersion )
7373
7474 // when we trigger the reconciliation loop for all templates
75- require .NoError (t , controller .ReconcileAll (ctx ))
75+ _ , err = controller .ReconcileAll (ctx )
76+ require .NoError (t , err )
7677
7778 // then no reconciliation actions are taken
7879 // because without presets, there are no prebuilds
@@ -126,7 +127,8 @@ func TestNoReconciliationActionsIfNoPrebuilds(t *testing.T) {
126127 require .NotEmpty (t , presetParameters )
127128
128129 // when we trigger the reconciliation loop for all templates
129- require .NoError (t , controller .ReconcileAll (ctx ))
130+ _ , err = controller .ReconcileAll (ctx )
131+ require .NoError (t , err )
130132
131133 // then no reconciliation actions are taken
132134 // because without prebuilds, there is nothing to reconcile
@@ -428,7 +430,8 @@ func (tc testCase) run(t *testing.T) {
428430 // Run the reconciliation multiple times to ensure idempotency
429431 // 8 was arbitrary, but large enough to reasonably trust the result
430432 for i := 1 ; i <= 8 ; i ++ {
431- require .NoErrorf (t , controller .ReconcileAll (ctx ), "failed on iteration %d" , i )
433+ _ , err := controller .ReconcileAll (ctx )
434+ require .NoErrorf (t , err , "failed on iteration %d" , i )
432435
433436 if tc .shouldCreateNewPrebuild != nil {
434437 newPrebuildCount := 0
@@ -542,7 +545,8 @@ func TestMultiplePresetsPerTemplateVersion(t *testing.T) {
542545 // Run the reconciliation multiple times to ensure idempotency
543546 // 8 was arbitrary, but large enough to reasonably trust the result
544547 for i := 1 ; i <= 8 ; i ++ {
545- require .NoErrorf (t , controller .ReconcileAll (ctx ), "failed on iteration %d" , i )
548+ _ , err := controller .ReconcileAll (ctx )
549+ require .NoErrorf (t , err , "failed on iteration %d" , i )
546550
547551 newPrebuildCount := 0
548552 workspaces , err := db .GetWorkspacesByTemplateID (ctx , template .ID )
@@ -668,7 +672,7 @@ func TestPrebuildScheduling(t *testing.T) {
668672 DesiredInstances : 5 ,
669673 })
670674
671- err := controller .ReconcileAll (ctx )
675+ _ , err := controller .ReconcileAll (ctx )
672676 require .NoError (t , err )
673677
674678 // get workspace builds
@@ -751,7 +755,8 @@ func TestInvalidPreset(t *testing.T) {
751755 // Run the reconciliation multiple times to ensure idempotency
752756 // 8 was arbitrary, but large enough to reasonably trust the result
753757 for i := 1 ; i <= 8 ; i ++ {
754- require .NoErrorf (t , controller .ReconcileAll (ctx ), "failed on iteration %d" , i )
758+ _ , err := controller .ReconcileAll (ctx )
759+ require .NoErrorf (t , err , "failed on iteration %d" , i )
755760
756761 workspaces , err := db .GetWorkspacesByTemplateID (ctx , template .ID )
757762 require .NoError (t , err )
@@ -817,7 +822,8 @@ func TestDeletionOfPrebuiltWorkspaceWithInvalidPreset(t *testing.T) {
817822 })
818823
819824 // Old prebuilt workspace should be deleted.
820- require .NoError (t , controller .ReconcileAll (ctx ))
825+ _ , err = controller .ReconcileAll (ctx )
826+ require .NoError (t , err )
821827
822828 builds , err := db .GetWorkspaceBuildsByWorkspaceID (ctx , database.GetWorkspaceBuildsByWorkspaceIDParams {
823829 WorkspaceID : prebuiltWorkspace .ID ,
@@ -916,12 +922,15 @@ func TestSkippingHardLimitedPresets(t *testing.T) {
916922
917923 // Trigger reconciliation to attempt creating a new prebuild.
918924 // The outcome depends on whether the hard limit has been reached.
919- require .NoError (t , controller .ReconcileAll (ctx ))
925+ _ , err = controller .ReconcileAll (ctx )
926+ require .NoError (t , err )
920927
921928 // These two additional calls to ReconcileAll should not trigger any notifications.
922929 // A notification is only sent once.
923- require .NoError (t , controller .ReconcileAll (ctx ))
924- require .NoError (t , controller .ReconcileAll (ctx ))
930+ _ , err = controller .ReconcileAll (ctx )
931+ require .NoError (t , err )
932+ _ , err = controller .ReconcileAll (ctx )
933+ require .NoError (t , err )
925934
926935 // Verify the final state after reconciliation.
927936 workspaces , err = db .GetWorkspacesByTemplateID (ctx , template .ID )
@@ -1093,12 +1102,15 @@ func TestHardLimitedPresetShouldNotBlockDeletion(t *testing.T) {
10931102
10941103 // Trigger reconciliation to attempt creating a new prebuild.
10951104 // The outcome depends on whether the hard limit has been reached.
1096- require .NoError (t , controller .ReconcileAll (ctx ))
1105+ _ , err = controller .ReconcileAll (ctx )
1106+ require .NoError (t , err )
10971107
10981108 // These two additional calls to ReconcileAll should not trigger any notifications.
10991109 // A notification is only sent once.
1100- require .NoError (t , controller .ReconcileAll (ctx ))
1101- require .NoError (t , controller .ReconcileAll (ctx ))
1110+ _ , err = controller .ReconcileAll (ctx )
1111+ require .NoError (t , err )
1112+ _ , err = controller .ReconcileAll (ctx )
1113+ require .NoError (t , err )
11021114
11031115 // Verify the final state after reconciliation.
11041116 // When hard limit is reached, no new workspace should be created.
@@ -1141,7 +1153,8 @@ func TestHardLimitedPresetShouldNotBlockDeletion(t *testing.T) {
11411153 }
11421154
11431155 // Trigger reconciliation to make sure that successful, but outdated prebuilt workspace will be deleted.
1144- require .NoError (t , controller .ReconcileAll (ctx ))
1156+ _ , err = controller .ReconcileAll (ctx )
1157+ require .NoError (t , err )
11451158
11461159 workspaces , err = db .GetWorkspacesByTemplateID (ctx , template .ID )
11471160 require .NoError (t , err )
@@ -1740,7 +1753,8 @@ func TestExpiredPrebuildsMultipleActions(t *testing.T) {
17401753 }
17411754
17421755 // Trigger reconciliation to process expired prebuilds and enforce desired state.
1743- require .NoError (t , controller .ReconcileAll (ctx ))
1756+ _ , err = controller .ReconcileAll (ctx )
1757+ require .NoError (t , err )
17441758
17451759 // Sort non-expired workspaces by CreatedAt in ascending order (oldest first)
17461760 sort .Slice (nonExpiredWorkspaces , func (i , j int ) bool {
@@ -2145,7 +2159,8 @@ func TestCancelPendingPrebuilds(t *testing.T) {
21452159 require .NoError (t , err )
21462160
21472161 // When: the reconciliation loop is triggered
2148- require .NoError (t , reconciler .ReconcileAll (ctx ))
2162+ _ , err = reconciler .ReconcileAll (ctx )
2163+ require .NoError (t , err )
21492164
21502165 if tt .shouldCancel {
21512166 // Then: the pending prebuild job from non-active version should be canceled
@@ -2347,7 +2362,8 @@ func TestCancelPendingPrebuilds(t *testing.T) {
23472362 templateBVersion3Pending := setupPrebuilds (t , db , owner .OrganizationID , templateBID , templateBVersion3ID , templateBVersion3PresetID , 1 , true )
23482363
23492364 // When: the reconciliation loop is executed
2350- require .NoError (t , reconciler .ReconcileAll (ctx ))
2365+ _ , err := reconciler .ReconcileAll (ctx )
2366+ require .NoError (t , err )
23512367
23522368 // Then: template A version 1 running workspaces should not be canceled
23532369 checkIfJobCanceledAndDeleted (t , clock , ctx , db , false , templateAVersion1Running )
@@ -2369,6 +2385,51 @@ func TestCancelPendingPrebuilds(t *testing.T) {
23692385 })
23702386}
23712387
2388+ func TestReconciliationStats (t * testing.T ) {
2389+ t .Parallel ()
2390+
2391+ // Setup
2392+ clock := quartz .NewReal ()
2393+ db , ps := dbtestutil .NewDB (t )
2394+ client , _ , _ := coderdtest .NewWithAPI (t , & coderdtest.Options {
2395+ Database : db ,
2396+ Pubsub : ps ,
2397+ Clock : clock ,
2398+ })
2399+ fakeEnqueuer := newFakeEnqueuer ()
2400+ registry := prometheus .NewRegistry ()
2401+ cache := files .New (registry , & coderdtest.FakeAuthorizer {})
2402+ logger := slogtest .Make (t , & slogtest.Options {IgnoreErrors : false }).Leveled (slog .LevelDebug )
2403+ reconciler := prebuilds .NewStoreReconciler (db , ps , cache , codersdk.PrebuildsConfig {}, logger , clock , registry , fakeEnqueuer , newNoopUsageCheckerPtr ())
2404+ owner := coderdtest .CreateFirstUser (t , client )
2405+
2406+ ctx , cancel := context .WithTimeout (context .Background (), testutil .WaitShort )
2407+ defer cancel ()
2408+
2409+ // Create a template version with a preset
2410+ dbfake .TemplateVersion (t , db ).Seed (database.TemplateVersion {
2411+ OrganizationID : owner .OrganizationID ,
2412+ CreatedBy : owner .UserID ,
2413+ }).Preset (database.TemplateVersionPreset {
2414+ DesiredInstances : sql.NullInt32 {
2415+ Int32 : 1 ,
2416+ Valid : true ,
2417+ },
2418+ }).Do ()
2419+
2420+ // Verify that ReconcileAll tracks and returns elapsed time
2421+ start := time .Now ()
2422+ stats , err := reconciler .ReconcileAll (ctx )
2423+ actualElapsed := time .Since (start )
2424+ require .NoError (t , err )
2425+ require .Greater (t , stats .Elapsed , time .Duration (0 ))
2426+
2427+ // Verify stats.Elapsed matches actual execution time
2428+ require .InDelta (t , actualElapsed .Milliseconds (), stats .Elapsed .Milliseconds (), 100 )
2429+ // Verify reconciliation loop is not unexpectedly slow
2430+ require .Less (t , stats .Elapsed , 5 * time .Second )
2431+ }
2432+
23722433func newNoopEnqueuer () * notifications.NoopEnqueuer {
23732434 return notifications .NewNoopEnqueuer ()
23742435}
@@ -2863,7 +2924,7 @@ func TestReconciliationRespectsPauseSetting(t *testing.T) {
28632924 _ = setupTestDBPreset (t , db , templateVersionID , 2 , "test" )
28642925
28652926 // Initially, reconciliation should create prebuilds
2866- err := reconciler .ReconcileAll (ctx )
2927+ _ , err := reconciler .ReconcileAll (ctx )
28672928 require .NoError (t , err )
28682929
28692930 // Verify that prebuilds were created
@@ -2890,7 +2951,7 @@ func TestReconciliationRespectsPauseSetting(t *testing.T) {
28902951 require .Len (t , workspaces , 0 , "prebuilds should be deleted" )
28912952
28922953 // Run reconciliation again - it should be paused and not recreate prebuilds
2893- err = reconciler .ReconcileAll (ctx )
2954+ _ , err = reconciler .ReconcileAll (ctx )
28942955 require .NoError (t , err )
28952956
28962957 // Verify that no new prebuilds were created because reconciliation is paused
@@ -2903,7 +2964,7 @@ func TestReconciliationRespectsPauseSetting(t *testing.T) {
29032964 require .NoError (t , err )
29042965
29052966 // Run reconciliation again - it should now recreate the prebuilds
2906- err = reconciler .ReconcileAll (ctx )
2967+ _ , err = reconciler .ReconcileAll (ctx )
29072968 require .NoError (t , err )
29082969
29092970 // Verify that prebuilds were recreated
0 commit comments