Skip to content

Commit

Permalink
Add logging to download:plugins script (#13905)
Browse files Browse the repository at this point in the history
Attempted mitigation for #13902 

- do not eat exceptions and properly log errors
- reduces request rate to 3/sec.

Contributed on behalf of STMicroelectronics

Signed-off-by: Thomas Mäder <t.s.maeder@gmail.com>
  • Loading branch information
tsmaeder committed Jul 12, 2024
1 parent f12a854 commit 54c7927
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 94 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ jobs:
if: runner.os == 'Linux'
shell: bash
run: |
yarn -s download:plugins
yarn -s download:plugins --rate-limit 3
- name: Build
shell: bash
Expand Down
1 change: 1 addition & 0 deletions dev-packages/cli/src/download-plugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ export default async function downloadPlugins(ovsxClient: OVSXClient, requestSer
failures.push(`No download url for extension pack ${id} (${version})`);
}
} catch (err) {
console.error(err);
failures.push(err.message);
}
}));
Expand Down
5 changes: 3 additions & 2 deletions dev-packages/ovsx-client/src/ovsx-api-filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ export class OVSXApiFilterImpl implements OVSXApiFilter {
let offset = 0;
let loop = true;
while (loop) {
const queryOptions = {
const queryOptions: VSXQueryOptions = {
...query,
offset
offset,
size: 5 // there is a great chance that the newest version will work
};
const results = await this.client.query(queryOptions);
const compatibleExtension = this.getLatestCompatibleExtension(results.extensions);
Expand Down
24 changes: 4 additions & 20 deletions dev-packages/ovsx-client/src/ovsx-http-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,28 +34,12 @@ export class OVSXHttpClient implements OVSXClient {
protected requestService: RequestService
) { }

async search(searchOptions?: VSXSearchOptions): Promise<VSXSearchResult> {
try {
return await this.requestJson(this.buildUrl('api/-/search', searchOptions));
} catch (err) {
return {
error: err?.message || String(err),
offset: -1,
extensions: []
};
}
search(searchOptions?: VSXSearchOptions): Promise<VSXSearchResult> {
return this.requestJson(this.buildUrl('api/-/search', searchOptions));
}

async query(queryOptions?: VSXQueryOptions): Promise<VSXQueryResult> {
try {
return await this.requestJson(this.buildUrl('api/v2/-/query', queryOptions));
} catch (error) {
return {
offset: 0,
totalSize: 0,
extensions: []
};
}
query(queryOptions?: VSXQueryOptions): Promise<VSXQueryResult> {
return this.requestJson(this.buildUrl('api/v2/-/query', queryOptions));
}

protected async requestJson<R>(url: string): Promise<R> {
Expand Down
1 change: 0 additions & 1 deletion dev-packages/ovsx-client/src/ovsx-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,6 @@ export interface VSXSearchOptions {
* Should be aligned with https://github.com/eclipse/openvsx/blob/e8f64fe145fc05d2de1469735d50a7a90e400bc4/server/src/main/java/org/eclipse/openvsx/json/SearchResultJson.java
*/
export interface VSXSearchResult {
error?: string;
offset: number;
extensions: VSXSearchEntry[];
}
Expand Down
14 changes: 11 additions & 3 deletions dev-packages/request/src/node-request-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,19 @@ export class NodeRequestService implements RequestService {
});
});

stream.on('error', reject);
stream.on('error', err => {
reject(err);
});
}
});

req.on('error', reject);
req.on('error', err => {
reject(err);
});

req.on('timeout', () => {
reject('timeout');
});

if (options.timeout) {
req.setTimeout(options.timeout);
Expand All @@ -153,7 +161,7 @@ export class NodeRequestService implements RequestService {
req.end();

token?.onCancellationRequested(() => {
req.abort();
req.destroy();
reject();
});
});
Expand Down
76 changes: 43 additions & 33 deletions packages/vsx-registry/src/browser/vsx-extensions-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,49 +225,59 @@ export class VSXExtensionsModel {
}
const client = await this.clientProvider();
const filter = await this.vsxApiFilter();
const result = await client.search(param);
this._searchError = result.error;
if (token.isCancellationRequested) {
return;
}
for (const data of result.extensions) {
const id = data.namespace.toLowerCase() + '.' + data.name.toLowerCase();
const allVersions = filter.getLatestCompatibleVersion(data);
if (!allVersions) {
continue;
try {
const result = await client.search(param);

if (token.isCancellationRequested) {
return;
}
if (this.preferences.get('extensions.onlyShowVerifiedExtensions')) {
this.fetchVerifiedStatus(id, client, allVersions).then(verified => {
this.doChange(() => {
this.addExtensions(data, id, allVersions, !!verified);
return Promise.resolve();
for (const data of result.extensions) {
const id = data.namespace.toLowerCase() + '.' + data.name.toLowerCase();
const allVersions = filter.getLatestCompatibleVersion(data);
if (!allVersions) {
continue;
}
if (this.preferences.get('extensions.onlyShowVerifiedExtensions')) {
this.fetchVerifiedStatus(id, client, allVersions).then(verified => {
this.doChange(() => {
this.addExtensions(data, id, allVersions, !!verified);
return Promise.resolve();
});
});
});
} else {
this.addExtensions(data, id, allVersions);
this.fetchVerifiedStatus(id, client, allVersions).then(verified => {
this.doChange(() => {
let extension = this.getExtension(id);
extension = this.setExtension(id);
extension.update(Object.assign({
verified: verified
}));
return Promise.resolve();
} else {
this.addExtensions(data, id, allVersions);
this.fetchVerifiedStatus(id, client, allVersions).then(verified => {
this.doChange(() => {
let extension = this.getExtension(id);
extension = this.setExtension(id);
extension.update(Object.assign({
verified: verified
}));
return Promise.resolve();
});
});
});
}
}
} catch (error) {
this._searchError = error?.message || String(error);
}

}, token);
}

protected async fetchVerifiedStatus(id: string, client: OVSXClient, allVersions: VSXAllVersions): Promise<boolean | undefined> {
const res = await client.query({ extensionId: id, extensionVersion: allVersions.version, includeAllVersions: true });
const extension = res.extensions?.[0];
let verified = extension?.verified;
if (!verified && extension?.publishedBy.loginName === 'open-vsx') {
verified = true;
try {
const res = await client.query({ extensionId: id, extensionVersion: allVersions.version, includeAllVersions: true });
const extension = res.extensions?.[0];
let verified = extension?.verified;
if (!verified && extension?.publishedBy.loginName === 'open-vsx') {
verified = true;
}
return verified;
} catch (error) {
console.error(error);
return false;
}
return verified;
}

protected addExtensions(data: VSXSearchEntry, id: string, allVersions: VSXAllVersions, verified?: boolean): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,47 +42,49 @@ export class VSXLanguageQuickPickService extends LanguageQuickPickService {

protected override async getAvailableLanguages(): Promise<LanguageQuickPickItem[]> {
const client = await this.clientProvider();
const searchResult = await client.search({
category: 'Language Packs',
sortBy: 'downloadCount',
sortOrder: 'desc',
size: 20
});
if (searchResult.error) {
throw new Error('Error while loading available languages: ' + searchResult.error);
}
try {
const searchResult = await client.search({
category: 'Language Packs',
sortBy: 'downloadCount',
sortOrder: 'desc',
size: 20
});

const extensionLanguages = await Promise.all(
searchResult.extensions.map(async extension => ({
extension,
languages: await this.loadExtensionLanguages(extension)
}))
);
const extensionLanguages = await Promise.all(
searchResult.extensions.map(async extension => ({
extension,
languages: await this.loadExtensionLanguages(extension)
}))
);

const languages = new Map<string, LanguageQuickPickItem>();
const languages = new Map<string, LanguageQuickPickItem>();

for (const extension of extensionLanguages) {
for (const localizationContribution of extension.languages) {
if (!languages.has(localizationContribution.languageId)) {
languages.set(localizationContribution.languageId, {
...this.createLanguageQuickPickItem(localizationContribution),
execute: async () => {
const progress = await this.messageService.showProgress({
text: nls.localizeByDefault('Installing {0} language support...',
localizationContribution.localizedLanguageName ?? localizationContribution.languageName ?? localizationContribution.languageId),
});
try {
const extensionUri = VSCodeExtensionUri.fromId(`${extension.extension.namespace}.${extension.extension.name}`).toString();
await this.pluginServer.deploy(extensionUri);
} finally {
progress.cancel();
for (const extension of extensionLanguages) {
for (const localizationContribution of extension.languages) {
if (!languages.has(localizationContribution.languageId)) {
languages.set(localizationContribution.languageId, {
...this.createLanguageQuickPickItem(localizationContribution),
execute: async () => {
const progress = await this.messageService.showProgress({
text: nls.localizeByDefault('Installing {0} language support...',
localizationContribution.localizedLanguageName ?? localizationContribution.languageName ?? localizationContribution.languageId),
});
try {
const extensionUri = VSCodeExtensionUri.fromId(`${extension.extension.namespace}.${extension.extension.name}`).toString();
await this.pluginServer.deploy(extensionUri);
} finally {
progress.cancel();
}
}
}
});
});
}
}
}
return Array.from(languages.values());
} catch (error) {
console.error(error);
return [];
}
return Array.from(languages.values());
}

protected async loadExtensionLanguages(extension: VSXSearchEntry): Promise<LanguageInfo[]> {
Expand Down

0 comments on commit 54c7927

Please sign in to comment.