Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commiteb8a0a3

Browse files
committed
Unify WS implementations across VS Code
1 parent80d2958 commiteb8a0a3

File tree

10 files changed

+213
-203
lines changed

10 files changed

+213
-203
lines changed

‎src/agentMetadataHelper.ts‎

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import{Api}from"coder/site/src/api/api";
21
import{WorkspaceAgent}from"coder/site/src/api/typesGenerated";
3-
import{ProxyAgent}from"proxy-agent";
42
import*asvscodefrom"vscode";
53
import{
64
AgentMetadataEvent,
75
AgentMetadataEventSchemaArray,
86
errToStr,
97
}from"./api-helper";
10-
import{watchAgentMetadata}from"./websocket/ws-helper";
8+
import{CoderWebSocketClient}from"./websocket/webSocketClient";
119

1210
exporttypeAgentMetadataWatcher={
1311
onChange:vscode.EventEmitter<null>["event"];
@@ -22,10 +20,9 @@ export type AgentMetadataWatcher = {
2220
*/
2321
exportfunctioncreateAgentMetadataWatcher(
2422
agentId:WorkspaceAgent["id"],
25-
restClient:Api,
26-
httpAgent:ProxyAgent,
23+
webSocketClient:CoderWebSocketClient,
2724
):AgentMetadataWatcher{
28-
constsocket=watchAgentMetadata(restClient,httpAgent,agentId);
25+
constsocket=webSocketClient.watchAgentMetadata(agentId);
2926

3027
letdisposed=false;
3128
constonChange=newvscode.EventEmitter<null>();

‎src/api.ts‎

Lines changed: 38 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,18 @@
11
import{AxiosInstance,InternalAxiosRequestConfig,isAxiosError}from"axios";
22
import{spawn}from"child_process";
33
import{Api}from"coder/site/src/api/api";
4-
import{
5-
ProvisionerJobLog,
6-
Workspace,
7-
}from"coder/site/src/api/typesGenerated";
4+
import{Workspace}from"coder/site/src/api/typesGenerated";
85
importfsfrom"fs/promises";
96
import{ProxyAgent}from"proxy-agent";
107
import*asvscodefrom"vscode";
11-
import*aswsfrom"ws";
128
import{errToStr}from"./api-helper";
139
import{CertificateError}from"./error";
1410
import{FeatureSet}from"./featureSet";
1511
import{getHeaderArgs}from"./headers";
1612
import{getProxyForUrl}from"./proxy";
1713
import{Storage}from"./storage";
1814
import{expandPath}from"./util";
15+
import{CoderWebSocketClient}from"./websocket/webSocketClient";
1916

2017
exportconstcoderSessionTokenHeader="Coder-Session-Token";
2118

@@ -68,8 +65,12 @@ export async function createHttpAgent(): Promise<ProxyAgent> {
6865

6966
/**
7067
* Create an sdk instance using the provided URL and token and hook it up to
71-
* configuration.The token may be undefined if some other form of
68+
* configuration. The token may be undefined if some other form of
7269
* authentication is being used.
70+
*
71+
* Automatically configures logging interceptors that log:
72+
* - Requests and responses at the trace level
73+
* - Errors at the error level
7374
*/
7475
exportfunctionmakeCoderSdk(
7576
baseUrl:string,
@@ -128,14 +129,14 @@ function addLoggingInterceptors(
128129
){
129130
client.interceptors.request.use(
130131
(config)=>{
131-
constrequestId=crypto.randomUUID();
132+
constrequestId=crypto.randomUUID().replace(/-/g,"");
132133
(configasRequestConfigWithMetadata).metadata={
133134
requestId,
134135
startedAt:Date.now(),
135136
};
136137

137138
logger.trace(
138-
`Request${requestId}:${config.method?.toUpperCase()}${config.url}`,
139+
`req${requestId}:${config.method?.toUpperCase()}${config.url}`,
139140
config.data??"",
140141
);
141142

@@ -146,9 +147,9 @@ function addLoggingInterceptors(
146147
if(isAxiosError(error)){
147148
constmeta=(error.configasRequestConfigWithMetadata)?.metadata;
148149
constrequestId=meta?.requestId??"n/a";
149-
message=`Request${requestId} error`;
150+
message=`req${requestId} error`;
150151
}
151-
logger.warn(message,error);
152+
logger.error(message,error);
152153

153154
returnPromise.reject(error);
154155
},
@@ -161,7 +162,7 @@ function addLoggingInterceptors(
161162
constms=startedAt ?Date.now()-startedAt :undefined;
162163

163164
logger.trace(
164-
`Response${requestId??"n/a"}:${response.status}${
165+
`res${requestId??"n/a"}:${response.status}${
165166
ms!==undefined ?` in${ms}ms` :""
166167
}`,
167168
// { responseBody: response.data }, // TODO too noisy
@@ -177,7 +178,7 @@ function addLoggingInterceptors(
177178
constms=startedAt ?Date.now()-startedAt :undefined;
178179

179180
conststatus=error.response?.status??"unknown";
180-
message=`Response${requestId}:${status}${ms!==undefined ?` in${ms}ms` :""}`;
181+
message=`res${requestId}:${status}${ms!==undefined ?` in${ms}ms` :""}`;
181182
}
182183
logger.warn(message,error);
183184

@@ -264,70 +265,47 @@ export async function startWorkspaceIfStoppedOrFailed(
264265
*/
265266
exportasyncfunctionwaitForBuild(
266267
restClient:Api,
268+
webSocketClient:CoderWebSocketClient,
267269
writeEmitter:vscode.EventEmitter<string>,
268270
workspace:Workspace,
269271
):Promise<Workspace>{
270-
constbaseUrlRaw=restClient.getAxiosInstance().defaults.baseURL;
271-
if(!baseUrlRaw){
272-
thrownewError("No base URL set on REST client");
273-
}
274-
275272
// This fetches the initial bunch of logs.
276273
constlogs=awaitrestClient.getWorkspaceBuildLogs(
277274
workspace.latest_build.id,
278275
);
279276
logs.forEach((log)=>writeEmitter.fire(log.output+"\r\n"));
280277

281-
// This follows the logs for new activity!
282-
// TODO: watchBuildLogsByBuildId exists, but it uses `location`.
283-
// Would be nice if we could use it here.
284-
letpath=`/api/v2/workspacebuilds/${workspace.latest_build.id}/logs?follow=true`;
285-
if(logs.length){
286-
path+=`&after=${logs[logs.length-1].id}`;
287-
}
288-
289-
constagent=awaitcreateHttpAgent();
290278
awaitnewPromise<void>((resolve,reject)=>{
279+
constrejectError=(error:unknown)=>{
280+
constbaseUrlRaw=restClient.getAxiosInstance().defaults.baseURL!;
281+
returnreject(
282+
newError(
283+
`Failed to watch workspace build on${baseUrlRaw}:${errToStr(error,"no further details")}`,
284+
),
285+
);
286+
};
287+
291288
try{
292-
// TODO move to `ws-helper`
293-
constbaseUrl=newURL(baseUrlRaw);
294-
constproto=baseUrl.protocol==="https:" ?"wss:" :"ws:";
295-
constsocketUrlRaw=`${proto}//${baseUrl.host}${path}`;
296-
consttoken=restClient.getAxiosInstance().defaults.headers.common[
297-
coderSessionTokenHeader
298-
]asstring|undefined;
299-
constsocket=newws.WebSocket(newURL(socketUrlRaw),{
300-
agent:agent,
301-
followRedirects:true,
302-
headers:token
303-
?{
304-
[coderSessionTokenHeader]:token,
305-
}
306-
:undefined,
307-
});
308-
socket.binaryType="nodebuffer";
309-
socket.on("message",(data)=>{
310-
constbuf=dataasBuffer;
311-
constlog=JSON.parse(buf.toString())asProvisionerJobLog;
289+
constsocket=webSocketClient.watchBuildLogsByBuildId(
290+
workspace.latest_build.id,
291+
logs,
292+
);
293+
constcloseHandler=()=>{
294+
resolve();
295+
};
296+
socket.addEventListener("close",closeHandler);
297+
socket.addEventListener("message",(data)=>{
298+
constlog=data.parsedMessage!;
312299
writeEmitter.fire(log.output+"\r\n");
313300
});
314-
socket.on("error",(error)=>{
315-
reject(
316-
newError(
317-
`Failed to watch workspace build using${socketUrlRaw}:${errToStr(error,"no further details")}`,
318-
),
319-
);
320-
});
321-
socket.on("close",()=>{
322-
resolve();
301+
socket.addEventListener("error",(error)=>{
302+
socket.removeEventListener("close",closeHandler);
303+
socket.close();
304+
rejectError(error);
323305
});
324306
}catch(error){
325307
// If this errors, it is probably a malformed URL.
326-
reject(
327-
newError(
328-
`Failed to watch workspace build on${baseUrlRaw}:${errToStr(error,"no further details")}`,
329-
),
330-
);
308+
reject(rejectError);
331309
}
332310
});
333311

‎src/extension.ts‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { CertificateError, getErrorDetail } from "./error";
1010
import{Remote}from"./remote";
1111
import{Storage}from"./storage";
1212
import{toSafeHost}from"./util";
13+
import{CoderWebSocketClient}from"./websocket/webSocketClient";
1314
import{WorkspaceQuery,WorkspaceProvider}from"./workspacesProvider";
1415

1516
exportasyncfunctionactivate(ctx:vscode.ExtensionContext):Promise<void>{
@@ -69,18 +70,23 @@ export async function activate(ctx: vscode.ExtensionContext): Promise<void> {
6970

7071
// TODO this won't get updated when users change their settings; Listen to changes and update this
7172
consthttpAgent=awaitcreateHttpAgent();
73+
constwebSocketClient=newCoderWebSocketClient(
74+
restClient,
75+
httpAgent,
76+
storage,
77+
);
7278
constmyWorkspacesProvider=newWorkspaceProvider(
7379
WorkspaceQuery.Mine,
7480
restClient,
7581
storage,
76-
httpAgent,
82+
webSocketClient,
7783
5,
7884
);
7985
constallWorkspacesProvider=newWorkspaceProvider(
8086
WorkspaceQuery.All,
8187
restClient,
8288
storage,
83-
httpAgent,
89+
webSocketClient,
8490
);
8591

8692
// createTreeView, unlike registerTreeDataProvider, gives us the tree view API

‎src/inbox.ts‎

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
import{Api}from"coder/site/src/api/api";
21
import{
32
Workspace,
43
GetInboxNotificationResponse,
54
}from"coder/site/src/api/typesGenerated";
6-
import{ProxyAgent}from"proxy-agent";
75
import*asvscodefrom"vscode";
86
import{errToStr}from"./api-helper";
97
import{typeStorage}from"./storage";
10-
import{OneWayCodeWebSocket}from"./websocket/OneWayCodeWebSocket";
11-
import{watchInboxNotifications}from"./websocket/ws-helper";
8+
import{OneWayCodeWebSocket}from"./websocket/oneWayCodeWebSocket";
9+
import{CoderWebSocketClient}from"./websocket/webSocketClient";
1210

1311
// These are the template IDs of our notifications.
1412
// Maybe in the future we should avoid hardcoding
@@ -23,8 +21,7 @@ export class Inbox implements vscode.Disposable {
2321

2422
constructor(
2523
workspace:Workspace,
26-
httpAgent:ProxyAgent,
27-
restClient:Api,
24+
webSocketClient:CoderWebSocketClient,
2825
storage:Storage,
2926
){
3027
this.#storage=storage;
@@ -36,9 +33,7 @@ export class Inbox implements vscode.Disposable {
3633

3734
constwatchTargets=[workspace.id];
3835

39-
this.#socket=watchInboxNotifications(
40-
restClient,
41-
httpAgent,
36+
this.#socket=webSocketClient.watchInboxNotifications(
4237
watchTemplates,
4338
watchTargets,
4439
);
@@ -47,8 +42,8 @@ export class Inbox implements vscode.Disposable {
4742
this.#storage.output.info("Listening to Coder Inbox");
4843
});
4944

50-
this.#socket.addEventListener("error",(error)=>{
51-
this.notifyError(error);
45+
this.#socket.addEventListener("error",()=>{
46+
// Errors are already logged internally
5247
this.dispose();
5348
});
5449

‎src/remote.ts‎

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import * as jsonc from "jsonc-parser";
77
import*asosfrom"os";
88
import*aspathfrom"path";
99
importprettyBytesfrom"pretty-bytes";
10-
import{ProxyAgent}from"proxy-agent";
1110
import*assemverfrom"semver";
1211
import*asvscodefrom"vscode";
1312
import{
@@ -39,6 +38,7 @@ import {
3938
findPort,
4039
parseRemoteAuthority,
4140
}from"./util";
41+
import{CoderWebSocketClient}from"./websocket/webSocketClient";
4242
import{WorkspaceMonitor}from"./workspaceMonitor";
4343

4444
exportinterfaceRemoteDetailsextendsvscode.Disposable{
@@ -493,27 +493,27 @@ export class Remote {
493493
}
494494

495495
consthttpAgent=awaitcreateHttpAgent();
496+
constwebSocketClient=newCoderWebSocketClient(
497+
workspaceRestClient,
498+
httpAgent,
499+
this.storage,
500+
);
496501

497502
// Watch the workspace for changes.
498503
constmonitor=newWorkspaceMonitor(
499504
workspace,
500505
workspaceRestClient,
501506
this.storage,
502507
this.vscodeProposed,
503-
httpAgent,
508+
webSocketClient,
504509
);
505510
disposables.push(monitor);
506511
disposables.push(
507512
monitor.onChange.event((w)=>(this.commands.workspace=w)),
508513
);
509514

510515
// Watch coder inbox for messages
511-
constinbox=newInbox(
512-
workspace,
513-
httpAgent,
514-
workspaceRestClient,
515-
this.storage,
516-
);
516+
constinbox=newInbox(workspace,webSocketClient,this.storage);
517517
disposables.push(inbox);
518518

519519
// Wait for the agent to connect.
@@ -631,11 +631,7 @@ export class Remote {
631631
);
632632

633633
disposables.push(
634-
...this.createAgentMetadataStatusBar(
635-
agent,
636-
workspaceRestClient,
637-
httpAgent,
638-
),
634+
...this.createAgentMetadataStatusBar(agent,webSocketClient),
639635
);
640636

641637
this.storage.output.info("Remote setup complete");
@@ -987,19 +983,14 @@ export class Remote {
987983
*/
988984
privatecreateAgentMetadataStatusBar(
989985
agent:WorkspaceAgent,
990-
restClient:Api,
991-
httpAgent:ProxyAgent,
986+
webSocketClient:CoderWebSocketClient,
992987
):vscode.Disposable[]{
993988
conststatusBarItem=vscode.window.createStatusBarItem(
994989
"agentMetadata",
995990
vscode.StatusBarAlignment.Left,
996991
);
997992

998-
constagentWatcher=createAgentMetadataWatcher(
999-
agent.id,
1000-
restClient,
1001-
httpAgent,
1002-
);
993+
constagentWatcher=createAgentMetadataWatcher(agent.id,webSocketClient);
1003994

1004995
constonChangeDisposable=agentWatcher.onChange(()=>{
1005996
if(agentWatcher.error){
File renamed without changes.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp