Skip to content

Commit 5baaa82

Browse files
committed
Add timeouts to scratchpad and DB queries
1 parent 08c1115 commit 5baaa82

20 files changed

+805
-127
lines changed

package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,18 @@
130130
"default": {},
131131
"scope": "resource"
132132
},
133+
"kdb.timeoutMap": {
134+
"type": "object",
135+
"description": "Timeout map for workspace files",
136+
"default": {},
137+
"scope": "resource"
138+
},
139+
"kdb.defaultTimeout": {
140+
"type": "number",
141+
"description": "Timeout in seconds for Insights Enterprise requests",
142+
"default": 30,
143+
"scope": "machine-overridable"
144+
},
133145
"kdb.connectionLabels": {
134146
"type": "array",
135147
"description": "List of label names and colorset",

ref_card.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
| [kdb.qHomeDirectoryWorkspace](https://github.com/KxSystems/kx-vscode/wiki/qHomeDirectory) | resource | `string` | `""` |
5353
| kdb.connectionMap | resource | `object` | `{}` |
5454
| kdb.targetMap | resource | `object` | `{}` |
55+
| kdb.timeoutMap | resource | `object` | `{}` |
56+
| kdb.defaultTimeout | resource | `number` | `30` |
5557
| kdb.linting | resource | `boolean` | `false` |
5658
| kdb.refactoring | resource | `string` | `"Workspace"` |
5759

@@ -95,6 +97,7 @@
9597
| Connection.Export.All | | src/extension.ts |
9698
| Connection.Export.Single | | src/extension.ts |
9799
| Connection.Import | | src/extension.ts |
100+
| Connection.Cancel.ie.sp | | src/classes/insightsConnection.ts |
98101
| Connection.Reset.ie.sp | | src/classes/insightsConnection.ts |
99102
| Connection.Label.Create || src/utils/connLabel.ts |
100103
| Connection.Label.Delete || src/utils/connLabel.ts |

src/classes/insightsConnection.ts

Lines changed: 61 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,16 @@ import {
4141
} from "../utils/core";
4242
import { convertTimeToTimestamp } from "../utils/dataSource";
4343
import { MessageKind, notify } from "../utils/notifications";
44-
import { handleScratchpadTableRes, handleWSResults } from "../utils/queryUtils";
44+
import {
45+
getHeaders,
46+
handleScratchpadTableRes,
47+
handleWSResults,
48+
} from "../utils/queryUtils";
4549
import { normalizeAssemblyTarget } from "../utils/shared";
4650
import { retrieveUDAtoCreateReqBody } from "../utils/uda";
4751

4852
const logger = "insightsConnection";
4953

50-
const customHeadersOctet = {
51-
Accept: "application/struct-text",
52-
"Content-Type": "application/json",
53-
};
54-
const customHeadersJson = {
55-
"Content-Type": "application/json",
56-
Accept: "application/json",
57-
json: true,
58-
};
59-
6054
export class InsightsConnection {
6155
public connected: boolean;
6256
public connLabel: string;
@@ -295,6 +289,7 @@ export class InsightsConnection {
295289
importSql: "scratchpadmanager/scratchpad/import/sql",
296290
importQsql: "scratchpadmanager/scratchpad/import/qsql",
297291
importUDA: "scratchpadmanager/scratchpad/import/uda",
292+
cancel: "scratchpadmanager/scratchpad/cancel",
298293
reset: "scratchpadmanager/reset",
299294
};
300295

@@ -457,6 +452,7 @@ export class InsightsConnection {
457452
public async getDatasourceQuery(
458453
type: DataSourceTypes,
459454
body: any,
455+
timeout?: number,
460456
): Promise<GetDataObjectPayload | undefined> {
461457
if (this.connected) {
462458
const udaName = (body as UDARequestBody).name
@@ -473,7 +469,7 @@ export class InsightsConnection {
473469
const requestUrl = this.generateDatasourceEndpoints(type, udaName);
474470
const options = await this.getOptions(
475471
false,
476-
customHeadersOctet,
472+
getHeaders(timeout ? timeout * 1000 : 0, "struct-text"), // DAPs use milliseconds
477473
"POST",
478474
requestUrl,
479475
body,
@@ -518,6 +514,7 @@ export class InsightsConnection {
518514
variableName: string,
519515
params: DataSourceFiles,
520516
silent?: boolean,
517+
timeout?: number,
521518
): Promise<void> {
522519
if (this.connected && this.connEndpoints) {
523520
let coreUrl: string;
@@ -579,7 +576,7 @@ export class InsightsConnection {
579576
const scratchpadURL = new url.URL(coreUrl!, this.node.details.server);
580577
const options = await this.getOptions(
581578
true,
582-
customHeadersJson,
579+
getHeaders(timeout),
583580
"POST",
584581
scratchpadURL.toString(),
585582
body,
@@ -654,6 +651,7 @@ export class InsightsConnection {
654651

655652
public async getUDAScratchpadQuery(
656653
udaReqBody: UDARequestBody,
654+
timeout?: number,
657655
): Promise<any | undefined> {
658656
if (this.connected && this.connEndpoints) {
659657
const isTableView = udaReqBody.returnFormat === "structuredText";
@@ -663,7 +661,7 @@ export class InsightsConnection {
663661
);
664662
const options = await this.getOptions(
665663
true,
666-
customHeadersJson,
664+
getHeaders(timeout),
667665
"POST",
668666
udaURL.toString(),
669667
udaReqBody,
@@ -706,6 +704,7 @@ export class InsightsConnection {
706704
context?: string,
707705
isPython?: boolean,
708706
isTableView?: boolean,
707+
timeout?: number,
709708
): Promise<any | undefined> {
710709
if (this.connected && this.connEndpoints) {
711710
if (isTableView === undefined) {
@@ -733,7 +732,7 @@ export class InsightsConnection {
733732

734733
const options = await this.getOptions(
735734
true,
736-
customHeadersJson,
735+
getHeaders(timeout),
737736
"POST",
738737
scratchpadURL.toString(),
739738
body,
@@ -792,6 +791,52 @@ export class InsightsConnection {
792791
return undefined;
793792
}
794793

794+
public async cancelScratchpad(): Promise<boolean | undefined> {
795+
if (this.connected && this.connEndpoints) {
796+
const scratchpadURL = new url.URL(
797+
this.connEndpoints.scratchpad.cancel,
798+
this.node.details.server,
799+
);
800+
const options = await this.getOptions(
801+
true,
802+
getHeaders(),
803+
"POST",
804+
scratchpadURL.toString(),
805+
undefined,
806+
);
807+
808+
if (!options) {
809+
return;
810+
}
811+
812+
notify("REST", MessageKind.DEBUG, {
813+
logger,
814+
params: { url: options.url },
815+
});
816+
817+
return await axios(options)
818+
.then((_response: any) => {
819+
notify(
820+
`Scratchpad cancel request sent for ${this.connLabel}.`,
821+
MessageKind.INFO,
822+
{ logger, telemetry: "Connection.Cancel.ie.sp" },
823+
);
824+
return true;
825+
})
826+
.catch((_error: any) => {
827+
notify(
828+
`Scratchpad cancel request error: ${_error.response.data.message}`,
829+
MessageKind.ERROR,
830+
{ logger },
831+
);
832+
return false;
833+
});
834+
} else {
835+
this.noConnectionOrEndpoints();
836+
return false;
837+
}
838+
}
839+
795840
public async resetScratchpad(): Promise<boolean | undefined> {
796841
if (this.connected && this.connEndpoints) {
797842
const scratchpadURL = new url.URL(
@@ -800,7 +845,7 @@ export class InsightsConnection {
800845
);
801846
const options = await this.getOptions(
802847
true,
803-
customHeadersJson,
848+
getHeaders(),
804849
"POST",
805850
scratchpadURL.toString(),
806851
null,

src/commands/dataSourceCommand.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ export async function populateScratchpad(
8686
connLabel: string,
8787
outputVariable?: string,
8888
silent?: boolean,
89+
timeout?: number,
8990
): Promise<void> {
9091
const connMngService = new ConnectionManagementService();
9192

@@ -112,6 +113,7 @@ export async function populateScratchpad(
112113
outputVariable,
113114
dataSourceForm,
114115
silent,
116+
timeout,
115117
);
116118
} else {
117119
notify(
@@ -126,6 +128,7 @@ export async function runDataSource(
126128
dataSourceForm: DataSourceFiles,
127129
connLabel: string,
128130
executorName: string,
131+
timeout?: number,
129132
): Promise<any> {
130133
if (DataSourcesPanel.running) {
131134
return;
@@ -165,24 +168,26 @@ export async function runDataSource(
165168

166169
switch (selectedType) {
167170
case "API":
168-
res = await runApiDataSource(fileContent, selectedConnection);
171+
res = await runApiDataSource(fileContent, selectedConnection, timeout);
169172
break;
170173
case "QSQL":
171174
res = await runQsqlDataSource(
172175
fileContent,
173176
selectedConnection,
174177
isNotebook || undefined,
178+
timeout,
175179
);
176180
break;
177181
case "UDA":
178-
res = await runUDADataSource(fileContent, selectedConnection);
182+
res = await runUDADataSource(fileContent, selectedConnection, timeout);
179183
break;
180184
case "SQL":
181185
default:
182186
res = await runSqlDataSource(
183187
fileContent,
184188
selectedConnection,
185189
isNotebook || undefined,
190+
timeout,
186191
);
187192
break;
188193
}
@@ -300,6 +305,7 @@ export function getSelectedType(fileContent: DataSourceFiles): string {
300305
export async function runApiDataSource(
301306
fileContent: DataSourceFiles,
302307
selectedConn: InsightsConnection,
308+
timeout?: number,
303309
): Promise<any> {
304310
const isTimeCorrect = checkIfTimeParamIsCorrect(
305311
fileContent.dataSource.api.startTS,
@@ -317,6 +323,7 @@ export async function runApiDataSource(
317323
const apiCall = await selectedConn.getDatasourceQuery(
318324
DataSourceTypes.API,
319325
JSON.stringify(apiBody),
326+
timeout,
320327
);
321328

322329
if (apiCall?.error) {
@@ -420,6 +427,7 @@ export async function runQsqlDataSource(
420427
fileContent: DataSourceFiles,
421428
selectedConn: InsightsConnection,
422429
isTableView?: boolean,
430+
timeout?: number,
423431
): Promise<any> {
424432
const qsqlBody = selectedConn.generateQSqlBody(
425433
fileContent.dataSource.qsql.query,
@@ -430,6 +438,7 @@ export async function runQsqlDataSource(
430438
const qsqlCall = await selectedConn.getDatasourceQuery(
431439
DataSourceTypes.QSQL,
432440
JSON.stringify(qsqlBody),
441+
timeout,
433442
);
434443

435444
if (qsqlCall?.error) {
@@ -448,13 +457,15 @@ export async function runSqlDataSource(
448457
fileContent: DataSourceFiles,
449458
selectedConn: InsightsConnection,
450459
isTableView?: boolean,
460+
timeout?: number,
451461
): Promise<any> {
452462
const sqlBody = {
453463
query: fileContent.dataSource.sql.query,
454464
};
455465
const sqlCall = await selectedConn.getDatasourceQuery(
456466
DataSourceTypes.SQL,
457467
JSON.stringify(sqlBody),
468+
timeout,
458469
);
459470

460471
if (sqlCall?.error) {
@@ -472,6 +483,7 @@ export async function runSqlDataSource(
472483
export async function runUDADataSource(
473484
fileContent: DataSourceFiles,
474485
selectedConn: InsightsConnection,
486+
timeout?: number,
475487
): Promise<any> {
476488
const uda = fileContent.dataSource.uda;
477489

@@ -485,16 +497,18 @@ export async function runUDADataSource(
485497
return udaReqBody;
486498
}
487499

488-
return await executeUDARequest(selectedConn, udaReqBody);
500+
return await executeUDARequest(selectedConn, udaReqBody, timeout);
489501
}
490502

491503
export async function executeUDARequest(
492504
selectedConn: InsightsConnection,
493505
udaReqBody: UDARequestBody,
506+
timeout?: number,
494507
): Promise<any> {
495508
const udaCall = await selectedConn.getDatasourceQuery(
496509
DataSourceTypes.UDA,
497510
udaReqBody,
511+
timeout,
498512
);
499513

500514
if (udaCall?.error) {

src/commands/serverCommand.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,7 @@ export async function executeQuery(
883883
isWorkbook: boolean,
884884
isFromConnTree?: boolean,
885885
token?: CancellationToken,
886+
timeout?: number,
886887
): Promise<any> {
887888
const connMngService = new ConnectionManagementService();
888889
const queryConsole = ExecutionConsole.start();
@@ -933,6 +934,7 @@ export async function executeQuery(
933934
context,
934935
isStringfy,
935936
isPython,
937+
timeout,
936938
);
937939
const endTime = Date.now();
938940
const duration = (endTime - startTime).toString();
@@ -1078,6 +1080,8 @@ export async function runQuery(
10781080
target?: string,
10791081
isSql?: boolean,
10801082
isInsights?: boolean,
1083+
timeout?: number,
1084+
cancel?: () => void,
10811085
) {
10821086
const editor = ext.activeTextEditor;
10831087
if (!editor) {
@@ -1129,17 +1133,24 @@ export async function runQuery(
11291133
}
11301134

11311135
const runner = Runner.create((_, token) => {
1136+
if (cancel) {
1137+
token.onCancellationRequested(cancel);
1138+
}
1139+
11321140
return target || (isSql && isInsights)
11331141
? variable
11341142
? populateScratchpad(
11351143
getPartialDatasourceFile(query, target, isSql, isPython),
11361144
connLabel,
11371145
variable,
1146+
undefined,
1147+
timeout,
11381148
)
11391149
: runDataSource(
11401150
getPartialDatasourceFile(query, target, isSql, isPython),
11411151
connLabel,
11421152
executorName,
1153+
timeout,
11431154
)
11441155
: executeQuery(
11451156
query,
@@ -1150,6 +1161,7 @@ export async function runQuery(
11501161
isWorkbook,
11511162
false,
11521163
token,
1164+
timeout,
11531165
);
11541166
});
11551167

0 commit comments

Comments
 (0)