Retry fetching release notes on failure, and display failures (#101158)

* Retry getting release notes on failure, and show xhr failures

* improved release notes errors

* improve async code in loadReleaseNotes
This commit is contained in:
NotWearingPants 2020-06-27 01:25:57 +03:00 committed by GitHub
parent e0d4a2fe2d
commit d0c1d2ed94
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 24 deletions

View file

@ -21,7 +21,7 @@ export function request(options: IRequestOptions, token: CancellationToken): Pro
setRequestHeaders(xhr, options);
xhr.responseType = 'arraybuffer';
xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText)));
xhr.onerror = e => reject(new Error(xhr.statusText && ('XHR failed: ' + xhr.statusText) || 'XHR failed'));
xhr.onload = (e) => {
resolve({
res: {

View file

@ -95,10 +95,10 @@ export class ReleaseNotesManager {
return true;
}
private loadReleaseNotes(version: string): Promise<string> {
private async loadReleaseNotes(version: string): Promise<string> {
const match = /^(\d+\.\d+)\./.exec(version);
if (!match) {
return Promise.reject(new Error('not found'));
throw new Error('not found');
}
const versionLabel = match[1].replace(/\./g, '_');
@ -138,17 +138,30 @@ export class ReleaseNotesManager {
.replace(/kbstyle\(([^\)]+)\)/gi, kbstyle);
};
if (!this._releaseNotesCache.has(version)) {
this._releaseNotesCache.set(version, this._requestService.request({ url }, CancellationToken.None)
.then(asText)
.then(text => {
if (!text || !/^#\s/.test(text)) { // release notes always starts with `#` followed by whitespace
return Promise.reject(new Error('Invalid release notes'));
}
const fetchReleaseNotes = async () => {
let text;
try {
text = await asText(await this._requestService.request({ url }, CancellationToken.None));
} catch {
throw new Error('Failed to fetch release notes');
}
return Promise.resolve(text);
})
.then(text => patchKeybindings(text)));
if (!text || !/^#\s/.test(text)) { // release notes always starts with `#` followed by whitespace
throw new Error('Invalid release notes');
}
return patchKeybindings(text);
};
if (!this._releaseNotesCache.has(version)) {
this._releaseNotesCache.set(version, (async () => {
try {
return await fetchReleaseNotes();
} catch (err) {
this._releaseNotesCache.delete(version);
throw err;
}
})());
}
return this._releaseNotesCache.get(version)!;

View file

@ -51,12 +51,12 @@ export class OpenLatestReleaseNotesInBrowserAction extends Action {
super('update.openLatestReleaseNotes', nls.localize('releaseNotes', "Release Notes"), undefined, true);
}
run(): Promise<any> {
async run(): Promise<void> {
if (this.productService.releaseNotesUrl) {
const uri = URI.parse(this.productService.releaseNotesUrl);
return this.openerService.open(uri);
await this.openerService.open(uri);
}
return Promise.resolve(false);
throw new Error('This version of Visual Studio Code does not have release notes online');
}
}
@ -71,18 +71,22 @@ export abstract class AbstractShowReleaseNotesAction extends Action {
super(id, label, undefined, true);
}
run(): Promise<boolean> {
async run(): Promise<void> {
if (!this.enabled) {
return Promise.resolve(false);
return;
}
this.enabled = false;
return showReleaseNotes(this.instantiationService, this.version)
.then(undefined, () => {
const action = this.instantiationService.createInstance(OpenLatestReleaseNotesInBrowserAction);
return action.run().then(() => false);
});
try {
await showReleaseNotes(this.instantiationService, this.version);
} catch (err) {
const action = this.instantiationService.createInstance(OpenLatestReleaseNotesInBrowserAction);
try {
await action.run();
} catch (err2) {
throw new Error(`${err.message} and ${err2.message}`);
}
}
}
}