Skip to content

Commit c516c26

Browse files
authored
Merge pull request #14 from bitcomposer/master
Added concurrency control to export to spare license use.
2 parents 1b25706 + 1320d75 commit c516c26

File tree

5 files changed

+75
-30
lines changed

5 files changed

+75
-30
lines changed

api/index.ts

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@ import * as httpsModule from 'https';
33
import { outputConsole, currentWorkspaceFolder } from '../utils';
44
import { config } from '../extension';
55

6+
const DEFAULT_API_VERSION: number = 3;
7+
68
export class AtelierAPI {
79
private cookies: string[] = [];
810
private _config: any;
911
private _namespace: string;
12+
private static _apiVersion: number;
1013

1114
private get ns(): string {
1215
return this._namespace || this._config.ns;
1316
}
1417

18+
private get apiVersion(): number {
19+
return AtelierAPI._apiVersion || DEFAULT_API_VERSION;
20+
}
21+
1522
constructor() {
1623
this.setConnection(currentWorkspaceFolder());
1724
}
@@ -20,6 +27,10 @@ export class AtelierAPI {
2027
this._namespace = namespace;
2128
}
2229

30+
setApiVersion(apiVersion: number) {
31+
AtelierAPI._apiVersion = apiVersion;
32+
}
33+
2334
updateCookies(cookies: string[]) {
2435
cookies.forEach(cookie => {
2536
let [cookieName] = cookie.split('=');
@@ -134,7 +145,7 @@ export class AtelierAPI {
134145
serverInfo(): Promise<any> {
135146
return this.request('GET');
136147
}
137-
148+
// api v1+
138149
getDocNames({
139150
generated = false,
140151
category = '*',
@@ -146,63 +157,69 @@ export class AtelierAPI {
146157
type?: string;
147158
filter?: string;
148159
}): Promise<any> {
149-
return this.request('GET', `v3/${this.ns}/docnames/${category}/${type}`, null, {
160+
return this.request('GET', `v${this.apiVersion}/${this.ns}/docnames/${category}/${type}`, null, {
150161
filter,
151162
generated
152163
});
153164
}
154-
165+
// api v1+
155166
getDoc(name: string, format?: string): Promise<any> {
156167
let params = {};
157168
if (format) {
158169
params = {
159170
format
160171
};
161172
}
162-
return this.request('GET', `v3/${this.ns}/doc/${name}`, params);
173+
return this.request('GET', `v${this.apiVersion}/${this.ns}/doc/${name}`, params);
163174
}
164-
175+
// v1+
165176
putDoc(name: string, data: { enc: boolean; content: string[] }, ignoreConflict?: boolean): Promise<any> {
166177
let params = { ignoreConflict };
167-
return this.request('PUT', `v3/${this.ns}/doc/${name}`, data, params);
178+
return this.request('PUT', `v${this.apiVersion}/${this.ns}/doc/${name}`, data, params);
168179
}
169-
180+
// v1+
170181
actionIndex(docs: string[]): Promise<any> {
171-
return this.request('POST', `v3/${this.ns}/action/index`, docs);
182+
return this.request('POST', `v${this.apiVersion}/${this.ns}/action/index`, docs);
172183
}
173-
184+
// v2+
174185
actionSearch(params: { query: string; files?: string; sys?: boolean; gen?: boolean; max?: number }): Promise<any> {
175-
return this.request('GET', `v3/${this.ns}/action/search`, null, params);
186+
return this.apiVersion >= 2 ?
187+
this.request('GET', `v${this.apiVersion}/${this.ns}/action/search`, null, params) :
188+
Promise.reject(`Method 'search' not supported by API version ${this.apiVersion}`);
176189
}
177-
190+
// v1+
178191
actionQuery(query: string, parameters: string[]): Promise<any> {
179-
return this.request('POST', `v3/${this.ns}/action/query`, {
192+
return this.request('POST', `v${this.apiVersion}/${this.ns}/action/query`, {
180193
query,
181194
parameters
182195
});
183196
}
184-
197+
// v1+
185198
actionCompile(docs: string[], flags?: string, source = false): Promise<any> {
186-
return this.request('POST', `v3/${this.ns}/action/compile`, docs, { flags, source });
199+
return this.request('POST', `v${this.apiVersion}/${this.ns}/action/compile`, docs, { flags, source });
187200
}
188201

189202
cvtXmlUdl(source: string): Promise<any> {
190-
return this.request('POST', `v3/${this.ns}/cvt/xml/doc`, source, {}, { 'Content-Type': 'application/xml' });
203+
return this.request('POST', `v${this.apiVersion}/${this.ns}/cvt/xml/doc`, source, {}, { 'Content-Type': 'application/xml' });
191204
}
192-
205+
// v2+
193206
getmacrodefinition(docname: string, macroname: string, includes: string[]) {
194-
return this.request('POST', `v3/${this.ns}/action/getmacrodefinition`, {
195-
docname,
196-
macroname,
197-
includes
198-
});
199-
}
200-
207+
return this.apiVersion >= 2 ?
208+
this.request('POST', `v${this.apiVersion}/${this.ns}/action/getmacrodefinition`, {
209+
docname,
210+
macroname,
211+
includes
212+
}) :
213+
Promise.reject(`Method 'getmacrodefinition' not supported by API version ${this.apiVersion}`);
214+
}
215+
// v2+
201216
getmacrolocation(docname: string, macroname: string, includes: string[]) {
202-
return this.request('POST', `v3/${this.ns}/action/getmacrolocation`, {
203-
docname,
204-
macroname,
205-
includes
206-
});
217+
return this.apiVersion >= 2 ?
218+
this.request('POST', `v${this.apiVersion}/${this.ns}/action/getmacrolocation`, {
219+
docname,
220+
macroname,
221+
includes
222+
}) :
223+
Promise.reject(`Method 'getmacrolocation' not supported by API version ${this.apiVersion}`);
207224
}
208225
}

commands/export.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { PackageNode } from '../explorer/models/packageNode';
77
import { ClassNode } from '../explorer/models/classesNode';
88
import { RoutineNode } from '../explorer/models/routineNode';
99
import { config } from '../extension';
10+
import Bottleneck from 'bottleneck';
1011

1112
const filesFilter = (file: any) => {
1213
if (file.cat === 'CSP' || file.name.startsWith('%') || file.name.startsWith('INFORMATION.')) {
@@ -52,7 +53,7 @@ export async function exportFile(name: string, fileName: string): Promise<any> {
5253
}
5354
const storageContent = storageData.result.content;
5455

55-
if (storageContent.length>1 && storageContent[0]) {
56+
if (storageContent.length > 1 && storageContent[0] && storageContent.length < content.length) {
5657
const storageContentString = storageContent.join("\n");
5758
const contentString = content.join("\n");
5859

@@ -102,8 +103,19 @@ export async function exportList(files: string[]): Promise<any> {
102103
if (!files || !files.length) {
103104
vscode.window.showWarningMessage('Nothing to export');
104105
}
105-
const { atelier, folder } = config().get('export');
106+
const { atelier, folder, maxConcurrentConnections } = config().get('export');
106107

108+
if (maxConcurrentConnections > 0) {
109+
const limiter = new Bottleneck({
110+
maxConcurrent: maxConcurrentConnections
111+
});
112+
const results = [];
113+
for (let i=0;i<files.length;i++) {
114+
const result = await limiter.schedule(() => exportFile(files[i], getFileName(folder, files[i], atelier)));
115+
results.push(result);
116+
}
117+
return results;
118+
}
107119
return Promise.all(
108120
files.map(file => {
109121
exportFile(file, getFileName(folder, file, atelier));

extension.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { WorkspaceSymbolProvider } from './providers/WorkspaceSymbolProvider';
2929
export var explorerProvider: ObjectScriptExplorerProvider;
3030
export var documentContentProvider: DocumentContentProvider;
3131
export var workspaceState: vscode.Memento;
32+
export var extensionContext: vscode.ExtensionContext;
3233

3334
export const config = (config?: string, workspaceFolderName?: string): any => {
3435
workspaceFolderName = workspaceFolderName || currentWorkspaceFolder();
@@ -62,6 +63,7 @@ export function getXmlUri(uri: vscode.Uri): vscode.Uri {
6263
export async function activate(context: vscode.ExtensionContext): Promise<void> {
6364
const languages = require(context.asAbsolutePath('./package.json'))['contributes']['languages'].map(lang => lang.id);
6465
workspaceState = context.workspaceState;
66+
extensionContext = context;
6567
workspaceState.update('workspaceFolder', '');
6668

6769
explorerProvider = new ObjectScriptExplorerProvider();
@@ -88,6 +90,9 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
8890
.serverInfo()
8991
.then(info => {
9092
panel.text = `${conn.label}:${conn.ns} - Connected`;
93+
if (info && info.result && info.result.content && info.result.content.api > 0) {
94+
api.setApiVersion(info.result.content.api);
95+
}
9196
explorerProvider.refresh();
9297
})
9398
.catch(error => {

package-lock.json

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,11 @@
427427
"description": "Don't update the local file on export if the content is identical to the server code",
428428
"type": "boolean",
429429
"default": false
430+
},
431+
"objectscript.export.maxConcurrentConnections": {
432+
"description": "Max Export Connections (0 = Unlimited)",
433+
"type": "number",
434+
"default": 0
430435
}
431436
}
432437
},
@@ -472,6 +477,7 @@
472477
"vscode": "^1.1.26"
473478
},
474479
"dependencies": {
480+
"bottleneck": "^2.16.2",
475481
"glob": "^7.1.3",
476482
"vscode-cache": "^0.3.0"
477483
}

0 commit comments

Comments
 (0)