dolphindb 2.0.506 → 2.0.509
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/browser.d.ts +35 -26
- package/browser.js +119 -98
- package/browser.js.map +1 -1
- package/index.d.ts +52 -41
- package/index.js +136 -113
- package/index.js.map +1 -1
- package/package.json +4 -4
package/index.d.ts
CHANGED
|
@@ -78,8 +78,22 @@ export interface DdbArrayVectorBlock {
|
|
|
78
78
|
lengths: Uint8Array | Uint16Array | Uint32Array;
|
|
79
79
|
data: DdbVectorValue;
|
|
80
80
|
}
|
|
81
|
-
export
|
|
82
|
-
|
|
81
|
+
export interface DdbMatrixValue {
|
|
82
|
+
rows: DdbObj<DdbVectorValue>;
|
|
83
|
+
cols: DdbObj<DdbVectorValue>;
|
|
84
|
+
data: DdbVectorValue;
|
|
85
|
+
}
|
|
86
|
+
export declare type DdbScalarValue = null | boolean | number | bigint | string | Uint8Array | // uuid, ipaddr, int128, blob
|
|
87
|
+
[
|
|
88
|
+
number,
|
|
89
|
+
number
|
|
90
|
+
] | // complex, point
|
|
91
|
+
DdbFunctionDefValue;
|
|
92
|
+
export declare type DdbVectorValue = Uint8Array | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | string[] | // string[]
|
|
93
|
+
Uint8Array[] | // blob
|
|
94
|
+
DdbObj[] | // any
|
|
95
|
+
DdbSymbolExtendedValue | DdbArrayVectorBlock[];
|
|
96
|
+
export declare type DdbValue = DdbScalarValue | DdbVectorValue | DdbMatrixValue;
|
|
83
97
|
export declare const nulls: {
|
|
84
98
|
readonly int8: -128;
|
|
85
99
|
readonly int16: -32768;
|
|
@@ -123,23 +137,20 @@ export declare class DdbObj<T extends DdbValue = DdbValue> {
|
|
|
123
137
|
rows?: number;
|
|
124
138
|
/** 第 2 维 */
|
|
125
139
|
cols?: number;
|
|
126
|
-
/** matrix 中值的类型,仅 matrix 才有 */
|
|
127
|
-
datatype?: DdbType;
|
|
128
140
|
/** 实际数据。不同的 DdbForm, DdbType 使用 DdbValue 中不同的类型来表示实际数据 */
|
|
129
141
|
value: T;
|
|
130
|
-
/**
|
|
142
|
+
/** 原始二进制数据,仅在 parse_object 为 false 时通过 parse_message 生成的顶层对象有这个属性 */
|
|
131
143
|
buffer?: Uint8Array;
|
|
132
144
|
constructor(data: Partial<DdbObj> & {
|
|
133
145
|
form: DdbForm;
|
|
134
146
|
type: DdbType;
|
|
135
|
-
length: number;
|
|
136
147
|
});
|
|
137
148
|
static parse(buf: Uint8Array, le: boolean): DdbObj<DdbValue>;
|
|
138
|
-
static parse_scalar(buf: Uint8Array, le: boolean, type: DdbType): [number,
|
|
149
|
+
static parse_scalar(buf: Uint8Array, le: boolean, type: DdbType): [number, DdbScalarValue];
|
|
139
150
|
/** parse: rows, cols, items
|
|
140
151
|
返回的 ddbobj.length 不包括 vector 的 type 和 form
|
|
141
152
|
*/
|
|
142
|
-
static parse_vector(buf: Uint8Array, le: boolean, type: DdbType): DdbObj
|
|
153
|
+
static parse_vector(buf: Uint8Array, le: boolean, type: DdbType): DdbObj<DdbVectorValue>;
|
|
143
154
|
/** 有可能没有字节对齐,不能直接使用原有 message 的 arraybuffer, 统一复制出来,让原有 arraybuffer 被回收掉比较好 */
|
|
144
155
|
static parse_vector_items(buf: Uint8Array, le: boolean, type: DdbType, length: number): [
|
|
145
156
|
number,
|
|
@@ -273,12 +284,9 @@ export declare class DDB {
|
|
|
273
284
|
print_object_buffer: boolean;
|
|
274
285
|
print_message: boolean;
|
|
275
286
|
parse_object: boolean;
|
|
276
|
-
/**
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
presolver(ddbobj: DdbObj): void;
|
|
280
|
-
prejector(error: Error): void;
|
|
281
|
-
presult: Promise<DdbObj<DdbValue>>;
|
|
287
|
+
/** DdbMessage listeners */
|
|
288
|
+
listeners: DdbMessageListener[];
|
|
289
|
+
promise: Promise<any>;
|
|
282
290
|
get connected(): boolean;
|
|
283
291
|
/**
|
|
284
292
|
Initialize an instance of DolphinDB Client using the WebSocket URL
|
|
@@ -307,6 +315,7 @@ export declare class DDB {
|
|
|
307
315
|
password?: string;
|
|
308
316
|
python?: boolean;
|
|
309
317
|
});
|
|
318
|
+
private on_message;
|
|
310
319
|
/** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
|
|
311
320
|
- options?:
|
|
312
321
|
- url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
|
|
@@ -351,52 +360,54 @@ export declare class DDB {
|
|
|
351
360
|
- options:
|
|
352
361
|
- urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
|
|
353
362
|
- vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
|
|
354
|
-
- handler?:
|
|
363
|
+
- handler?: Process messages during this rpc (DdbMessage)
|
|
355
364
|
- parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
|
|
356
365
|
不做解析,以便后续转发、序列化
|
|
357
366
|
*/
|
|
358
|
-
rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent,
|
|
367
|
+
rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, listener, parse_object, }: {
|
|
359
368
|
script?: string;
|
|
360
369
|
func?: string;
|
|
361
370
|
args?: (DdbObj | string | boolean)[];
|
|
362
371
|
vars?: string[];
|
|
363
372
|
urgent?: boolean;
|
|
364
|
-
|
|
373
|
+
listener?: DdbMessageListener;
|
|
365
374
|
parse_object?: boolean;
|
|
366
375
|
}): Promise<T>;
|
|
367
376
|
/** eval script through websocket (script command)
|
|
368
|
-
- script?:
|
|
369
|
-
- options?:
|
|
370
|
-
- urgent?:
|
|
371
|
-
-
|
|
372
|
-
- parse_object?:
|
|
373
|
-
|
|
377
|
+
- script?: Script to execute
|
|
378
|
+
- options?: execution options
|
|
379
|
+
- urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
|
|
380
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
381
|
+
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
382
|
+
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
383
|
+
so as to facilitate subsequent forwarding and serialization
|
|
374
384
|
*/
|
|
375
|
-
eval<T extends DdbObj>(script: string, { urgent,
|
|
385
|
+
eval<T extends DdbObj>(script: string, { urgent, listener, parse_object, }?: {
|
|
376
386
|
urgent?: boolean;
|
|
377
|
-
|
|
387
|
+
listener?: DdbMessageListener;
|
|
378
388
|
parse_object?: boolean;
|
|
379
389
|
}): Promise<T>;
|
|
380
390
|
/** call function through websocket (function command)
|
|
381
|
-
- func:
|
|
382
|
-
- args?: `[ ]`
|
|
383
|
-
- options?:
|
|
384
|
-
- urgent?:
|
|
385
|
-
- node?:
|
|
386
|
-
- nodes?:
|
|
387
|
-
- func_type?:
|
|
388
|
-
- add_node_alias?:
|
|
389
|
-
-
|
|
390
|
-
- parse_object?:
|
|
391
|
-
|
|
391
|
+
- func: function name
|
|
392
|
+
- args?: `[ ]` Call parameters (the incoming native string and boolean will be automatically converted to DdbObj<string> and DdbObj<boolean>)
|
|
393
|
+
- options?: call options
|
|
394
|
+
- urgent?: Emergency flag. Use urgent worker execution to prevent being blocked by other jobs
|
|
395
|
+
- node?: When the node alias is set, it is sent to the corresponding node in the cluster for execution (using the rpc method in DolphinDB)
|
|
396
|
+
- nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
|
|
397
|
+
- func_type?: It must be passed when setting the node parameter, the function type needs to be specified, and it is not passed in other cases
|
|
398
|
+
- add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
|
|
399
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
400
|
+
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
401
|
+
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
402
|
+
so as to facilitate subsequent forwarding and serialization
|
|
392
403
|
*/
|
|
393
|
-
call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias,
|
|
404
|
+
call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, }?: {
|
|
394
405
|
urgent?: boolean;
|
|
395
406
|
node?: string;
|
|
396
407
|
nodes?: string[];
|
|
397
408
|
func_type?: DdbFunctionType;
|
|
398
409
|
add_node_alias?: boolean;
|
|
399
|
-
|
|
410
|
+
listener?: DdbMessageListener;
|
|
400
411
|
parse_object?: boolean;
|
|
401
412
|
}): Promise<T>;
|
|
402
413
|
/** upload variable through websocket (variable command) */
|
|
@@ -404,8 +415,8 @@ export declare class DDB {
|
|
|
404
415
|
/** Uploaded variables' name */
|
|
405
416
|
vars: string[],
|
|
406
417
|
/** Uploaded variables' value */
|
|
407
|
-
args: (DdbObj | string | boolean)[], {
|
|
408
|
-
|
|
418
|
+
args: (DdbObj | string | boolean)[], { listener, parse_object, }?: {
|
|
419
|
+
listener?: DdbMessageListener;
|
|
409
420
|
parse_object?: boolean;
|
|
410
421
|
}): Promise<DdbObj<DdbValue>>;
|
|
411
422
|
/** 解析服务端响应报文,返回去掉 header 的 data buf */
|
|
@@ -415,7 +426,7 @@ export declare class DDB {
|
|
|
415
426
|
/** 转换 js 数组为 DdbObj[] */
|
|
416
427
|
to_ddbobjs(values: any[]): DdbObj<DdbValue>[];
|
|
417
428
|
}
|
|
418
|
-
export interface
|
|
429
|
+
export interface DdbMessageListener {
|
|
419
430
|
(message: DdbMessage, _this: DDB): any;
|
|
420
431
|
}
|
|
421
432
|
export interface DdbPrintMessage {
|
package/index.js
CHANGED
|
@@ -239,34 +239,60 @@ class DdbObj {
|
|
|
239
239
|
});
|
|
240
240
|
}
|
|
241
241
|
case DdbForm.matrix: {
|
|
242
|
-
//
|
|
242
|
+
// rename!(
|
|
243
|
+
// 1..9$3:3,
|
|
243
244
|
// [1, 2, 3],
|
|
244
|
-
// [
|
|
245
|
-
//
|
|
246
|
-
// <Buffer
|
|
247
|
-
//
|
|
248
|
-
//
|
|
249
|
-
// 01
|
|
245
|
+
// ['c1', 'c2', 'c3']
|
|
246
|
+
// )
|
|
247
|
+
// <Buffer 04 03 type = int, form = matrix
|
|
248
|
+
// 03 has_row_label (& 0x01) = 1, has_col_label (& 0x02) = 1
|
|
249
|
+
// row labels
|
|
250
|
+
// 04 01 type = int, form = vector
|
|
251
|
+
// 03 00 00 00 01 00 00 00 rows = 3, cols = 1
|
|
252
|
+
// 01 00 00 00 02 00 00 00 03 00 00 00 vector values
|
|
253
|
+
// col labels
|
|
254
|
+
// 12 01 type = string, form = vector
|
|
255
|
+
// 03 00 00 00 01 00 00 00 rows = 3, cols = 1
|
|
256
|
+
// 63 31 00 63 32 00 63 33 00
|
|
257
|
+
// matrix data
|
|
258
|
+
// 04 03 type = matrix.type, form = matrix
|
|
259
|
+
// 03 00 00 00 03 00 00 00 rows = 3, cols = 3
|
|
250
260
|
const dv = new DataView(buf.buffer, buf.byteOffset + i_data);
|
|
251
261
|
const label_flags = buf_data[0];
|
|
252
262
|
const has_row_labels = Boolean(label_flags & 0x01);
|
|
253
263
|
const has_col_labels = Boolean(label_flags & 0x02);
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
264
|
+
let row_labels = null;
|
|
265
|
+
let col_labels = null;
|
|
266
|
+
let offset = 1;
|
|
267
|
+
if (has_row_labels) {
|
|
268
|
+
row_labels = this.parse_vector(buf_data.subarray(offset + 2), le, buf_data[offset]);
|
|
269
|
+
row_labels.length += 2;
|
|
270
|
+
offset += row_labels.length;
|
|
271
|
+
}
|
|
272
|
+
if (has_col_labels) {
|
|
273
|
+
col_labels = this.parse_vector(buf_data.subarray(offset + 2), le, buf_data[offset]);
|
|
274
|
+
col_labels.length += 2;
|
|
275
|
+
offset += col_labels.length;
|
|
276
|
+
}
|
|
277
|
+
if (buf_data[offset] !== type)
|
|
278
|
+
throw new Error('matrix.datatype !== matrix.type');
|
|
279
|
+
const rows = dv.getUint32(offset + 2, le);
|
|
280
|
+
const cols = dv.getUint32(offset + 6, le);
|
|
281
|
+
const [len_items, data] = this.parse_vector_items(buf_data.subarray(offset + 10), le, type, rows * cols // 假设小于 2**32
|
|
260
282
|
);
|
|
283
|
+
offset += 10 + len_items;
|
|
261
284
|
return new this({
|
|
262
285
|
le,
|
|
263
286
|
form,
|
|
264
287
|
type,
|
|
265
|
-
length: i_data +
|
|
288
|
+
length: i_data + offset,
|
|
266
289
|
rows,
|
|
267
290
|
cols,
|
|
268
|
-
|
|
269
|
-
|
|
291
|
+
value: {
|
|
292
|
+
rows: row_labels,
|
|
293
|
+
cols: col_labels,
|
|
294
|
+
data,
|
|
295
|
+
},
|
|
270
296
|
});
|
|
271
297
|
}
|
|
272
298
|
default:
|
|
@@ -494,6 +520,7 @@ class DdbObj {
|
|
|
494
520
|
case DdbType.minute:
|
|
495
521
|
case DdbType.second:
|
|
496
522
|
case DdbType.datetime:
|
|
523
|
+
case DdbType.datehour:
|
|
497
524
|
return [
|
|
498
525
|
4 * length,
|
|
499
526
|
new Int32Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 4 * length))
|
|
@@ -618,7 +645,7 @@ class DdbObj {
|
|
|
618
645
|
}
|
|
619
646
|
pack() {
|
|
620
647
|
const { form, type, value } = this;
|
|
621
|
-
let header = new Uint8Array(
|
|
648
|
+
let header = new Uint8Array(2);
|
|
622
649
|
header[0] = type;
|
|
623
650
|
header[1] = form;
|
|
624
651
|
const body = (() => {
|
|
@@ -759,12 +786,17 @@ class DdbObj {
|
|
|
759
786
|
value[0].pack(),
|
|
760
787
|
value[1].pack(),
|
|
761
788
|
];
|
|
762
|
-
case DdbForm.matrix:
|
|
789
|
+
case DdbForm.matrix: {
|
|
790
|
+
const { rows, cols, data } = value;
|
|
763
791
|
return [
|
|
764
|
-
Uint8Array.of(
|
|
792
|
+
Uint8Array.of((rows && 0x01) | (cols && 0x02)),
|
|
793
|
+
...rows ? [rows.pack()] : [],
|
|
794
|
+
...cols ? [cols.pack()] : [],
|
|
795
|
+
Uint8Array.of(this.type, this.form),
|
|
765
796
|
Uint32Array.of(this.rows, this.cols),
|
|
766
|
-
...DdbObj.pack_vector_body(
|
|
797
|
+
...DdbObj.pack_vector_body(data, this.type, this.rows * this.cols)
|
|
767
798
|
];
|
|
799
|
+
}
|
|
768
800
|
default:
|
|
769
801
|
throw new Error(`${DdbForm[form]} 暂不支持序列化`);
|
|
770
802
|
}
|
|
@@ -792,6 +824,7 @@ class DdbObj {
|
|
|
792
824
|
case DdbType.minute:
|
|
793
825
|
case DdbType.second:
|
|
794
826
|
case DdbType.datetime:
|
|
827
|
+
case DdbType.datehour:
|
|
795
828
|
return [value];
|
|
796
829
|
case DdbType.float:
|
|
797
830
|
return [value];
|
|
@@ -878,7 +911,7 @@ class DdbObj {
|
|
|
878
911
|
case DdbForm.dict:
|
|
879
912
|
return `dict<${DdbType[this.value[0].type]}, ${DdbType[this.value[1].type]}>`;
|
|
880
913
|
case DdbForm.matrix:
|
|
881
|
-
return `matrix<${DdbType[this.
|
|
914
|
+
return `matrix<${DdbType[this.type]}>[${this.rows} rows][${this.cols} cols]`;
|
|
882
915
|
default:
|
|
883
916
|
return `${DdbForm[this.form]} ${tname}`;
|
|
884
917
|
}
|
|
@@ -907,21 +940,26 @@ class DdbObj {
|
|
|
907
940
|
for (let i = 0; i < this.rows; i++) {
|
|
908
941
|
let row = {};
|
|
909
942
|
for (let j = 0; j < this.cols; j++) {
|
|
910
|
-
const { type, name, value } = this.value[j]; // column
|
|
943
|
+
const { type, name, value: values } = this.value[j]; // column
|
|
911
944
|
switch (type) {
|
|
912
|
-
case DdbType.bool:
|
|
913
|
-
|
|
945
|
+
case DdbType.bool: {
|
|
946
|
+
const value = values[i];
|
|
947
|
+
row[name] = value === exports.nulls.int8 ?
|
|
948
|
+
null
|
|
949
|
+
:
|
|
950
|
+
Boolean(value);
|
|
914
951
|
break;
|
|
952
|
+
}
|
|
915
953
|
case DdbType.ipaddr:
|
|
916
|
-
row[name] =
|
|
954
|
+
row[name] = values.subarray(16 * i, 16 * (i + 1));
|
|
917
955
|
break;
|
|
918
956
|
case DdbType.symbol_extended: {
|
|
919
|
-
const { base, data } =
|
|
957
|
+
const { base, data } = values;
|
|
920
958
|
row[name] = base[data[i]];
|
|
921
959
|
break;
|
|
922
960
|
}
|
|
923
961
|
default:
|
|
924
|
-
row[name] =
|
|
962
|
+
row[name] = values[i];
|
|
925
963
|
}
|
|
926
964
|
}
|
|
927
965
|
rows[i] = row;
|
|
@@ -1388,9 +1426,9 @@ class DDB {
|
|
|
1388
1426
|
this.print_object_buffer = false;
|
|
1389
1427
|
this.print_message = true;
|
|
1390
1428
|
this.parse_object = true;
|
|
1391
|
-
/**
|
|
1392
|
-
this.
|
|
1393
|
-
this.
|
|
1429
|
+
/** DdbMessage listeners */
|
|
1430
|
+
this.listeners = [];
|
|
1431
|
+
this.promise = Promise.resolve(null);
|
|
1394
1432
|
this.url = url;
|
|
1395
1433
|
if (options.autologin !== undefined)
|
|
1396
1434
|
this.autologin = options.autologin;
|
|
@@ -1401,12 +1439,10 @@ class DDB {
|
|
|
1401
1439
|
if (options.python !== undefined)
|
|
1402
1440
|
this.python = options.python;
|
|
1403
1441
|
}
|
|
1404
|
-
/** resolver, rejector, promise of last rpc */
|
|
1405
|
-
presolver(ddbobj) { }
|
|
1406
|
-
prejector(error) { }
|
|
1407
1442
|
get connected() {
|
|
1408
1443
|
return this.websocket?.readyState === ws_1.WebSocket.OPEN;
|
|
1409
1444
|
}
|
|
1445
|
+
on_message(event) { }
|
|
1410
1446
|
/** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
|
|
1411
1447
|
- options?:
|
|
1412
1448
|
- url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
|
|
@@ -1434,30 +1470,7 @@ class DDB {
|
|
|
1434
1470
|
await this.rpc('connect', {});
|
|
1435
1471
|
},
|
|
1436
1472
|
on_message: event => {
|
|
1437
|
-
|
|
1438
|
-
if (this.print_message_buffer)
|
|
1439
|
-
console.log((0, utils_js_1.typed_array_to_buffer)(buf));
|
|
1440
|
-
const message = this.parse_message(buf);
|
|
1441
|
-
if (this.handlers.length) {
|
|
1442
|
-
const _handlers = [...this.handlers].reverse();
|
|
1443
|
-
for (const handler of _handlers)
|
|
1444
|
-
handler(message, this);
|
|
1445
|
-
}
|
|
1446
|
-
const { type, data } = message;
|
|
1447
|
-
switch (type) {
|
|
1448
|
-
case 'print':
|
|
1449
|
-
if (this.print_message)
|
|
1450
|
-
console.log(data);
|
|
1451
|
-
return;
|
|
1452
|
-
case 'object':
|
|
1453
|
-
if (this.print_object_buffer)
|
|
1454
|
-
console.log((0, utils_js_1.typed_array_to_buffer)(data.buffer));
|
|
1455
|
-
this.presolver(data);
|
|
1456
|
-
return;
|
|
1457
|
-
case 'error':
|
|
1458
|
-
this.prejector(data);
|
|
1459
|
-
return;
|
|
1460
|
-
}
|
|
1473
|
+
this.on_message(event);
|
|
1461
1474
|
}
|
|
1462
1475
|
});
|
|
1463
1476
|
await this.eval(this.python ?
|
|
@@ -1535,45 +1548,64 @@ class DDB {
|
|
|
1535
1548
|
disconnect() {
|
|
1536
1549
|
if (this.connected)
|
|
1537
1550
|
this.websocket.close(1000);
|
|
1538
|
-
this.
|
|
1539
|
-
this.
|
|
1540
|
-
this.presult = Promise.resolve(null);
|
|
1551
|
+
this.on_message = () => { };
|
|
1552
|
+
this.promise = Promise.resolve(null);
|
|
1541
1553
|
}
|
|
1542
1554
|
/** rpc through websocket (function/script/variable command)
|
|
1543
1555
|
- type: API 类型: 'script' | 'function' | 'variable'
|
|
1544
1556
|
- options:
|
|
1545
1557
|
- urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
|
|
1546
1558
|
- vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
|
|
1547
|
-
- handler?:
|
|
1559
|
+
- handler?: Process messages during this rpc (DdbMessage)
|
|
1548
1560
|
- parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
|
|
1549
1561
|
不做解析,以便后续转发、序列化
|
|
1550
1562
|
*/
|
|
1551
|
-
async rpc(type, { script, func, args = [], vars = [], urgent,
|
|
1563
|
+
async rpc(type, { script, func, args = [], vars = [], urgent, listener, parse_object, }) {
|
|
1552
1564
|
if (!this.websocket)
|
|
1553
1565
|
await this.connect();
|
|
1554
1566
|
if (!this.connected)
|
|
1555
1567
|
throw new Error(`${this.url} is already disconnected`);
|
|
1568
|
+
// this 上的当前配置需要在 message 到达后使用,先保存起来
|
|
1569
|
+
const _handlers = [...this.listeners].reverse();
|
|
1556
1570
|
// 临界区:保证多个 rpc 并发时形成 promise 链
|
|
1557
1571
|
// ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
|
|
1558
1572
|
// 违反世界观可能造成:
|
|
1559
1573
|
// 1. 并发多个请求只返回第一个结果(阻塞,需后续请求疏通)
|
|
1560
1574
|
// 2. windows 下 ddb server 返回多个相同的结果
|
|
1561
|
-
const ptail = this.
|
|
1562
|
-
let
|
|
1563
|
-
let
|
|
1564
|
-
const
|
|
1565
|
-
|
|
1566
|
-
|
|
1575
|
+
const ptail = this.promise;
|
|
1576
|
+
let resolve;
|
|
1577
|
+
let reject;
|
|
1578
|
+
const promise = this.promise = new Promise((_resolve, _reject) => {
|
|
1579
|
+
resolve = _resolve;
|
|
1580
|
+
reject = _reject;
|
|
1567
1581
|
});
|
|
1568
1582
|
try {
|
|
1569
1583
|
await ptail;
|
|
1570
1584
|
}
|
|
1571
1585
|
catch { }
|
|
1572
|
-
this.
|
|
1573
|
-
this.
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1586
|
+
// 临界区结束,只有一个 rpc 函数调用运行到这里,可以独占 this.on_message 然后写 WebSocket
|
|
1587
|
+
this.on_message = ({ data: buffer }) => {
|
|
1588
|
+
const buf = new Uint8Array(buffer);
|
|
1589
|
+
if (this.print_message_buffer)
|
|
1590
|
+
console.log((0, utils_js_1.typed_array_to_buffer)(buf));
|
|
1591
|
+
const message = this.parse_message(buf, parse_object);
|
|
1592
|
+
listener?.(message, this);
|
|
1593
|
+
for (const listener of _handlers)
|
|
1594
|
+
listener(message, this);
|
|
1595
|
+
const { type, data } = message;
|
|
1596
|
+
switch (type) {
|
|
1597
|
+
case 'print':
|
|
1598
|
+
if (this.print_message)
|
|
1599
|
+
console.log(data);
|
|
1600
|
+
return;
|
|
1601
|
+
case 'object':
|
|
1602
|
+
resolve(data);
|
|
1603
|
+
return;
|
|
1604
|
+
case 'error':
|
|
1605
|
+
reject(data);
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1577
1609
|
args = this.to_ddbobjs(args);
|
|
1578
1610
|
const command = this.enc.encode((() => {
|
|
1579
1611
|
switch (type) {
|
|
@@ -1594,51 +1626,40 @@ class DDB {
|
|
|
1594
1626
|
return 'connect\n';
|
|
1595
1627
|
}
|
|
1596
1628
|
})());
|
|
1597
|
-
|
|
1629
|
+
this.websocket.send((0, utils_js_1.concat)([
|
|
1598
1630
|
this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
|
|
1599
1631
|
command,
|
|
1600
1632
|
...args.map((arg) => arg.pack())
|
|
1601
|
-
]);
|
|
1602
|
-
|
|
1603
|
-
if (handler)
|
|
1604
|
-
this.handlers.push(handler);
|
|
1605
|
-
if (parse_object !== undefined)
|
|
1606
|
-
this.parse_object = parse_object;
|
|
1607
|
-
try {
|
|
1608
|
-
this.websocket.send(message);
|
|
1609
|
-
return (await presult);
|
|
1610
|
-
}
|
|
1611
|
-
finally {
|
|
1612
|
-
if (handler)
|
|
1613
|
-
this.handlers = this.handlers.filter(h => h !== handler);
|
|
1614
|
-
this.parse_object = _parse_object;
|
|
1615
|
-
}
|
|
1633
|
+
]));
|
|
1634
|
+
return promise;
|
|
1616
1635
|
}
|
|
1617
1636
|
/** eval script through websocket (script command)
|
|
1618
|
-
- script?:
|
|
1619
|
-
- options?:
|
|
1620
|
-
- urgent?:
|
|
1621
|
-
-
|
|
1622
|
-
- parse_object?:
|
|
1623
|
-
|
|
1637
|
+
- script?: Script to execute
|
|
1638
|
+
- options?: execution options
|
|
1639
|
+
- urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
|
|
1640
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
1641
|
+
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
1642
|
+
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
1643
|
+
so as to facilitate subsequent forwarding and serialization
|
|
1624
1644
|
*/
|
|
1625
|
-
async eval(script, { urgent,
|
|
1626
|
-
return this.rpc('script', { script, urgent,
|
|
1645
|
+
async eval(script, { urgent, listener, parse_object, } = {}) {
|
|
1646
|
+
return this.rpc('script', { script, urgent, listener, parse_object });
|
|
1627
1647
|
}
|
|
1628
1648
|
/** call function through websocket (function command)
|
|
1629
|
-
- func:
|
|
1630
|
-
- args?: `[ ]`
|
|
1631
|
-
- options?:
|
|
1632
|
-
- urgent?:
|
|
1633
|
-
- node?:
|
|
1634
|
-
- nodes?:
|
|
1635
|
-
- func_type?:
|
|
1636
|
-
- add_node_alias?:
|
|
1637
|
-
-
|
|
1638
|
-
- parse_object?:
|
|
1639
|
-
|
|
1649
|
+
- func: function name
|
|
1650
|
+
- args?: `[ ]` Call parameters (the incoming native string and boolean will be automatically converted to DdbObj<string> and DdbObj<boolean>)
|
|
1651
|
+
- options?: call options
|
|
1652
|
+
- urgent?: Emergency flag. Use urgent worker execution to prevent being blocked by other jobs
|
|
1653
|
+
- node?: When the node alias is set, it is sent to the corresponding node in the cluster for execution (using the rpc method in DolphinDB)
|
|
1654
|
+
- nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
|
|
1655
|
+
- func_type?: It must be passed when setting the node parameter, the function type needs to be specified, and it is not passed in other cases
|
|
1656
|
+
- add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
|
|
1657
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
1658
|
+
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
1659
|
+
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
1660
|
+
so as to facilitate subsequent forwarding and serialization
|
|
1640
1661
|
*/
|
|
1641
|
-
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias,
|
|
1662
|
+
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, } = {}) {
|
|
1642
1663
|
if (node) {
|
|
1643
1664
|
if (typeof func_type === 'undefined')
|
|
1644
1665
|
throw new Error('指定 node 时必须设置 func_type');
|
|
@@ -1668,7 +1689,7 @@ class DDB {
|
|
|
1668
1689
|
func,
|
|
1669
1690
|
args,
|
|
1670
1691
|
urgent,
|
|
1671
|
-
|
|
1692
|
+
listener,
|
|
1672
1693
|
parse_object
|
|
1673
1694
|
});
|
|
1674
1695
|
}
|
|
@@ -1677,10 +1698,10 @@ class DDB {
|
|
|
1677
1698
|
/** Uploaded variables' name */
|
|
1678
1699
|
vars,
|
|
1679
1700
|
/** Uploaded variables' value */
|
|
1680
|
-
args, {
|
|
1701
|
+
args, { listener, parse_object, } = {}) {
|
|
1681
1702
|
if (!args.length || args.length !== vars.length)
|
|
1682
1703
|
throw new Error('variable command parameter is empty or parameter name is empty, or the number does not match');
|
|
1683
|
-
return this.rpc('variable', { vars, args,
|
|
1704
|
+
return this.rpc('variable', { vars, args, listener, parse_object });
|
|
1684
1705
|
}
|
|
1685
1706
|
/** 解析服务端响应报文,返回去掉 header 的 data buf */
|
|
1686
1707
|
parse_message(buf, parse_object = this.parse_object) {
|
|
@@ -1718,10 +1739,12 @@ class DDB {
|
|
|
1718
1739
|
data: new Error(message)
|
|
1719
1740
|
};
|
|
1720
1741
|
const buf_obj = buf.subarray(i_lf_1 + 1);
|
|
1742
|
+
if (this.print_object_buffer)
|
|
1743
|
+
console.log((0, utils_js_1.typed_array_to_buffer)(buf_obj));
|
|
1721
1744
|
return {
|
|
1722
1745
|
type: 'object',
|
|
1723
1746
|
data: parse_object ?
|
|
1724
|
-
|
|
1747
|
+
DdbObj.parse(buf_obj, this.le)
|
|
1725
1748
|
:
|
|
1726
1749
|
new DdbObj({
|
|
1727
1750
|
form: DdbForm.scalar,
|