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/browser.d.ts
CHANGED
|
@@ -75,8 +75,22 @@ export interface DdbArrayVectorBlock {
|
|
|
75
75
|
lengths: Uint8Array | Uint16Array | Uint32Array;
|
|
76
76
|
data: DdbVectorValue;
|
|
77
77
|
}
|
|
78
|
-
export
|
|
79
|
-
|
|
78
|
+
export interface DdbMatrixValue {
|
|
79
|
+
rows: DdbObj<DdbVectorValue>;
|
|
80
|
+
cols: DdbObj<DdbVectorValue>;
|
|
81
|
+
data: DdbVectorValue;
|
|
82
|
+
}
|
|
83
|
+
export declare type DdbScalarValue = null | boolean | number | bigint | string | Uint8Array | // uuid, ipaddr, int128, blob
|
|
84
|
+
[
|
|
85
|
+
number,
|
|
86
|
+
number
|
|
87
|
+
] | // complex, point
|
|
88
|
+
DdbFunctionDefValue;
|
|
89
|
+
export declare type DdbVectorValue = Uint8Array | Int8Array | Int16Array | Int32Array | Float32Array | Float64Array | BigInt64Array | string[] | // string[]
|
|
90
|
+
Uint8Array[] | // blob
|
|
91
|
+
DdbObj[] | // any
|
|
92
|
+
DdbSymbolExtendedValue | DdbArrayVectorBlock[];
|
|
93
|
+
export declare type DdbValue = DdbScalarValue | DdbVectorValue | DdbMatrixValue;
|
|
80
94
|
export declare const nulls: {
|
|
81
95
|
readonly int8: -128;
|
|
82
96
|
readonly int16: -32768;
|
|
@@ -120,23 +134,20 @@ export declare class DdbObj<T extends DdbValue = DdbValue> {
|
|
|
120
134
|
rows?: number;
|
|
121
135
|
/** 第 2 维 */
|
|
122
136
|
cols?: number;
|
|
123
|
-
/** matrix 中值的类型,仅 matrix 才有 */
|
|
124
|
-
datatype?: DdbType;
|
|
125
137
|
/** 实际数据。不同的 DdbForm, DdbType 使用 DdbValue 中不同的类型来表示实际数据 */
|
|
126
138
|
value: T;
|
|
127
|
-
/**
|
|
139
|
+
/** 原始二进制数据,仅在 parse_object 为 false 时通过 parse_message 生成的顶层对象有这个属性 */
|
|
128
140
|
buffer?: Uint8Array;
|
|
129
141
|
constructor(data: Partial<DdbObj> & {
|
|
130
142
|
form: DdbForm;
|
|
131
143
|
type: DdbType;
|
|
132
|
-
length: number;
|
|
133
144
|
});
|
|
134
145
|
static parse(buf: Uint8Array, le: boolean): DdbObj<DdbValue>;
|
|
135
|
-
static parse_scalar(buf: Uint8Array, le: boolean, type: DdbType): [number,
|
|
146
|
+
static parse_scalar(buf: Uint8Array, le: boolean, type: DdbType): [number, DdbScalarValue];
|
|
136
147
|
/** parse: rows, cols, items
|
|
137
148
|
返回的 ddbobj.length 不包括 vector 的 type 和 form
|
|
138
149
|
*/
|
|
139
|
-
static parse_vector(buf: Uint8Array, le: boolean, type: DdbType): DdbObj
|
|
150
|
+
static parse_vector(buf: Uint8Array, le: boolean, type: DdbType): DdbObj<DdbVectorValue>;
|
|
140
151
|
/** 有可能没有字节对齐,不能直接使用原有 message 的 arraybuffer, 统一复制出来,让原有 arraybuffer 被回收掉比较好 */
|
|
141
152
|
static parse_vector_items(buf: Uint8Array, le: boolean, type: DdbType, length: number): [
|
|
142
153
|
number,
|
|
@@ -275,12 +286,9 @@ export declare class DDB {
|
|
|
275
286
|
print_object_buffer: boolean;
|
|
276
287
|
print_message: boolean;
|
|
277
288
|
parse_object: boolean;
|
|
278
|
-
/**
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
presolver(ddbobj: DdbObj): void;
|
|
282
|
-
prejector(error: Error): void;
|
|
283
|
-
presult: Promise<DdbObj<DdbValue>>;
|
|
289
|
+
/** DdbMessage listeners */
|
|
290
|
+
listeners: DdbMessageListener[];
|
|
291
|
+
promise: Promise<any>;
|
|
284
292
|
get connected(): boolean;
|
|
285
293
|
/**
|
|
286
294
|
Initialize an instance of DolphinDB Client using the WebSocket URL
|
|
@@ -309,6 +317,7 @@ export declare class DDB {
|
|
|
309
317
|
password?: string;
|
|
310
318
|
python?: boolean;
|
|
311
319
|
});
|
|
320
|
+
private on_message;
|
|
312
321
|
/** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
|
|
313
322
|
- options?:
|
|
314
323
|
- url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
|
|
@@ -353,31 +362,31 @@ export declare class DDB {
|
|
|
353
362
|
- options:
|
|
354
363
|
- urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
|
|
355
364
|
- vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
|
|
356
|
-
-
|
|
365
|
+
- listener?: 处理本次 rpc 期间的消息 (DdbMessage)
|
|
357
366
|
- parse_object?: 在本次 rpc 期间设置 parse_object, 结束后恢复原有
|
|
358
367
|
为 false 时返回的 DdbObj 仅含有 buffer 和 le,不做解析,以便后续转发、序列化
|
|
359
368
|
*/
|
|
360
|
-
rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent,
|
|
369
|
+
rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, listener, parse_object, }: {
|
|
361
370
|
script?: string;
|
|
362
371
|
func?: string;
|
|
363
372
|
args?: (DdbObj | string | boolean)[];
|
|
364
373
|
vars?: string[];
|
|
365
374
|
urgent?: boolean;
|
|
366
|
-
|
|
375
|
+
listener?: DdbMessageListener;
|
|
367
376
|
parse_object?: boolean;
|
|
368
377
|
}): Promise<T>;
|
|
369
378
|
/** eval script through websocket (script command)
|
|
370
379
|
- script?: Script to execute
|
|
371
380
|
- options?: execution options
|
|
372
381
|
- urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
|
|
373
|
-
-
|
|
382
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
374
383
|
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
375
384
|
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
376
385
|
so as to facilitate subsequent forwarding and serialization
|
|
377
386
|
*/
|
|
378
|
-
eval<T extends DdbObj>(script: string, { urgent,
|
|
387
|
+
eval<T extends DdbObj>(script: string, { urgent, listener, parse_object, }?: {
|
|
379
388
|
urgent?: boolean;
|
|
380
|
-
|
|
389
|
+
listener?: DdbMessageListener;
|
|
381
390
|
parse_object?: boolean;
|
|
382
391
|
}): Promise<T>;
|
|
383
392
|
/** call function through websocket (function command)
|
|
@@ -389,18 +398,18 @@ export declare class DDB {
|
|
|
389
398
|
- nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
|
|
390
399
|
- 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
|
|
391
400
|
- add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
|
|
392
|
-
-
|
|
401
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
393
402
|
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
394
403
|
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
395
404
|
so as to facilitate subsequent forwarding and serialization
|
|
396
405
|
*/
|
|
397
|
-
call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias,
|
|
406
|
+
call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, }?: {
|
|
398
407
|
urgent?: boolean;
|
|
399
408
|
node?: string;
|
|
400
409
|
nodes?: string[];
|
|
401
410
|
func_type?: DdbFunctionType;
|
|
402
411
|
add_node_alias?: boolean;
|
|
403
|
-
|
|
412
|
+
listener?: DdbMessageListener;
|
|
404
413
|
parse_object?: boolean;
|
|
405
414
|
}): Promise<T>;
|
|
406
415
|
/** upload variable through websocket (variable command) */
|
|
@@ -408,8 +417,8 @@ export declare class DDB {
|
|
|
408
417
|
/** Uploaded variables' name */
|
|
409
418
|
vars: string[],
|
|
410
419
|
/** Uploaded variables' value */
|
|
411
|
-
args: (DdbObj | string | boolean)[], {
|
|
412
|
-
|
|
420
|
+
args: (DdbObj | string | boolean)[], { listener, parse_object, }?: {
|
|
421
|
+
listener?: DdbMessageListener;
|
|
413
422
|
parse_object?: boolean;
|
|
414
423
|
}): Promise<DdbObj<DdbValue>>;
|
|
415
424
|
/** 解析服务端响应报文,返回去掉 header 的 data buf */
|
|
@@ -419,7 +428,7 @@ export declare class DDB {
|
|
|
419
428
|
/** 转换 js 数组为 DdbObj[] */
|
|
420
429
|
to_ddbobjs(values: any[]): DdbObj<DdbValue>[];
|
|
421
430
|
}
|
|
422
|
-
export interface
|
|
431
|
+
export interface DdbMessageListener {
|
|
423
432
|
(message: DdbMessage, _this: DDB): any;
|
|
424
433
|
}
|
|
425
434
|
export interface DdbPrintMessage {
|
package/browser.js
CHANGED
|
@@ -202,34 +202,60 @@ class DdbObj {
|
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
204
|
case DdbForm.matrix: {
|
|
205
|
-
//
|
|
205
|
+
// rename!(
|
|
206
|
+
// 1..9$3:3,
|
|
206
207
|
// [1, 2, 3],
|
|
207
|
-
// [
|
|
208
|
-
//
|
|
209
|
-
// <Buffer
|
|
210
|
-
//
|
|
211
|
-
//
|
|
212
|
-
// 01
|
|
208
|
+
// ['c1', 'c2', 'c3']
|
|
209
|
+
// )
|
|
210
|
+
// <Buffer 04 03 type = int, form = matrix
|
|
211
|
+
// 03 has_row_label (& 0x01) = 1, has_col_label (& 0x02) = 1
|
|
212
|
+
// row labels
|
|
213
|
+
// 04 01 type = int, form = vector
|
|
214
|
+
// 03 00 00 00 01 00 00 00 rows = 3, cols = 1
|
|
215
|
+
// 01 00 00 00 02 00 00 00 03 00 00 00 vector values
|
|
216
|
+
// col labels
|
|
217
|
+
// 12 01 type = string, form = vector
|
|
218
|
+
// 03 00 00 00 01 00 00 00 rows = 3, cols = 1
|
|
219
|
+
// 63 31 00 63 32 00 63 33 00
|
|
220
|
+
// matrix data
|
|
221
|
+
// 04 03 type = matrix.type, form = matrix
|
|
222
|
+
// 03 00 00 00 03 00 00 00 rows = 3, cols = 3
|
|
213
223
|
const dv = new DataView(buf.buffer, buf.byteOffset + i_data);
|
|
214
224
|
const label_flags = buf_data[0];
|
|
215
225
|
const has_row_labels = Boolean(label_flags & 0x01);
|
|
216
226
|
const has_col_labels = Boolean(label_flags & 0x02);
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
227
|
+
let row_labels = null;
|
|
228
|
+
let col_labels = null;
|
|
229
|
+
let offset = 1;
|
|
230
|
+
if (has_row_labels) {
|
|
231
|
+
row_labels = this.parse_vector(buf_data.subarray(offset + 2), le, buf_data[offset]);
|
|
232
|
+
row_labels.length += 2;
|
|
233
|
+
offset += row_labels.length;
|
|
234
|
+
}
|
|
235
|
+
if (has_col_labels) {
|
|
236
|
+
col_labels = this.parse_vector(buf_data.subarray(offset + 2), le, buf_data[offset]);
|
|
237
|
+
col_labels.length += 2;
|
|
238
|
+
offset += col_labels.length;
|
|
239
|
+
}
|
|
240
|
+
if (buf_data[offset] !== type)
|
|
241
|
+
throw new Error('matrix.datatype !== matrix.type');
|
|
242
|
+
const rows = dv.getUint32(offset + 2, le);
|
|
243
|
+
const cols = dv.getUint32(offset + 6, le);
|
|
244
|
+
const [len_items, data] = this.parse_vector_items(buf_data.subarray(offset + 10), le, type, rows * cols // 假设小于 2**32
|
|
223
245
|
);
|
|
246
|
+
offset += 10 + len_items;
|
|
224
247
|
return new this({
|
|
225
248
|
le,
|
|
226
249
|
form,
|
|
227
250
|
type,
|
|
228
|
-
length: i_data +
|
|
251
|
+
length: i_data + offset,
|
|
229
252
|
rows,
|
|
230
253
|
cols,
|
|
231
|
-
|
|
232
|
-
|
|
254
|
+
value: {
|
|
255
|
+
rows: row_labels,
|
|
256
|
+
cols: col_labels,
|
|
257
|
+
data,
|
|
258
|
+
},
|
|
233
259
|
});
|
|
234
260
|
}
|
|
235
261
|
default:
|
|
@@ -457,6 +483,7 @@ class DdbObj {
|
|
|
457
483
|
case DdbType.minute:
|
|
458
484
|
case DdbType.second:
|
|
459
485
|
case DdbType.datetime:
|
|
486
|
+
case DdbType.datehour:
|
|
460
487
|
return [
|
|
461
488
|
4 * length,
|
|
462
489
|
new Int32Array(buf.buffer.slice(buf.byteOffset, buf.byteOffset + 4 * length))
|
|
@@ -581,7 +608,7 @@ class DdbObj {
|
|
|
581
608
|
}
|
|
582
609
|
pack() {
|
|
583
610
|
const { form, type, value } = this;
|
|
584
|
-
let header = new Uint8Array(
|
|
611
|
+
let header = new Uint8Array(2);
|
|
585
612
|
header[0] = type;
|
|
586
613
|
header[1] = form;
|
|
587
614
|
const body = (() => {
|
|
@@ -722,12 +749,17 @@ class DdbObj {
|
|
|
722
749
|
value[0].pack(),
|
|
723
750
|
value[1].pack(),
|
|
724
751
|
];
|
|
725
|
-
case DdbForm.matrix:
|
|
752
|
+
case DdbForm.matrix: {
|
|
753
|
+
const { rows, cols, data } = value;
|
|
726
754
|
return [
|
|
727
|
-
Uint8Array.of(
|
|
755
|
+
Uint8Array.of((rows && 0x01) | (cols && 0x02)),
|
|
756
|
+
...rows ? [rows.pack()] : [],
|
|
757
|
+
...cols ? [cols.pack()] : [],
|
|
758
|
+
Uint8Array.of(this.type, this.form),
|
|
728
759
|
Uint32Array.of(this.rows, this.cols),
|
|
729
|
-
...DdbObj.pack_vector_body(
|
|
760
|
+
...DdbObj.pack_vector_body(data, this.type, this.rows * this.cols)
|
|
730
761
|
];
|
|
762
|
+
}
|
|
731
763
|
default:
|
|
732
764
|
throw new Error(`${DdbForm[form]} 暂不支持序列化`);
|
|
733
765
|
}
|
|
@@ -755,6 +787,7 @@ class DdbObj {
|
|
|
755
787
|
case DdbType.minute:
|
|
756
788
|
case DdbType.second:
|
|
757
789
|
case DdbType.datetime:
|
|
790
|
+
case DdbType.datehour:
|
|
758
791
|
return [value];
|
|
759
792
|
case DdbType.float:
|
|
760
793
|
return [value];
|
|
@@ -841,7 +874,7 @@ class DdbObj {
|
|
|
841
874
|
case DdbForm.dict:
|
|
842
875
|
return `dict<${DdbType[this.value[0].type]}, ${DdbType[this.value[1].type]}>`;
|
|
843
876
|
case DdbForm.matrix:
|
|
844
|
-
return `matrix<${DdbType[this.
|
|
877
|
+
return `matrix<${DdbType[this.type]}>[${this.rows} rows][${this.cols} cols]`;
|
|
845
878
|
default:
|
|
846
879
|
return `${DdbForm[this.form]} ${tname}`;
|
|
847
880
|
}
|
|
@@ -890,21 +923,26 @@ class DdbObj {
|
|
|
890
923
|
for (let i = 0; i < this.rows; i++) {
|
|
891
924
|
let row = {};
|
|
892
925
|
for (let j = 0; j < this.cols; j++) {
|
|
893
|
-
const { type, name, value } = this.value[j]; // column
|
|
926
|
+
const { type, name, value: values } = this.value[j]; // column
|
|
894
927
|
switch (type) {
|
|
895
|
-
case DdbType.bool:
|
|
896
|
-
|
|
928
|
+
case DdbType.bool: {
|
|
929
|
+
const value = values[i];
|
|
930
|
+
row[name] = value === exports.nulls.int8 ?
|
|
931
|
+
null
|
|
932
|
+
:
|
|
933
|
+
Boolean(value);
|
|
897
934
|
break;
|
|
935
|
+
}
|
|
898
936
|
case DdbType.ipaddr:
|
|
899
|
-
row[name] =
|
|
937
|
+
row[name] = values.subarray(16 * i, 16 * (i + 1));
|
|
900
938
|
break;
|
|
901
939
|
case DdbType.symbol_extended: {
|
|
902
|
-
const { base, data } =
|
|
940
|
+
const { base, data } = values;
|
|
903
941
|
row[name] = base[data[i]];
|
|
904
942
|
break;
|
|
905
943
|
}
|
|
906
944
|
default:
|
|
907
|
-
row[name] =
|
|
945
|
+
row[name] = values[i];
|
|
908
946
|
}
|
|
909
947
|
}
|
|
910
948
|
rows[i] = row;
|
|
@@ -1371,9 +1409,9 @@ class DDB {
|
|
|
1371
1409
|
this.print_object_buffer = false;
|
|
1372
1410
|
this.print_message = true;
|
|
1373
1411
|
this.parse_object = true;
|
|
1374
|
-
/**
|
|
1375
|
-
this.
|
|
1376
|
-
this.
|
|
1412
|
+
/** DdbMessage listeners */
|
|
1413
|
+
this.listeners = [];
|
|
1414
|
+
this.promise = Promise.resolve(null);
|
|
1377
1415
|
if (!url) {
|
|
1378
1416
|
const _url = new URL(location.href);
|
|
1379
1417
|
const hostname = _url.searchParams.get('hostname') || location.hostname;
|
|
@@ -1390,12 +1428,10 @@ class DDB {
|
|
|
1390
1428
|
if (options.python !== undefined)
|
|
1391
1429
|
this.python = options.python;
|
|
1392
1430
|
}
|
|
1393
|
-
/** resolver, rejector, promise of last rpc */
|
|
1394
|
-
presolver(ddbobj) { }
|
|
1395
|
-
prejector(error) { }
|
|
1396
1431
|
get connected() {
|
|
1397
1432
|
return this.websocket?.readyState === WebSocket.OPEN;
|
|
1398
1433
|
}
|
|
1434
|
+
on_message(event) { }
|
|
1399
1435
|
/** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
|
|
1400
1436
|
- options?:
|
|
1401
1437
|
- url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
|
|
@@ -1423,30 +1459,7 @@ class DDB {
|
|
|
1423
1459
|
await this.rpc('connect', {});
|
|
1424
1460
|
},
|
|
1425
1461
|
on_message: event => {
|
|
1426
|
-
|
|
1427
|
-
if (this.print_message_buffer)
|
|
1428
|
-
console.log(buf);
|
|
1429
|
-
const message = this.parse_message(buf);
|
|
1430
|
-
if (this.handlers.length) {
|
|
1431
|
-
const _handlers = [...this.handlers].reverse();
|
|
1432
|
-
for (const handler of _handlers)
|
|
1433
|
-
handler(message, this);
|
|
1434
|
-
}
|
|
1435
|
-
const { type, data } = message;
|
|
1436
|
-
switch (type) {
|
|
1437
|
-
case 'print':
|
|
1438
|
-
if (this.print_message)
|
|
1439
|
-
console.log(data);
|
|
1440
|
-
return;
|
|
1441
|
-
case 'object':
|
|
1442
|
-
if (this.print_object_buffer)
|
|
1443
|
-
console.log(data.buffer);
|
|
1444
|
-
this.presolver(data);
|
|
1445
|
-
return;
|
|
1446
|
-
case 'error':
|
|
1447
|
-
this.prejector(data);
|
|
1448
|
-
return;
|
|
1449
|
-
}
|
|
1462
|
+
this.on_message(event);
|
|
1450
1463
|
}
|
|
1451
1464
|
});
|
|
1452
1465
|
await this.eval(this.python ?
|
|
@@ -1524,45 +1537,64 @@ class DDB {
|
|
|
1524
1537
|
disconnect() {
|
|
1525
1538
|
if (this.connected)
|
|
1526
1539
|
this.websocket.close(1000);
|
|
1527
|
-
this.
|
|
1528
|
-
this.
|
|
1529
|
-
this.presult = Promise.resolve(null);
|
|
1540
|
+
this.on_message = () => { };
|
|
1541
|
+
this.promise = Promise.resolve(null);
|
|
1530
1542
|
}
|
|
1531
1543
|
/** rpc through websocket (function/script/variable command)
|
|
1532
1544
|
- type: API 类型: 'script' | 'function' | 'variable'
|
|
1533
1545
|
- options:
|
|
1534
1546
|
- urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
|
|
1535
1547
|
- vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
|
|
1536
|
-
-
|
|
1548
|
+
- listener?: 处理本次 rpc 期间的消息 (DdbMessage)
|
|
1537
1549
|
- parse_object?: 在本次 rpc 期间设置 parse_object, 结束后恢复原有
|
|
1538
1550
|
为 false 时返回的 DdbObj 仅含有 buffer 和 le,不做解析,以便后续转发、序列化
|
|
1539
1551
|
*/
|
|
1540
|
-
async rpc(type, { script, func, args = [], vars = [], urgent,
|
|
1552
|
+
async rpc(type, { script, func, args = [], vars = [], urgent, listener, parse_object, }) {
|
|
1541
1553
|
if (!this.websocket)
|
|
1542
1554
|
await this.connect();
|
|
1543
1555
|
if (!this.connected)
|
|
1544
1556
|
throw new Error(`${this.url} is already disconnected`);
|
|
1557
|
+
// this 上的当前配置需要在 message 到达后使用,先保存起来
|
|
1558
|
+
const _handlers = [...this.listeners].reverse();
|
|
1545
1559
|
// 临界区:保证多个 rpc 并发时形成 promise 链
|
|
1546
1560
|
// ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
|
|
1547
1561
|
// 违反世界观可能造成:
|
|
1548
1562
|
// 1. 并发多个请求只返回第一个结果(阻塞,需后续请求疏通)
|
|
1549
1563
|
// 2. windows 下 ddb server 返回多个相同的结果
|
|
1550
|
-
const ptail = this.
|
|
1551
|
-
let
|
|
1552
|
-
let
|
|
1553
|
-
const
|
|
1554
|
-
|
|
1555
|
-
|
|
1564
|
+
const ptail = this.promise;
|
|
1565
|
+
let resolve;
|
|
1566
|
+
let reject;
|
|
1567
|
+
const promise = this.promise = new Promise((_resolve, _reject) => {
|
|
1568
|
+
resolve = _resolve;
|
|
1569
|
+
reject = _reject;
|
|
1556
1570
|
});
|
|
1557
1571
|
try {
|
|
1558
1572
|
await ptail;
|
|
1559
1573
|
}
|
|
1560
1574
|
catch { }
|
|
1561
|
-
this.
|
|
1562
|
-
this.
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1575
|
+
// 临界区结束,只有一个 rpc 函数调用运行到这里,可以独占 this.on_message 然后写 WebSocket
|
|
1576
|
+
this.on_message = ({ data: buffer }) => {
|
|
1577
|
+
const buf = new Uint8Array(buffer);
|
|
1578
|
+
if (this.print_message_buffer)
|
|
1579
|
+
console.log(buf);
|
|
1580
|
+
const message = this.parse_message(buf, parse_object);
|
|
1581
|
+
listener?.(message, this);
|
|
1582
|
+
for (const listener of _handlers)
|
|
1583
|
+
listener(message, this);
|
|
1584
|
+
const { type, data } = message;
|
|
1585
|
+
switch (type) {
|
|
1586
|
+
case 'print':
|
|
1587
|
+
if (this.print_message)
|
|
1588
|
+
console.log(data);
|
|
1589
|
+
return;
|
|
1590
|
+
case 'object':
|
|
1591
|
+
resolve(data);
|
|
1592
|
+
return;
|
|
1593
|
+
case 'error':
|
|
1594
|
+
reject(data);
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1597
|
+
};
|
|
1566
1598
|
args = this.to_ddbobjs(args);
|
|
1567
1599
|
const command = this.enc.encode((() => {
|
|
1568
1600
|
switch (type) {
|
|
@@ -1583,37 +1615,24 @@ class DDB {
|
|
|
1583
1615
|
return 'connect\n';
|
|
1584
1616
|
}
|
|
1585
1617
|
})());
|
|
1586
|
-
|
|
1618
|
+
this.websocket.send((0, utils_browser_1.concat)([
|
|
1587
1619
|
this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
|
|
1588
1620
|
command,
|
|
1589
1621
|
...args.map((arg) => arg.pack())
|
|
1590
|
-
]);
|
|
1591
|
-
|
|
1592
|
-
if (handler)
|
|
1593
|
-
this.handlers.push(handler);
|
|
1594
|
-
if (parse_object !== undefined)
|
|
1595
|
-
this.parse_object = parse_object;
|
|
1596
|
-
try {
|
|
1597
|
-
this.websocket.send(message);
|
|
1598
|
-
return (await presult);
|
|
1599
|
-
}
|
|
1600
|
-
finally {
|
|
1601
|
-
if (handler)
|
|
1602
|
-
this.handlers = this.handlers.filter(h => h !== handler);
|
|
1603
|
-
this.parse_object = _parse_object;
|
|
1604
|
-
}
|
|
1622
|
+
]));
|
|
1623
|
+
return promise;
|
|
1605
1624
|
}
|
|
1606
1625
|
/** eval script through websocket (script command)
|
|
1607
1626
|
- script?: Script to execute
|
|
1608
1627
|
- options?: execution options
|
|
1609
1628
|
- urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
|
|
1610
|
-
-
|
|
1629
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
1611
1630
|
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
1612
1631
|
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
1613
1632
|
so as to facilitate subsequent forwarding and serialization
|
|
1614
1633
|
*/
|
|
1615
|
-
async eval(script, { urgent,
|
|
1616
|
-
return this.rpc('script', { script, urgent,
|
|
1634
|
+
async eval(script, { urgent, listener, parse_object, } = {}) {
|
|
1635
|
+
return this.rpc('script', { script, urgent, listener, parse_object });
|
|
1617
1636
|
}
|
|
1618
1637
|
/** call function through websocket (function command)
|
|
1619
1638
|
- func: function name
|
|
@@ -1624,12 +1643,12 @@ class DDB {
|
|
|
1624
1643
|
- nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
|
|
1625
1644
|
- 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
|
|
1626
1645
|
- add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
|
|
1627
|
-
-
|
|
1646
|
+
- listener?: Process messages during this rpc (DdbMessage)
|
|
1628
1647
|
- parse_object?: Set parse_object during this rpc, and restore the original after the end.
|
|
1629
1648
|
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
1630
1649
|
so as to facilitate subsequent forwarding and serialization
|
|
1631
1650
|
*/
|
|
1632
|
-
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias,
|
|
1651
|
+
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, } = {}) {
|
|
1633
1652
|
if (node) {
|
|
1634
1653
|
if (typeof func_type === 'undefined')
|
|
1635
1654
|
throw new Error('指定 node 时必须设置 func_type');
|
|
@@ -1659,7 +1678,7 @@ class DDB {
|
|
|
1659
1678
|
func,
|
|
1660
1679
|
args,
|
|
1661
1680
|
urgent,
|
|
1662
|
-
|
|
1681
|
+
listener,
|
|
1663
1682
|
parse_object
|
|
1664
1683
|
});
|
|
1665
1684
|
}
|
|
@@ -1668,10 +1687,10 @@ class DDB {
|
|
|
1668
1687
|
/** Uploaded variables' name */
|
|
1669
1688
|
vars,
|
|
1670
1689
|
/** Uploaded variables' value */
|
|
1671
|
-
args, {
|
|
1690
|
+
args, { listener, parse_object, } = {}) {
|
|
1672
1691
|
if (!args.length || args.length !== vars.length)
|
|
1673
1692
|
throw new Error('variable 指令参数为空或参数名为空,或数量不匹配');
|
|
1674
|
-
return this.rpc('variable', { vars, args,
|
|
1693
|
+
return this.rpc('variable', { vars, args, listener, parse_object });
|
|
1675
1694
|
}
|
|
1676
1695
|
/** 解析服务端响应报文,返回去掉 header 的 data buf */
|
|
1677
1696
|
parse_message(buf, parse_object = this.parse_object) {
|
|
@@ -1709,10 +1728,12 @@ class DDB {
|
|
|
1709
1728
|
data: new Error(message)
|
|
1710
1729
|
};
|
|
1711
1730
|
const buf_obj = buf.subarray(i_lf_1 + 1);
|
|
1731
|
+
if (this.print_object_buffer)
|
|
1732
|
+
console.log(buf_obj);
|
|
1712
1733
|
return {
|
|
1713
1734
|
type: 'object',
|
|
1714
1735
|
data: parse_object ?
|
|
1715
|
-
|
|
1736
|
+
DdbObj.parse(buf_obj, this.le)
|
|
1716
1737
|
:
|
|
1717
1738
|
new DdbObj({
|
|
1718
1739
|
form: DdbForm.scalar,
|