5
5
"io"
6
6
"net/http"
7
7
"strings"
8
+ "sync"
8
9
9
10
"golang.org/x/xerrors"
10
11
@@ -61,84 +62,141 @@ type Deps struct {
61
62
}
62
63
63
64
func DeploymentInfo (ctx context.Context , client * codersdk.Client , log slog.Logger ) Deployment {
64
- var d Deployment
65
-
66
- bi , err := client .BuildInfo (ctx )
67
- if err != nil {
68
- log .Error (ctx , "fetch build info" , slog .Error (err ))
69
- } else {
65
+ var (
66
+ d Deployment
67
+ m sync.Mutex
68
+ wg sync.WaitGroup
69
+ )
70
+
71
+ wg .Add (1 )
72
+ go func () {
73
+ defer wg .Done ()
74
+ bi , err := client .BuildInfo (ctx )
75
+ if err != nil {
76
+ log .Error (ctx , "fetch build info" , slog .Error (err ))
77
+ return
78
+ }
79
+ m .Lock ()
70
80
d .BuildInfo = & bi
71
- }
81
+ m .Unlock ()
82
+ }()
72
83
73
- dc , err := client .DeploymentConfig (ctx )
74
- if err != nil {
75
- log .Error (ctx , "fetch deployment config" , slog .Error (err ))
76
- } else {
84
+ wg .Add (1 )
85
+ go func () {
86
+ defer wg .Done ()
87
+ dc , err := client .DeploymentConfig (ctx )
88
+ if err != nil {
89
+ log .Error (ctx , "fetch deployment config" , slog .Error (err ))
90
+ return
91
+ }
92
+ m .Lock ()
77
93
d .Config = dc
78
- }
94
+ m .Unlock ()
95
+ }()
79
96
80
- hr , err := client .DebugHealth (ctx )
81
- if err != nil {
82
- log .Error (ctx , "fetch health report" , slog .Error (err ))
83
- } else {
97
+ wg .Add (1 )
98
+ go func () {
99
+ defer wg .Done ()
100
+ hr , err := client .DebugHealth (ctx )
101
+ if err != nil {
102
+ log .Error (ctx , "fetch health report" , slog .Error (err ))
103
+ return
104
+ }
105
+ m .Lock ()
84
106
d .HealthReport = & hr
85
- }
107
+ m .Unlock ()
108
+ }()
86
109
87
- exp , err := client .Experiments (ctx )
88
- if err != nil {
89
- log .Error (ctx , "fetch experiments" , slog .Error (err ))
90
- } else {
110
+ wg .Add (1 )
111
+ go func () {
112
+ defer wg .Done ()
113
+ exp , err := client .Experiments (ctx )
114
+ if err != nil {
115
+ log .Error (ctx , "fetch experiments" , slog .Error (err ))
116
+ return
117
+ }
118
+ m .Lock ()
91
119
d .Experiments = exp
92
- }
120
+ m .Unlock ()
121
+ }()
93
122
123
+ wg .Wait ()
94
124
return d
95
125
}
96
126
97
127
func NetworkInfo (ctx context.Context , client * codersdk.Client , log slog.Logger , agentID uuid.UUID ) Network {
98
- var n Network
99
-
100
- coordResp , err := client .Request (ctx , http .MethodGet , "/api/v2/debug/coordinator" , nil )
101
- if err != nil {
102
- log .Error (ctx , "fetch coordinator debug page" , slog .Error (err ))
103
- } else {
128
+ var (
129
+ n Network
130
+ m sync.Mutex
131
+ wg sync.WaitGroup
132
+ )
133
+
134
+ wg .Add (1 )
135
+ go func () {
136
+ defer wg .Done ()
137
+ coordResp , err := client .Request (ctx , http .MethodGet , "/api/v2/debug/coordinator" , nil )
138
+ if err != nil {
139
+ log .Error (ctx , "fetch coordinator debug page" , slog .Error (err ))
140
+ return
141
+ }
104
142
defer coordResp .Body .Close ()
105
143
bs , err := io .ReadAll (coordResp .Body )
106
144
if err != nil {
107
145
log .Error (ctx , "read coordinator debug page" , slog .Error (err ))
108
- } else {
109
- n .CoordinatorDebug = string (bs )
146
+ return
110
147
}
111
- }
148
+ m .Lock ()
149
+ n .CoordinatorDebug = string (bs )
150
+ m .Unlock ()
151
+ }()
112
152
113
- tailResp , err := client .Request (ctx , http .MethodGet , "/api/v2/debug/tailnet" , nil )
114
- if err != nil {
115
- log .Error (ctx , "fetch tailnet debug page" , slog .Error (err ))
116
- } else {
153
+ wg .Add (1 )
154
+ go func () {
155
+ defer wg .Done ()
156
+ tailResp , err := client .Request (ctx , http .MethodGet , "/api/v2/debug/tailnet" , nil )
157
+ if err != nil {
158
+ log .Error (ctx , "fetch tailnet debug page" , slog .Error (err ))
159
+ return
160
+ }
117
161
defer tailResp .Body .Close ()
118
162
bs , err := io .ReadAll (tailResp .Body )
119
163
if err != nil {
120
164
log .Error (ctx , "read tailnet debug page" , slog .Error (err ))
121
- } else {
122
- n .TailnetDebug = string (bs )
165
+ return
123
166
}
124
- }
167
+ m .Lock ()
168
+ n .TailnetDebug = string (bs )
169
+ m .Unlock ()
170
+ }()
125
171
126
- if agentID != uuid .Nil {
172
+ wg .Add (1 )
173
+ go func () {
174
+ defer wg .Done ()
175
+ if agentID == uuid .Nil {
176
+ log .Warn (ctx , "agent id required for agent connection info" )
177
+ return
178
+ }
127
179
connInfo , err := client .WorkspaceAgentConnectionInfo (ctx , agentID )
128
180
if err != nil {
129
181
log .Error (ctx , "fetch agent conn info" , slog .Error (err ), slog .F ("agent_id" , agentID .String ()))
130
- } else {
131
- n .NetcheckLocal = & connInfo
182
+ return
132
183
}
133
- } else {
134
- log .Warn (ctx , "agent id required for agent connection info" )
135
- }
184
+ m .Lock ()
185
+ n .NetcheckLocal = & connInfo
186
+ m .Unlock ()
187
+ }()
188
+
189
+ wg .Wait ()
136
190
137
191
return n
138
192
}
139
193
140
194
func WorkspaceInfo (ctx context.Context , client * codersdk.Client , log slog.Logger , workspaceID , agentID uuid.UUID ) Workspace {
141
- var w Workspace
195
+ var (
196
+ w Workspace
197
+ m sync.Mutex
198
+ wg sync.WaitGroup
199
+ )
142
200
143
201
if workspaceID == uuid .Nil {
144
202
log .Error (ctx , "no workspace id specified" )
@@ -149,44 +207,66 @@ func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger
149
207
log .Error (ctx , "no agent id specified" )
150
208
}
151
209
210
+ // dependency, cannot fetch concurrently
152
211
ws , err := client .Workspace (ctx , workspaceID )
153
212
if err != nil {
154
213
log .Error (ctx , "fetch workspace" , slog .Error (err ), slog .F ("workspace_id" , workspaceID ))
155
214
return w
156
215
}
157
-
158
- agt , err := client .WorkspaceAgent (ctx , agentID )
159
- if err != nil {
160
- log .Error (ctx , "fetch workspace agent" , slog .Error (err ), slog .F ("agent_id" , agentID ))
161
- }
162
-
163
216
w .Workspace = ws
164
- w .Agent = agt
165
217
166
- buildLogCh , closer , err := client .WorkspaceBuildLogsAfter (ctx , ws .LatestBuild .ID , 0 )
167
- if err != nil {
168
- log .Error (ctx , "fetch provisioner job logs" , slog .Error (err ), slog .F ("job_id" , ws .LatestBuild .Job .ID .String ()))
169
- } else {
218
+ wg .Add (1 )
219
+ go func () {
220
+ defer wg .Done ()
221
+ agt , err := client .WorkspaceAgent (ctx , agentID )
222
+ if err != nil {
223
+ log .Error (ctx , "fetch workspace agent" , slog .Error (err ), slog .F ("agent_id" , agentID ))
224
+ }
225
+ m .Lock ()
226
+ w .Agent = agt
227
+ m .Unlock ()
228
+ }()
229
+
230
+ wg .Add (1 )
231
+ go func () {
232
+ defer wg .Done ()
233
+ buildLogCh , closer , err := client .WorkspaceBuildLogsAfter (ctx , ws .LatestBuild .ID , 0 )
234
+ if err != nil {
235
+ log .Error (ctx , "fetch provisioner job logs" , slog .Error (err ), slog .F ("job_id" , ws .LatestBuild .Job .ID .String ()))
236
+ return
237
+ }
170
238
defer closer .Close ()
239
+ var logs []codersdk.ProvisionerJobLog
171
240
for log := range buildLogCh {
172
- w . BuildLogs = append (w .BuildLogs , log )
241
+ logs = append (w .BuildLogs , log )
173
242
}
174
- }
175
-
176
- if len (w .Workspace .LatestBuild .Resources ) == 0 {
177
- log .Warn (ctx , "workspace build has no resources" )
178
- return w
179
- }
243
+ m .Lock ()
244
+ w .BuildLogs = logs
245
+ m .Unlock ()
246
+ }()
180
247
181
- agentLogCh , closer , err := client .WorkspaceAgentLogsAfter (ctx , agentID , 0 , false )
182
- if err != nil {
183
- log .Error (ctx , "fetch agent startup logs" , slog .Error (err ), slog .F ("agent_id" , agentID .String ()))
184
- } else {
248
+ wg .Add (1 )
249
+ go func () {
250
+ defer wg .Done ()
251
+ if len (w .Workspace .LatestBuild .Resources ) == 0 {
252
+ log .Warn (ctx , "workspace build has no resources" )
253
+ return
254
+ }
255
+ agentLogCh , closer , err := client .WorkspaceAgentLogsAfter (ctx , agentID , 0 , false )
256
+ if err != nil {
257
+ log .Error (ctx , "fetch agent startup logs" , slog .Error (err ), slog .F ("agent_id" , agentID .String ()))
258
+ }
185
259
defer closer .Close ()
260
+ var logs []codersdk.WorkspaceAgentLog
186
261
for logChunk := range agentLogCh {
187
- w . AgentStartupLogs = append (w .AgentStartupLogs , logChunk ... )
262
+ logs = append (w .AgentStartupLogs , logChunk ... )
188
263
}
189
- }
264
+ m .Lock ()
265
+ w .AgentStartupLogs = logs
266
+ m .Unlock ()
267
+ }()
268
+
269
+ wg .Wait ()
190
270
191
271
return w
192
272
}
@@ -225,9 +305,35 @@ func Run(ctx context.Context, d *Deps) (*Bundle, error) {
225
305
}
226
306
}
227
307
228
- b .Deployment = DeploymentInfo (ctx , d .Client , d .Log )
229
- b .Workspace = WorkspaceInfo (ctx , d .Client , d .Log , d .WorkspaceID , d .AgentID )
230
- b .Network = NetworkInfo (ctx , d .Client , d .Log , d .AgentID )
308
+ var (
309
+ wg sync.WaitGroup
310
+ m sync.Mutex
311
+ )
312
+ wg .Add (1 )
313
+ go func () {
314
+ defer wg .Done ()
315
+ di := DeploymentInfo (ctx , d .Client , d .Log )
316
+ m .Lock ()
317
+ b .Deployment = di
318
+ m .Unlock ()
319
+ }()
320
+ wg .Add (1 )
321
+ go func () {
322
+ defer wg .Done ()
323
+ wi := WorkspaceInfo (ctx , d .Client , d .Log , d .WorkspaceID , d .AgentID )
324
+ m .Lock ()
325
+ b .Workspace = wi
326
+ m .Unlock ()
327
+ }()
328
+ wg .Add (1 )
329
+ go func () {
330
+ defer wg .Done ()
331
+ ni := NetworkInfo (ctx , d .Client , d .Log , d .AgentID )
332
+ m .Lock ()
333
+ b .Network = ni
334
+ m .Unlock ()
335
+ }()
336
+ wg .Wait ()
231
337
232
338
return & b , nil
233
339
}
0 commit comments