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

Commitd545ba5

Browse files
committed
Refactoring and cleanup of agent startup script waiting
1 parent6e86cfe commitd545ba5

File tree

3 files changed

+280
-149
lines changed

3 files changed

+280
-149
lines changed

‎src/api/workspace.ts‎

Lines changed: 69 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import{spawn}from"child_process";
21
import{typeApi}from"coder/site/src/api/api";
32
import{
43
typeWorkspaceAgentLog,
54
typeWorkspace,
5+
typeWorkspaceAgent,
66
}from"coder/site/src/api/typesGenerated";
7+
import{spawn}from"node:child_process";
78
import*asvscodefrom"vscode";
89

910
import{typeFeatureSet}from"../featureSet";
@@ -40,35 +41,33 @@ export async function startWorkspaceIfStoppedOrFailed(
4041
createWorkspaceIdentifier(workspace),
4142
];
4243
if(featureSet.buildReason){
43-
startArgs.push(...["--reason","vscode_connection"]);
44+
startArgs.push("--reason","vscode_connection");
4445
}
4546

4647
// { shell: true } requires one shell-safe command string, otherwise we lose all escaping
4748
constcmd=`${escapeCommandArg(binPath)}${startArgs.join(" ")}`;
4849
conststartProcess=spawn(cmd,{shell:true});
4950

5051
startProcess.stdout.on("data",(data:Buffer)=>{
51-
data
52+
constlines=data
5253
.toString()
5354
.split(/\r*\n/)
54-
.forEach((line:string)=>{
55-
if(line!==""){
56-
writeEmitter.fire(line.toString()+"\r\n");
57-
}
58-
});
55+
.filter((line)=>line!=="");
56+
for(constlineoflines){
57+
writeEmitter.fire(line.toString()+"\r\n");
58+
}
5959
});
6060

6161
letcapturedStderr="";
6262
startProcess.stderr.on("data",(data:Buffer)=>{
63-
data
63+
constlines=data
6464
.toString()
6565
.split(/\r*\n/)
66-
.forEach((line:string)=>{
67-
if(line!==""){
68-
writeEmitter.fire(line.toString()+"\r\n");
69-
capturedStderr+=line.toString()+"\n";
70-
}
71-
});
66+
.filter((line)=>line!=="");
67+
for(constlineoflines){
68+
writeEmitter.fire(line.toString()+"\r\n");
69+
capturedStderr+=line.toString()+"\n";
70+
}
7271
});
7372

7473
startProcess.on("close",(code:number)=>{
@@ -85,43 +84,6 @@ export async function startWorkspaceIfStoppedOrFailed(
8584
});
8685
}
8786

88-
/**
89-
* Wait for the latest build to finish while streaming logs to the emitter.
90-
*
91-
* Once completed, fetch the workspace again and return it.
92-
*/
93-
exportasyncfunctionwriteAgentLogs(
94-
client:CoderApi,
95-
writeEmitter:vscode.EventEmitter<string>,
96-
agentId:string,
97-
):Promise<OneWayWebSocket<WorkspaceAgentLog[]>>{
98-
// This fetches the initial bunch of logs.
99-
constlogs=awaitclient.getWorkspaceAgentLogs(agentId);
100-
logs.forEach((log)=>writeEmitter.fire(log.output+"\r\n"));
101-
102-
constsocket=awaitclient.watchWorkspaceAgentLogs(agentId,logs);
103-
104-
socket.addEventListener("message",(data)=>{
105-
if(data.parseError){
106-
writeEmitter.fire(
107-
errToStr(data.parseError,"Failed to parse message")+"\r\n",
108-
);
109-
}else{
110-
data.parsedMessage.forEach((message)=>
111-
writeEmitter.fire(message.output+"\r\n"),
112-
);
113-
}
114-
});
115-
116-
socket.addEventListener("error",(error)=>{
117-
constbaseUrlRaw=client.getAxiosInstance().defaults.baseURL;
118-
thrownewError(
119-
`Failed to watch workspace build on${baseUrlRaw}:${errToStr(error,"no further details")}`,
120-
);
121-
});
122-
returnsocket;
123-
}
124-
12587
/**
12688
* Wait for the latest build to finish while streaming logs to the emitter.
12789
*
@@ -134,7 +96,9 @@ export async function waitForBuild(
13496
):Promise<Workspace>{
13597
// This fetches the initial bunch of logs.
13698
constlogs=awaitclient.getWorkspaceBuildLogs(workspace.latest_build.id);
137-
logs.forEach((log)=>writeEmitter.fire(log.output+"\r\n"));
99+
for(constlogoflogs){
100+
writeEmitter.fire(log.output+"\r\n");
101+
}
138102

139103
constsocket=awaitclient.watchBuildLogsByBuildId(
140104
workspace.latest_build.id,
@@ -171,3 +135,55 @@ export async function waitForBuild(
171135
);
172136
returnupdatedWorkspace;
173137
}
138+
139+
/**
140+
* Streams agent logs to the emitter in real-time.
141+
* Fetches existing logs and subscribes to new logs via websocket.
142+
* Returns the websocket and a completion promise that rejects on error.
143+
*/
144+
exportasyncfunctionstreamAgentLogs(
145+
client:CoderApi,
146+
writeEmitter:vscode.EventEmitter<string>,
147+
agent:WorkspaceAgent,
148+
):Promise<{
149+
socket:OneWayWebSocket<WorkspaceAgentLog[]>;
150+
completion:Promise<void>;
151+
}>{
152+
// This fetches the initial bunch of logs.
153+
constlogs=awaitclient.getWorkspaceAgentLogs(agent.id);
154+
for(constlogoflogs){
155+
writeEmitter.fire(log.output+"\r\n");
156+
}
157+
158+
constsocket=awaitclient.watchWorkspaceAgentLogs(agent.id,logs);
159+
160+
constcompletion=newPromise<void>((resolve,reject)=>{
161+
socket.addEventListener("message",(data)=>{
162+
if(data.parseError){
163+
writeEmitter.fire(
164+
errToStr(data.parseError,"Failed to parse message")+"\r\n",
165+
);
166+
}else{
167+
for(constlogofdata.parsedMessage){
168+
writeEmitter.fire(log.output+"\r\n");
169+
}
170+
}
171+
});
172+
173+
socket.addEventListener("error",(error)=>{
174+
constbaseUrlRaw=client.getAxiosInstance().defaults.baseURL;
175+
writeEmitter.fire(
176+
`Error watching agent logs on${baseUrlRaw}:${errToStr(error,"no further details")}\r\n`,
177+
);
178+
returnreject(
179+
newError(
180+
`Failed to watch agent logs on${baseUrlRaw}:${errToStr(error,"no further details")}`,
181+
),
182+
);
183+
});
184+
185+
socket.addEventListener("close",()=>resolve());
186+
});
187+
188+
return{ socket, completion};
189+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp