1
1
package agentapi_test
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
5
6
"database/sql"
6
7
"sync"
@@ -19,8 +20,11 @@ import (
19
20
"github.com/coder/coder/v2/coderd/database"
20
21
"github.com/coder/coder/v2/coderd/database/dbmock"
21
22
"github.com/coder/coder/v2/coderd/database/dbtime"
23
+ "github.com/coder/coder/v2/coderd/database/pubsub"
22
24
"github.com/coder/coder/v2/coderd/prometheusmetrics"
23
25
"github.com/coder/coder/v2/coderd/schedule"
26
+ "github.com/coder/coder/v2/codersdk"
27
+ "github.com/coder/coder/v2/testutil"
24
28
)
25
29
26
30
type statsBatcher struct {
@@ -78,8 +82,10 @@ func TestUpdateStates(t *testing.T) {
78
82
t .Parallel ()
79
83
80
84
var (
81
- now = dbtime .Now ()
82
- dbM = dbmock .NewMockStore (gomock .NewController (t ))
85
+ now = dbtime .Now ()
86
+ dbM = dbmock .NewMockStore (gomock .NewController (t ))
87
+ ps = pubsub .NewInMemory ()
88
+
83
89
templateScheduleStore = schedule.MockTemplateScheduleStore {
84
90
GetFn : func (context.Context , database.Store , uuid.UUID ) (schedule.TemplateScheduleOptions , error ) {
85
91
panic ("should not be called" )
@@ -125,6 +131,7 @@ func TestUpdateStates(t *testing.T) {
125
131
return agent , nil
126
132
},
127
133
Database : dbM ,
134
+ Pubsub : ps ,
128
135
StatsBatcher : batcher ,
129
136
TemplateScheduleStore : templateScheduleStorePtr (templateScheduleStore ),
130
137
AgentStatsRefreshInterval : 10 * time .Second ,
@@ -164,6 +171,15 @@ func TestUpdateStates(t *testing.T) {
164
171
// User gets fetched to hit the UpdateAgentMetricsFn.
165
172
dbM .EXPECT ().GetUserByID (gomock .Any (), user .ID ).Return (user , nil )
166
173
174
+ // Ensure that pubsub notifications are sent.
175
+ publishAgentStats := make (chan bool )
176
+ ps .Subscribe (codersdk .WorkspaceNotifyChannel (workspace .ID ), func (_ context.Context , description []byte ) {
177
+ go func () {
178
+ publishAgentStats <- bytes .Equal (description , codersdk .WorkspaceNotifyDescriptionAgentStatsOnly )
179
+ close (publishAgentStats )
180
+ }()
181
+ })
182
+
167
183
resp , err := api .UpdateStats (context .Background (), req )
168
184
require .NoError (t , err )
169
185
require .Equal (t , & agentproto.UpdateStatsResponse {
@@ -179,7 +195,13 @@ func TestUpdateStates(t *testing.T) {
179
195
require .Equal (t , user .ID , batcher .lastUserID )
180
196
require .Equal (t , workspace .ID , batcher .lastWorkspaceID )
181
197
require .Equal (t , req .Stats , batcher .lastStats )
182
-
198
+ ctx := testutil .Context (t , testutil .WaitShort )
199
+ select {
200
+ case <- ctx .Done ():
201
+ t .Error ("timed out while waiting for pubsub notification" )
202
+ case wasAgentStatsOnly := <- publishAgentStats :
203
+ require .Equal (t , wasAgentStatsOnly , true )
204
+ }
183
205
require .True (t , updateAgentMetricsFnCalled )
184
206
})
185
207
@@ -189,6 +211,7 @@ func TestUpdateStates(t *testing.T) {
189
211
var (
190
212
now = dbtime .Now ()
191
213
dbM = dbmock .NewMockStore (gomock .NewController (t ))
214
+ ps = pubsub .NewInMemory ()
192
215
templateScheduleStore = schedule.MockTemplateScheduleStore {
193
216
GetFn : func (context.Context , database.Store , uuid.UUID ) (schedule.TemplateScheduleOptions , error ) {
194
217
panic ("should not be called" )
@@ -214,6 +237,7 @@ func TestUpdateStates(t *testing.T) {
214
237
return agent , nil
215
238
},
216
239
Database : dbM ,
240
+ Pubsub : ps ,
217
241
StatsBatcher : batcher ,
218
242
TemplateScheduleStore : templateScheduleStorePtr (templateScheduleStore ),
219
243
AgentStatsRefreshInterval : 10 * time .Second ,
@@ -244,7 +268,8 @@ func TestUpdateStates(t *testing.T) {
244
268
t .Parallel ()
245
269
246
270
var (
247
- dbM = dbmock .NewMockStore (gomock .NewController (t ))
271
+ db = dbmock .NewMockStore (gomock .NewController (t ))
272
+ ps = pubsub .NewInMemory ()
248
273
req = & agentproto.UpdateStatsRequest {
249
274
Stats : & agentproto.Stats {
250
275
ConnectionsByProto : map [string ]int64 {}, // len() == 0
@@ -255,7 +280,8 @@ func TestUpdateStates(t *testing.T) {
255
280
AgentFn : func (context.Context ) (database.WorkspaceAgent , error ) {
256
281
return agent , nil
257
282
},
258
- Database : dbM ,
283
+ Database : db ,
284
+ Pubsub : ps ,
259
285
StatsBatcher : nil , // should not be called
260
286
TemplateScheduleStore : nil , // should not be called
261
287
AgentStatsRefreshInterval : 10 * time .Second ,
@@ -290,7 +316,9 @@ func TestUpdateStates(t *testing.T) {
290
316
nextAutostart := now .Add (30 * time .Minute ).UTC () // always sent to DB as UTC
291
317
292
318
var (
293
- dbM = dbmock .NewMockStore (gomock .NewController (t ))
319
+ db = dbmock .NewMockStore (gomock .NewController (t ))
320
+ ps = pubsub .NewInMemory ()
321
+
294
322
templateScheduleStore = schedule.MockTemplateScheduleStore {
295
323
GetFn : func (context.Context , database.Store , uuid.UUID ) (schedule.TemplateScheduleOptions , error ) {
296
324
return schedule.TemplateScheduleOptions {
@@ -321,7 +349,8 @@ func TestUpdateStates(t *testing.T) {
321
349
AgentFn : func (context.Context ) (database.WorkspaceAgent , error ) {
322
350
return agent , nil
323
351
},
324
- Database : dbM ,
352
+ Database : db ,
353
+ Pubsub : ps ,
325
354
StatsBatcher : batcher ,
326
355
TemplateScheduleStore : templateScheduleStorePtr (templateScheduleStore ),
327
356
AgentStatsRefreshInterval : 15 * time .Second ,
@@ -341,26 +370,26 @@ func TestUpdateStates(t *testing.T) {
341
370
}
342
371
343
372
// Workspace gets fetched.
344
- dbM .EXPECT ().GetWorkspaceByAgentID (gomock .Any (), agent .ID ).Return (database.GetWorkspaceByAgentIDRow {
373
+ db .EXPECT ().GetWorkspaceByAgentID (gomock .Any (), agent .ID ).Return (database.GetWorkspaceByAgentIDRow {
345
374
Workspace : workspace ,
346
375
TemplateName : template .Name ,
347
376
}, nil )
348
377
349
378
// We expect an activity bump because ConnectionCount > 0. However, the
350
379
// next autostart time will be set on the bump.
351
- dbM .EXPECT ().ActivityBumpWorkspace (gomock .Any (), database.ActivityBumpWorkspaceParams {
380
+ db .EXPECT ().ActivityBumpWorkspace (gomock .Any (), database.ActivityBumpWorkspaceParams {
352
381
WorkspaceID : workspace .ID ,
353
382
NextAutostart : nextAutostart ,
354
383
}).Return (nil )
355
384
356
385
// Workspace last used at gets bumped.
357
- dbM .EXPECT ().UpdateWorkspaceLastUsedAt (gomock .Any (), database.UpdateWorkspaceLastUsedAtParams {
386
+ db .EXPECT ().UpdateWorkspaceLastUsedAt (gomock .Any (), database.UpdateWorkspaceLastUsedAtParams {
358
387
ID : workspace .ID ,
359
388
LastUsedAt : now ,
360
389
}).Return (nil )
361
390
362
391
// User gets fetched to hit the UpdateAgentMetricsFn.
363
- dbM .EXPECT ().GetUserByID (gomock .Any (), user .ID ).Return (user , nil )
392
+ db .EXPECT ().GetUserByID (gomock .Any (), user .ID ).Return (user , nil )
364
393
365
394
resp , err := api .UpdateStats (context .Background (), req )
366
395
require .NoError (t , err )
0 commit comments