6
6
"net/http"
7
7
"strings"
8
8
9
+ "golang.org/x/sync/errgroup"
9
10
"golang.org/x/xerrors"
10
11
11
12
"github.com/google/uuid"
@@ -61,84 +62,114 @@ 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
+ // Note: each goroutine assigns to a different struct field, hence no mutex.
66
+ var (
67
+ d Deployment
68
+ eg errgroup.Group
69
+ )
70
+
71
+ eg .Go (func () error {
72
+ bi , err := client .BuildInfo (ctx )
73
+ if err != nil {
74
+ return xerrors .Errorf ("fetch build info: %w" , err )
75
+ }
70
76
d .BuildInfo = & bi
71
- }
77
+ return nil
78
+ })
72
79
73
- dc , err := client .DeploymentConfig (ctx )
74
- if err != nil {
75
- log .Error (ctx , "fetch deployment config" , slog .Error (err ))
76
- } else {
80
+ eg .Go (func () error {
81
+ dc , err := client .DeploymentConfig (ctx )
82
+ if err != nil {
83
+ return xerrors .Errorf ("fetch deployment config: %w" , err )
84
+ }
77
85
d .Config = dc
78
- }
86
+ return nil
87
+ })
79
88
80
- hr , err := client .DebugHealth (ctx )
81
- if err != nil {
82
- log .Error (ctx , "fetch health report" , slog .Error (err ))
83
- } else {
89
+ eg .Go (func () error {
90
+ hr , err := client .DebugHealth (ctx )
91
+ if err != nil {
92
+ return xerrors .Errorf ("fetch health report: %w" , err )
93
+ }
84
94
d .HealthReport = & hr
85
- }
95
+ return nil
96
+ })
86
97
87
- exp , err := client .Experiments (ctx )
88
- if err != nil {
89
- log .Error (ctx , "fetch experiments" , slog .Error (err ))
90
- } else {
98
+ eg .Go (func () error {
99
+ exp , err := client .Experiments (ctx )
100
+ if err != nil {
101
+ return xerrors .Errorf ("fetch experiments: %w" , err )
102
+ }
91
103
d .Experiments = exp
104
+ return nil
105
+ })
106
+
107
+ if err := eg .Wait (); err != nil {
108
+ log .Error (ctx , "fetch deployment information" , slog .Error (err ))
92
109
}
93
110
94
111
return d
95
112
}
96
113
97
114
func NetworkInfo (ctx context.Context , client * codersdk.Client , log slog.Logger , agentID uuid.UUID ) Network {
98
- var n Network
115
+ var (
116
+ n Network
117
+ eg errgroup.Group
118
+ )
99
119
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 {
120
+ eg .Go (func () error {
121
+ coordResp , err := client .Request (ctx , http .MethodGet , "/api/v2/debug/coordinator" , nil )
122
+ if err != nil {
123
+ return xerrors .Errorf ("fetch coordinator debug page: %w" , err )
124
+ }
104
125
defer coordResp .Body .Close ()
105
126
bs , err := io .ReadAll (coordResp .Body )
106
127
if err != nil {
107
- log .Error (ctx , "read coordinator debug page" , slog .Error (err ))
108
- } else {
109
- n .CoordinatorDebug = string (bs )
128
+ return xerrors .Errorf ("read coordinator debug page: %w" , err )
110
129
}
111
- }
130
+ n .CoordinatorDebug = string (bs )
131
+ return nil
132
+ })
112
133
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 {
134
+ eg .Go (func () error {
135
+ tailResp , err := client .Request (ctx , http .MethodGet , "/api/v2/debug/tailnet" , nil )
136
+ if err != nil {
137
+ return xerrors .Errorf ("fetch tailnet debug page: %w" , err )
138
+ }
117
139
defer tailResp .Body .Close ()
118
140
bs , err := io .ReadAll (tailResp .Body )
119
141
if err != nil {
120
- log .Error (ctx , "read tailnet debug page" , slog .Error (err ))
121
- } else {
122
- n .TailnetDebug = string (bs )
142
+ return xerrors .Errorf ("read tailnet debug page: %w" , err )
143
+ }
144
+ n .TailnetDebug = string (bs )
145
+ return nil
146
+ })
147
+
148
+ eg .Go (func () error {
149
+ if agentID == uuid .Nil {
150
+ log .Warn (ctx , "agent id required for agent connection info" )
151
+ return nil
123
152
}
124
- }
125
-
126
- if agentID != uuid .Nil {
127
153
connInfo , err := client .WorkspaceAgentConnectionInfo (ctx , agentID )
128
154
if err != nil {
129
- log .Error (ctx , "fetch agent conn info" , slog .Error (err ), slog .F ("agent_id" , agentID .String ()))
130
- } else {
131
- n .NetcheckLocal = & connInfo
155
+ return xerrors .Errorf ("fetch agent conn info: %w" , err )
132
156
}
133
- } else {
134
- log .Warn (ctx , "agent id required for agent connection info" )
157
+ n .NetcheckLocal = & connInfo
158
+ return nil
159
+ })
160
+
161
+ if err := eg .Wait (); err != nil {
162
+ log .Error (ctx , "fetch network information" , slog .Error (err ))
135
163
}
136
164
137
165
return n
138
166
}
139
167
140
168
func WorkspaceInfo (ctx context.Context , client * codersdk.Client , log slog.Logger , workspaceID , agentID uuid.UUID ) Workspace {
141
- var w Workspace
169
+ var (
170
+ w Workspace
171
+ eg errgroup.Group
172
+ )
142
173
143
174
if workspaceID == uuid .Nil {
144
175
log .Error (ctx , "no workspace id specified" )
@@ -149,43 +180,57 @@ func WorkspaceInfo(ctx context.Context, client *codersdk.Client, log slog.Logger
149
180
log .Error (ctx , "no agent id specified" )
150
181
}
151
182
183
+ // dependency, cannot fetch concurrently
152
184
ws , err := client .Workspace (ctx , workspaceID )
153
185
if err != nil {
154
186
log .Error (ctx , "fetch workspace" , slog .Error (err ), slog .F ("workspace_id" , workspaceID ))
155
187
return w
156
188
}
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
189
w .Workspace = ws
164
- w .Agent = agt
165
190
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 {
191
+ eg .Go (func () error {
192
+ agt , err := client .WorkspaceAgent (ctx , agentID )
193
+ if err != nil {
194
+ return xerrors .Errorf ("fetch workspace agent: %w" , err )
195
+ }
196
+ w .Agent = agt
197
+ return nil
198
+ })
199
+
200
+ eg .Go (func () error {
201
+ buildLogCh , closer , err := client .WorkspaceBuildLogsAfter (ctx , ws .LatestBuild .ID , 0 )
202
+ if err != nil {
203
+ return xerrors .Errorf ("fetch provisioner job logs: %w" , err )
204
+ }
170
205
defer closer .Close ()
206
+ var logs []codersdk.ProvisionerJobLog
171
207
for log := range buildLogCh {
172
- w .BuildLogs = append (w .BuildLogs , log )
208
+ logs = append (w .BuildLogs , log )
209
+ }
210
+ w .BuildLogs = logs
211
+ return nil
212
+ })
213
+
214
+ eg .Go (func () error {
215
+ if len (w .Workspace .LatestBuild .Resources ) == 0 {
216
+ log .Warn (ctx , "workspace build has no resources" )
217
+ return nil
218
+ }
219
+ agentLogCh , closer , err := client .WorkspaceAgentLogsAfter (ctx , agentID , 0 , false )
220
+ if err != nil {
221
+ return xerrors .Errorf ("fetch agent startup logs: %w" , err )
173
222
}
174
- }
175
-
176
- if len (w .Workspace .LatestBuild .Resources ) == 0 {
177
- log .Warn (ctx , "workspace build has no resources" )
178
- return w
179
- }
180
-
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 {
185
223
defer closer .Close ()
224
+ var logs []codersdk.WorkspaceAgentLog
186
225
for logChunk := range agentLogCh {
187
- w . AgentStartupLogs = append (w .AgentStartupLogs , logChunk ... )
226
+ logs = append (w .AgentStartupLogs , logChunk ... )
188
227
}
228
+ w .AgentStartupLogs = logs
229
+ return nil
230
+ })
231
+
232
+ if err := eg .Wait (); err != nil {
233
+ log .Error (ctx , "fetch workspace information" , slog .Error (err ))
189
234
}
190
235
191
236
return w
@@ -225,9 +270,24 @@ func Run(ctx context.Context, d *Deps) (*Bundle, error) {
225
270
}
226
271
}
227
272
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 )
273
+ var eg errgroup.Group
274
+ eg .Go (func () error {
275
+ di := DeploymentInfo (ctx , d .Client , d .Log )
276
+ b .Deployment = di
277
+ return nil
278
+ })
279
+ eg .Go (func () error {
280
+ wi := WorkspaceInfo (ctx , d .Client , d .Log , d .WorkspaceID , d .AgentID )
281
+ b .Workspace = wi
282
+ return nil
283
+ })
284
+ eg .Go (func () error {
285
+ ni := NetworkInfo (ctx , d .Client , d .Log , d .AgentID )
286
+ b .Network = ni
287
+ return nil
288
+ })
289
+
290
+ _ = eg .Wait ()
231
291
232
292
return & b , nil
233
293
}
0 commit comments