MoMo
update
11fcc5a
import * as Storage from "$lib/storage";
const networkErrors = [
"TypeError: Failed to fetch",
"TypeError: network error",
];
let attempts = 0;
const fetchFile = async (url: string) => {
const error = async (code: string, retry: boolean = true) => {
attempts++;
// try 3 more times before actually failing
if (retry && attempts <= 3) {
await fetchFile(url);
} else {
self.postMessage({
cobaltFetchWorker: {
error: code,
}
});
return self.close();
}
};
try {
const response = await fetch(url);
if (!response.ok) {
return error("queue.fetch.bad_response");
}
const contentType = response.headers.get('Content-Type')
|| 'application/octet-stream';
const contentLength = response.headers.get('Content-Length');
const estimatedLength = response.headers.get('Estimated-Content-Length');
let expectedSize;
if (contentLength) {
expectedSize = +contentLength;
} else if (estimatedLength) {
expectedSize = +estimatedLength;
}
const reader = response.body?.getReader();
const storage = await Storage.init(expectedSize);
if (!reader) {
return error("queue.fetch.no_file_reader");
}
let receivedBytes = 0;
while (true) {
const { done, value } = await reader.read();
if (done) break;
await storage.write(value, receivedBytes);
receivedBytes += value.length;
if (expectedSize) {
self.postMessage({
cobaltFetchWorker: {
progress: Math.round((receivedBytes / expectedSize) * 100),
size: receivedBytes,
}
});
}
}
if (receivedBytes === 0) {
return error("queue.fetch.empty_tunnel");
}
const file = Storage.retype(await storage.res(), contentType);
if (contentLength && Number(contentLength) !== file.size) {
return error("queue.fetch.corrupted_file", false);
}
self.postMessage({
cobaltFetchWorker: {
result: file
}
});
} catch (e) {
// retry several times if the error is network-related
if (networkErrors.includes(String(e))) {
return error("queue.fetch.network_error");
}
console.error("error from the fetch worker:");
console.error(e);
return error("queue.fetch.crashed", false);
}
}
self.onmessage = async (event: MessageEvent) => {
if (event.data.cobaltFetchWorker) {
await fetchFile(event.data.cobaltFetchWorker.url);
self.close();
}
}