vscode: added error handling to download file streams

This commit is contained in:
Veetaha 2020-02-11 23:58:20 +02:00
parent 759100fb0d
commit 36dc3edb7a
4 changed files with 24 additions and 7 deletions

View file

@ -753,6 +753,11 @@
"os-tmpdir": "~1.0.1" "os-tmpdir": "~1.0.1"
} }
}, },
"ts-nested-error": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/ts-nested-error/-/ts-nested-error-1.1.3.tgz",
"integrity": "sha512-CJSRAhXr6phdkuu65U/ctkY/TBzjkg2g1sL9juSG/PP3ONQNCbeksMy54OfCBTUt13hSpHNbnTO1OBPunOHj/Q=="
},
"tslib": { "tslib": {
"version": "1.10.0", "version": "1.10.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",

View file

@ -27,6 +27,7 @@
"jsonc-parser": "^2.1.0", "jsonc-parser": "^2.1.0",
"node-fetch": "^2.6.0", "node-fetch": "^2.6.0",
"throttle-debounce": "^2.1.0", "throttle-debounce": "^2.1.0",
"ts-nested-error": "^1.1.3",
"vscode-languageclient": "^6.1.0" "vscode-languageclient": "^6.1.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -1,6 +1,9 @@
import fetch from "node-fetch"; import fetch from "node-fetch";
import * as fs from "fs"; import * as fs from "fs";
import { strict as assert } from "assert"; import { strict as assert } from "assert";
import { NestedError } from "ts-nested-error";
class DownloadFileError extends NestedError {}
/** /**
* Downloads file from `url` and stores it at `destFilePath` with `destFilePermissions`. * Downloads file from `url` and stores it at `destFilePath` with `destFilePermissions`.
@ -14,13 +17,13 @@ export async function downloadFile(
destFilePermissions: number, destFilePermissions: number,
onProgress: (readBytes: number, totalBytes: number) => void onProgress: (readBytes: number, totalBytes: number) => void
): Promise<void> { ): Promise<void> {
const res = await fetch(url); const res = await fetch(url).catch(DownloadFileError.rethrow("Failed at initial fetch"));
if (!res.ok) { if (!res.ok) {
console.log("Error", res.status, "while downloading file from", url); console.log("Error", res.status, "while downloading file from", url);
console.dir({ body: await res.text(), headers: res.headers }, { depth: 3 }); console.dir({ body: await res.text(), headers: res.headers }, { depth: 3 });
throw new Error(`Got response ${res.status} when trying to download a file`); throw new DownloadFileError(`Got response ${res.status}`);
} }
const totalBytes = Number(res.headers.get('content-length')); const totalBytes = Number(res.headers.get('content-length'));
@ -30,15 +33,21 @@ export async function downloadFile(
console.log("Downloading file of", totalBytes, "bytes size from", url, "to", destFilePath); console.log("Downloading file of", totalBytes, "bytes size from", url, "to", destFilePath);
// Here reject() may be called 2 times. As per ECMAScript standard, 2-d call is ignored
// https://tc39.es/ecma262/#sec-promise-reject-functions
return new Promise<void>((resolve, reject) => res.body return new Promise<void>((resolve, reject) => res.body
.on("data", (chunk: Buffer) => { .on("data", (chunk: Buffer) => {
readBytes += chunk.length; readBytes += chunk.length;
onProgress(readBytes, totalBytes); onProgress(readBytes, totalBytes);
}) })
.on("error", reject) .on("error", err => reject(
.pipe(fs new DownloadFileError(`Read-stream error, read bytes: ${readBytes}`, err)
.createWriteStream(destFilePath, { mode: destFilePermissions }) ))
.on("close", resolve) .pipe(fs.createWriteStream(destFilePath, { mode: destFilePermissions }))
) .on("error", err => reject(
new DownloadFileError(`Write-stream error, read bytes: ${readBytes}`, err)
))
.on("close", resolve)
); );
} }

View file

@ -104,6 +104,8 @@ export async function ensureLanguageServerBinary(
`GitHub repository: ${err.message}` `GitHub repository: ${err.message}`
); );
console.error(err);
dns.resolve('example.com').then( dns.resolve('example.com').then(
addrs => console.log("DNS resolution for example.com was successful", addrs), addrs => console.log("DNS resolution for example.com was successful", addrs),
err => { err => {