Skip to content

Commit bd63c47

Browse files
committed
Make file uploading more resiliant
1 parent 9a924be commit bd63c47

File tree

1 file changed

+100
-63
lines changed

1 file changed

+100
-63
lines changed

src/lesson.ts

Lines changed: 100 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -217,89 +217,126 @@ export async function handleLesson(
217217
if (!token) throw new Error("Could not get a token!");
218218

219219
// Next, let's open a websocket channel.
220+
return uploadFiles(token, files);
221+
}
222+
223+
function uploadFiles(token: string, files: Record<string, string>) : Promise<void> {
224+
const filesBackup = { ...files };
225+
220226
const ws = new WebSocket(
221227
new URL("/control/" + token, core.getInput("websocket")).toString(),
222228
);
223229
ws.binaryType = "arraybuffer";
224230

225-
ws.on("message", (data) => {
226-
if (!(data instanceof ArrayBuffer)) return;
231+
websockets.push(ws);
227232

228-
const message = ProxyOut.Main.fromBinary(new Uint8Array(data));
233+
// Now, we'll create a promise that handles sending the files.
234+
return new Promise<void>((resolve) => {
235+
let finished = false;
229236

230-
switch (message.type) {
231-
case ProxyOut.MessageType.Initialized: {
232-
// Request files.
237+
ws.on("message", (data) => {
238+
if (!(data instanceof ArrayBuffer)) return;
233239

234-
const message = ProxyInMain.Main.toBinary({
235-
type: ProxyInMain.MessageType.GetFiles,
236-
});
240+
const message = ProxyOut.Main.fromBinary(new Uint8Array(data));
237241

238-
ws.send(message);
242+
switch (message.type) {
243+
case ProxyOut.MessageType.Initialized: {
244+
// Request files.
239245

240-
break;
241-
}
242-
case ProxyOut.MessageType.Files: {
243-
if (!message.value) break;
244-
245-
const inner_message = ProxyOutFiles.Files.fromBinary(
246-
message.value,
247-
);
248-
249-
// First, delete any files that don't exist in our list of files.
250-
const items = Object.keys(files);
251-
for (const file of inner_message.files) {
252-
// If our list of new items doesn't include this item,
253-
// delete it.
254-
if (!items.includes(file.path)) {
255-
const delete_file_inner =
256-
ProxyInDeleteFile.DeleteFile.toBinary({
257-
path: file.path,
258-
});
246+
const message = ProxyInMain.Main.toBinary({
247+
type: ProxyInMain.MessageType.GetFiles,
248+
});
259249

260-
const delete_file = ProxyInMain.Main.toBinary({
261-
type: ProxyInMain.MessageType.DeleteFile,
262-
value: delete_file_inner,
263-
});
250+
ws.send(message);
264251

265-
ws.send(delete_file);
266-
}
252+
break;
267253
}
254+
case ProxyOut.MessageType.NotInitialized: {
255+
// TODO: Find out why this gets triggered so frequently.
268256

269-
// Next, we'll filter out any items that already exist in the container.
270-
for (const file of inner_message.files) {
271-
// If the item already exists in the container,
272-
// no need to re-upload it.
273-
if (files[file.path] === file.data?.toString()) {
274-
delete files[file.path];
275-
}
276-
}
257+
// If we receive NotInitialized, we should wait
258+
// a little and retry. We'll set finished to true
259+
// to prevent it from continuing.
260+
console.warn("Received NotInitialized, retrying...");
277261

278-
// Finally, we need to upload our files.
279-
for (const file in files) {
280-
const set_file_inner = ProxyInSetFile.SetFile.toBinary({
281-
path: file,
282-
data: new TextEncoder().encode(files[file]),
283-
});
262+
finished = true;
263+
ws.close();
284264

285-
const set_file = ProxyInMain.Main.toBinary({
286-
type: ProxyInMain.MessageType.SetFile,
287-
value: set_file_inner,
288-
});
265+
setTimeout(() => {
266+
uploadFiles(token, filesBackup).then(resolve);
267+
}, 1000);
289268

290-
ws.send(set_file);
269+
break;
291270
}
271+
case ProxyOut.MessageType.Files: {
272+
if (!message.value) break;
273+
274+
const inner_message = ProxyOutFiles.Files.fromBinary(
275+
message.value,
276+
);
277+
278+
// First, delete any files that don't exist in our list of files.
279+
const items = Object.keys(files);
280+
for (const file of inner_message.files) {
281+
// If our list of new items doesn't include this item,
282+
// delete it.
283+
if (!items.includes(file.path)) {
284+
const delete_file_inner =
285+
ProxyInDeleteFile.DeleteFile.toBinary({
286+
path: file.path,
287+
});
288+
289+
const delete_file = ProxyInMain.Main.toBinary({
290+
type: ProxyInMain.MessageType.DeleteFile,
291+
value: delete_file_inner,
292+
});
293+
294+
ws.send(delete_file);
295+
}
296+
}
292297

293-
// Now that we're done, we can close the websocket.
294-
ws.close();
298+
// Next, we'll filter out any items that already exist in the container.
299+
for (const file of inner_message.files) {
300+
// If the item already exists in the container,
301+
// no need to re-upload it.
302+
if (files[file.path] === file.data?.toString()) {
303+
delete files[file.path];
304+
}
305+
}
306+
307+
// Finally, we need to upload our files.
308+
for (const file in files) {
309+
const set_file_inner = ProxyInSetFile.SetFile.toBinary({
310+
path: file,
311+
data: new TextEncoder().encode(files[file]),
312+
});
313+
314+
const set_file = ProxyInMain.Main.toBinary({
315+
type: ProxyInMain.MessageType.SetFile,
316+
value: set_file_inner,
317+
});
318+
319+
ws.send(set_file);
320+
}
321+
322+
// Now that we're done, we can close the websocket.
323+
setTimeout(() => ws.close(), 1000);
295324

296-
break;
325+
// And finally, resolve the promise.
326+
finished = true;
327+
resolve();
328+
329+
break;
330+
}
297331
}
298-
}
299-
});
332+
});
300333

301-
websockets.push(ws);
334+
// If it exceeds 10 seconds, we'll resolve the promise.
335+
sleep(10 * 1000).then(() => {
336+
if (finished) return;
302337

303-
// Sleep for 10 seconds for the upload.
304-
await sleep(10 * 1000);
305-
}
338+
console.warn("Timed out waiting for websocket to close.");
339+
resolve();
340+
});
341+
});
342+
}

0 commit comments

Comments
 (0)