@@ -49,16 +49,20 @@ func newMetricsCache(t *testing.T, log slog.Logger, clock quartz.Clock, interval
49
49
50
50
func TestCache_TemplateWorkspaceOwners (t * testing.T ) {
51
51
t .Parallel ()
52
- var ()
53
52
54
53
var (
55
- log = testutil .Logger (t )
56
- clock = quartz .NewReal ()
57
- cache ,db = newMetricsCache (t ,log ,clock , metricscache.Intervals {
58
- TemplateBuildTimes :testutil .IntervalFast ,
59
- },false )
54
+ ctx = testutil .Context (t ,testutil .WaitShort )
55
+ log = testutil .Logger (t )
56
+ clock = quartz .NewMock (t )
60
57
)
61
58
59
+ trapTickerFunc := clock .Trap ().TickerFunc ("metricscache" )
60
+ defer trapTickerFunc .Close ()
61
+
62
+ cache ,db := newMetricsCache (t ,log ,clock , metricscache.Intervals {
63
+ TemplateBuildTimes :time .Minute ,
64
+ },false )
65
+
62
66
org := dbgen .Organization (t ,db , database.Organization {})
63
67
user1 := dbgen .User (t ,db , database.User {})
64
68
user2 := dbgen .User (t ,db , database.User {})
@@ -67,38 +71,38 @@ func TestCache_TemplateWorkspaceOwners(t *testing.T) {
67
71
Provisioner :database .ProvisionerTypeEcho ,
68
72
CreatedBy :user1 .ID ,
69
73
})
70
- require .Eventuallyf (t ,func ()bool {
71
- count ,ok := cache .TemplateWorkspaceOwners (template .ID )
72
- return ok && count == 0
73
- },testutil .WaitShort ,testutil .IntervalMedium ,
74
- "TemplateWorkspaceOwners never populated 0 owners" ,
75
- )
74
+
75
+ // Wait for both ticker functions to be created (template build times and deployment stats)
76
+ trapTickerFunc .MustWait (ctx ).MustRelease (ctx )
77
+ trapTickerFunc .MustWait (ctx ).MustRelease (ctx )
78
+
79
+ clock .Advance (time .Minute ).MustWait (ctx )
80
+
81
+ count ,ok := cache .TemplateWorkspaceOwners (template .ID )
82
+ require .True (t ,ok ,"TemplateWorkspaceOwners should be populated" )
83
+ require .Equal (t ,0 ,count ,"should have 0 owners initially" )
76
84
77
85
dbgen .Workspace (t ,db , database.WorkspaceTable {
78
86
OrganizationID :org .ID ,
79
87
TemplateID :template .ID ,
80
88
OwnerID :user1 .ID ,
81
89
})
82
90
83
- require .Eventuallyf (t ,func ()bool {
84
- count ,_ := cache .TemplateWorkspaceOwners (template .ID )
85
- return count == 1
86
- },testutil .WaitShort ,testutil .IntervalMedium ,
87
- "TemplateWorkspaceOwners never populated 1 owner" ,
88
- )
91
+ clock .Advance (time .Minute ).MustWait (ctx )
92
+
93
+ count ,_ = cache .TemplateWorkspaceOwners (template .ID )
94
+ require .Equal (t ,1 ,count ,"should have 1 owner after adding workspace" )
89
95
90
96
workspace2 := dbgen .Workspace (t ,db , database.WorkspaceTable {
91
97
OrganizationID :org .ID ,
92
98
TemplateID :template .ID ,
93
99
OwnerID :user2 .ID ,
94
100
})
95
101
96
- require .Eventuallyf (t ,func ()bool {
97
- count ,_ := cache .TemplateWorkspaceOwners (template .ID )
98
- return count == 2
99
- },testutil .WaitShort ,testutil .IntervalMedium ,
100
- "TemplateWorkspaceOwners never populated 2 owners" ,
101
- )
102
+ clock .Advance (time .Minute ).MustWait (ctx )
103
+
104
+ count ,_ = cache .TemplateWorkspaceOwners (template .ID )
105
+ require .Equal (t ,2 ,count ,"should have 2 owners after adding second workspace" )
102
106
103
107
// 3rd workspace should not be counted since we have the same owner as workspace2.
104
108
dbgen .Workspace (t ,db , database.WorkspaceTable {
@@ -112,12 +116,10 @@ func TestCache_TemplateWorkspaceOwners(t *testing.T) {
112
116
Deleted :true ,
113
117
})
114
118
115
- require .Eventuallyf (t ,func ()bool {
116
- count ,_ := cache .TemplateWorkspaceOwners (template .ID )
117
- return count == 1
118
- },testutil .WaitShort ,testutil .IntervalMedium ,
119
- "TemplateWorkspaceOwners never populated 1 owner after delete" ,
120
- )
119
+ clock .Advance (time .Minute ).MustWait (ctx )
120
+
121
+ count ,_ = cache .TemplateWorkspaceOwners (template .ID )
122
+ require .Equal (t ,1 ,count ,"should have 1 owner after deleting workspace" )
121
123
}
122
124
123
125
func clockTime (t time.Time ,hour ,minute ,sec int ) time.Time {
@@ -206,15 +208,20 @@ func TestCache_BuildTime(t *testing.T) {
206
208
t .Parallel ()
207
209
208
210
var (
209
- log = testutil .Logger (t )
210
- clock = quartz .NewMock (t )
211
- cache ,db = newMetricsCache (t ,log ,clock , metricscache.Intervals {
212
- TemplateBuildTimes :testutil .IntervalFast ,
213
- },false )
211
+ ctx = testutil .Context (t ,testutil .WaitShort )
212
+ log = testutil .Logger (t )
213
+ clock = quartz .NewMock (t )
214
214
)
215
215
216
216
clock .Set (someDay )
217
217
218
+ trapTickerFunc := clock .Trap ().TickerFunc ("metricscache" )
219
+
220
+ defer trapTickerFunc .Close ()
221
+ cache ,db := newMetricsCache (t ,log ,clock , metricscache.Intervals {
222
+ TemplateBuildTimes :time .Minute ,
223
+ },false )
224
+
218
225
org := dbgen .Organization (t ,db , database.Organization {})
219
226
user := dbgen .User (t ,db , database.User {})
220
227
@@ -257,17 +264,19 @@ func TestCache_BuildTime(t *testing.T) {
257
264
})
258
265
}
259
266
267
+ // Wait for both ticker functions to be created (template build times and deployment stats)
268
+ trapTickerFunc .MustWait (ctx ).MustRelease (ctx )
269
+ trapTickerFunc .MustWait (ctx ).MustRelease (ctx )
270
+
271
+ clock .Advance (time .Minute ).MustWait (ctx )
272
+
260
273
if tt .want .loads {
261
274
wantTransition := codersdk .WorkspaceTransition (tt .args .transition )
262
- require .Eventuallyf (t ,func ()bool {
263
- stats := cache .TemplateBuildTimeStats (template .ID )
264
- ts := stats [wantTransition ]
265
- return ts .P50 != nil && * ts .P50 == tt .want .buildTimeMs
266
- },testutil .WaitLong ,testutil .IntervalMedium ,
267
- "P50 never reached expected value for %v" ,wantTransition ,
268
- )
269
-
270
275
gotStats := cache .TemplateBuildTimeStats (template .ID )
276
+ ts := gotStats [wantTransition ]
277
+ require .NotNil (t ,ts .P50 ,"P50 should be set for %v" ,wantTransition )
278
+ require .Equal (t ,tt .want .buildTimeMs ,* ts .P50 ,"P50 should match expected value for %v" ,wantTransition )
279
+
271
280
for transition ,ts := range gotStats {
272
281
if transition == wantTransition {
273
282
// Checked above
@@ -276,14 +285,8 @@ func TestCache_BuildTime(t *testing.T) {
276
285
require .Empty (t ,ts ,"%v" ,transition )
277
286
}
278
287
}else {
279
- var stats codersdk.TemplateBuildTimeStats
280
- require .Never (t ,func ()bool {
281
- stats = cache .TemplateBuildTimeStats (template .ID )
282
- requireBuildTimeStatsEmpty (t ,stats )
283
- return t .Failed ()
284
- },testutil .WaitShort / 2 ,testutil .IntervalMedium ,
285
- "BuildTimeStats populated" ,stats ,
286
- )
288
+ stats := cache .TemplateBuildTimeStats (template .ID )
289
+ requireBuildTimeStatsEmpty (t ,stats )
287
290
}
288
291
})
289
292
}
@@ -293,13 +296,18 @@ func TestCache_DeploymentStats(t *testing.T) {
293
296
t .Parallel ()
294
297
295
298
var (
296
- log = testutil .Logger (t )
297
- clock = quartz .NewMock (t )
298
- cache ,db = newMetricsCache (t ,log ,clock , metricscache.Intervals {
299
- DeploymentStats :testutil .IntervalFast ,
300
- },false )
299
+ ctx = testutil .Context (t ,testutil .WaitShort )
300
+ log = testutil .Logger (t )
301
+ clock = quartz .NewMock (t )
301
302
)
302
303
304
+ tickerTrap := clock .Trap ().TickerFunc ("metricscache" )
305
+ defer tickerTrap .Close ()
306
+
307
+ cache ,db := newMetricsCache (t ,log ,clock , metricscache.Intervals {
308
+ DeploymentStats :time .Minute ,
309
+ },false )
310
+
303
311
err := db .InsertWorkspaceAgentStats (context .Background (), database.InsertWorkspaceAgentStatsParams {
304
312
ID : []uuid.UUID {uuid .New ()},
305
313
CreatedAt : []time.Time {clock .Now ()},
@@ -323,11 +331,13 @@ func TestCache_DeploymentStats(t *testing.T) {
323
331
})
324
332
require .NoError (t ,err )
325
333
326
- var stat codersdk.DeploymentStats
327
- require .Eventually (t ,func ()bool {
328
- var ok bool
329
- stat ,ok = cache .DeploymentStats ()
330
- return ok
331
- },testutil .WaitLong ,testutil .IntervalMedium )
334
+ // Wait for both ticker functions to be created (template build times and deployment stats)
335
+ tickerTrap .MustWait (ctx ).MustRelease (ctx )
336
+ tickerTrap .MustWait (ctx ).MustRelease (ctx )
337
+
338
+ clock .Advance (time .Minute ).MustWait (ctx )
339
+
340
+ stat ,ok := cache .DeploymentStats ()
341
+ require .True (t ,ok ,"cache should be populated after refresh" )
332
342
require .Equal (t ,int64 (1 ),stat .SessionCount .VSCode )
333
343
}