dolphindb 2.0.506 → 2.0.507

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/index.d.ts CHANGED
@@ -127,12 +127,11 @@ export declare class DdbObj<T extends DdbValue = DdbValue> {
127
127
  datatype?: DdbType;
128
128
  /** 实际数据。不同的 DdbForm, DdbType 使用 DdbValue 中不同的类型来表示实际数据 */
129
129
  value: T;
130
- /** 原始二进制数据 */
130
+ /** 原始二进制数据,仅在 parse_object 为 false 时通过 parse_message 生成的顶层对象有这个属性 */
131
131
  buffer?: Uint8Array;
132
132
  constructor(data: Partial<DdbObj> & {
133
133
  form: DdbForm;
134
134
  type: DdbType;
135
- length: number;
136
135
  });
137
136
  static parse(buf: Uint8Array, le: boolean): DdbObj<DdbValue>;
138
137
  static parse_scalar(buf: Uint8Array, le: boolean, type: DdbType): [number, DdbValue];
@@ -273,12 +272,9 @@ export declare class DDB {
273
272
  print_object_buffer: boolean;
274
273
  print_message: boolean;
275
274
  parse_object: boolean;
276
- /** message handlers */
277
- handlers: DdbMessageHandler[];
278
- /** resolver, rejector, promise of last rpc */
279
- presolver(ddbobj: DdbObj): void;
280
- prejector(error: Error): void;
281
- presult: Promise<DdbObj<DdbValue>>;
275
+ /** DdbMessage listeners */
276
+ listeners: DdbMessageListener[];
277
+ promise: Promise<any>;
282
278
  get connected(): boolean;
283
279
  /**
284
280
  Initialize an instance of DolphinDB Client using the WebSocket URL
@@ -307,6 +303,7 @@ export declare class DDB {
307
303
  password?: string;
308
304
  python?: boolean;
309
305
  });
306
+ private on_message;
310
307
  /** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
311
308
  - options?:
312
309
  - url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
@@ -351,52 +348,54 @@ export declare class DDB {
351
348
  - options:
352
349
  - urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
353
350
  - vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
354
- - handler?: 处理本次 rpc 期间的消息
351
+ - handler?: Process messages during this rpc (DdbMessage)
355
352
  - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
356
353
  不做解析,以便后续转发、序列化
357
354
  */
358
- rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, handler, parse_object, }: {
355
+ rpc<T extends DdbObj = DdbObj>(type: 'script' | 'function' | 'variable' | 'connect', { script, func, args, vars, urgent, listener, parse_object, }: {
359
356
  script?: string;
360
357
  func?: string;
361
358
  args?: (DdbObj | string | boolean)[];
362
359
  vars?: string[];
363
360
  urgent?: boolean;
364
- handler?: DdbMessageHandler;
361
+ listener?: DdbMessageListener;
365
362
  parse_object?: boolean;
366
363
  }): Promise<T>;
367
364
  /** eval script through websocket (script command)
368
- - script?: 执行的脚本
369
- - options?: 执行选项
370
- - urgent?: 紧急 flag,确保提交的脚本使用 urgent worker 处理,防止被其它作业阻塞
371
- - handler?: 处理本次 rpc 期间的消息
372
- - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
373
- 不做解析,以便后续转发、序列化
365
+ - script?: Script to execute
366
+ - options?: execution options
367
+ - urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
368
+ - listener?: Process messages during this rpc (DdbMessage)
369
+ - parse_object?: Set parse_object during this rpc, and restore the original after the end.
370
+ When it is false, the returned DdbObj only contains buffer and le without parsing,
371
+ so as to facilitate subsequent forwarding and serialization
374
372
  */
375
- eval<T extends DdbObj>(script: string, { urgent, handler, parse_object, }?: {
373
+ eval<T extends DdbObj>(script: string, { urgent, listener, parse_object, }?: {
376
374
  urgent?: boolean;
377
- handler?: DdbMessageHandler;
375
+ listener?: DdbMessageListener;
378
376
  parse_object?: boolean;
379
377
  }): Promise<T>;
380
378
  /** call function through websocket (function command)
381
- - func: 函数名
382
- - args?: `[ ]` 调用参数 (传入的原生 string 和 boolean 会被自动转换为 DdbObj<string> 和 DdbObj<boolean>)
383
- - options?: 调用选项
384
- - urgent?: 紧急 flag。使用 urgent worker 执行,防止被其它作业阻塞
385
- - node?: 设置结点 alias 时发送到集群中对应的结点执行 (使用 DolphinDB 中的 rpc 方法)
386
- - nodes?: 设置多个结点 alias 时发送到集群中对应的多个结点执行 (使用 DolphinDB 中的 pnodeRun 方法)
387
- - func_type?: 设置 node 参数时必传,需指定函数类型,其它情况下不传
388
- - add_node_alias?: 设置 nodes 参数时选传,其它情况不传
389
- - handler?: 处理本次 rpc 期间的消息
390
- - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
391
- 不做解析,以便后续转发、序列化
379
+ - func: function name
380
+ - args?: `[ ]` Call parameters (the incoming native string and boolean will be automatically converted to DdbObj<string> and DdbObj<boolean>)
381
+ - options?: call options
382
+ - urgent?: Emergency flag. Use urgent worker execution to prevent being blocked by other jobs
383
+ - 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)
384
+ - nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
385
+ - 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
386
+ - add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
387
+ - listener?: Process messages during this rpc (DdbMessage)
388
+ - parse_object?: Set parse_object during this rpc, and restore the original after the end.
389
+ When it is false, the returned DdbObj only contains buffer and le without parsing,
390
+ so as to facilitate subsequent forwarding and serialization
392
391
  */
393
- call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias, handler, parse_object, }?: {
392
+ call<T extends DdbObj>(func: string, args?: (DdbObj | string | boolean)[], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, }?: {
394
393
  urgent?: boolean;
395
394
  node?: string;
396
395
  nodes?: string[];
397
396
  func_type?: DdbFunctionType;
398
397
  add_node_alias?: boolean;
399
- handler?: DdbMessageHandler;
398
+ listener?: DdbMessageListener;
400
399
  parse_object?: boolean;
401
400
  }): Promise<T>;
402
401
  /** upload variable through websocket (variable command) */
@@ -404,8 +403,8 @@ export declare class DDB {
404
403
  /** Uploaded variables' name */
405
404
  vars: string[],
406
405
  /** Uploaded variables' value */
407
- args: (DdbObj | string | boolean)[], { handler, parse_object, }?: {
408
- handler?: DdbMessageHandler;
406
+ args: (DdbObj | string | boolean)[], { listener, parse_object, }?: {
407
+ listener?: DdbMessageListener;
409
408
  parse_object?: boolean;
410
409
  }): Promise<DdbObj<DdbValue>>;
411
410
  /** 解析服务端响应报文,返回去掉 header 的 data buf */
@@ -415,7 +414,7 @@ export declare class DDB {
415
414
  /** 转换 js 数组为 DdbObj[] */
416
415
  to_ddbobjs(values: any[]): DdbObj<DdbValue>[];
417
416
  }
418
- export interface DdbMessageHandler {
417
+ export interface DdbMessageListener {
419
418
  (message: DdbMessage, _this: DDB): any;
420
419
  }
421
420
  export interface DdbPrintMessage {
package/index.js CHANGED
@@ -907,21 +907,26 @@ class DdbObj {
907
907
  for (let i = 0; i < this.rows; i++) {
908
908
  let row = {};
909
909
  for (let j = 0; j < this.cols; j++) {
910
- const { type, name, value } = this.value[j]; // column
910
+ const { type, name, value: values } = this.value[j]; // column
911
911
  switch (type) {
912
- case DdbType.bool:
913
- row[name] = Boolean(value[i]);
912
+ case DdbType.bool: {
913
+ const value = values[i];
914
+ row[name] = value === exports.nulls.int8 ?
915
+ null
916
+ :
917
+ Boolean(value);
914
918
  break;
919
+ }
915
920
  case DdbType.ipaddr:
916
- row[name] = value.subarray(16 * i, 16 * (i + 1));
921
+ row[name] = values.subarray(16 * i, 16 * (i + 1));
917
922
  break;
918
923
  case DdbType.symbol_extended: {
919
- const { base, data } = value;
924
+ const { base, data } = values;
920
925
  row[name] = base[data[i]];
921
926
  break;
922
927
  }
923
928
  default:
924
- row[name] = value[i];
929
+ row[name] = values[i];
925
930
  }
926
931
  }
927
932
  rows[i] = row;
@@ -1388,9 +1393,9 @@ class DDB {
1388
1393
  this.print_object_buffer = false;
1389
1394
  this.print_message = true;
1390
1395
  this.parse_object = true;
1391
- /** message handlers */
1392
- this.handlers = [];
1393
- this.presult = Promise.resolve(null);
1396
+ /** DdbMessage listeners */
1397
+ this.listeners = [];
1398
+ this.promise = Promise.resolve(null);
1394
1399
  this.url = url;
1395
1400
  if (options.autologin !== undefined)
1396
1401
  this.autologin = options.autologin;
@@ -1401,12 +1406,10 @@ class DDB {
1401
1406
  if (options.python !== undefined)
1402
1407
  this.python = options.python;
1403
1408
  }
1404
- /** resolver, rejector, promise of last rpc */
1405
- presolver(ddbobj) { }
1406
- prejector(error) { }
1407
1409
  get connected() {
1408
1410
  return this.websocket?.readyState === ws_1.WebSocket.OPEN;
1409
1411
  }
1412
+ on_message(event) { }
1410
1413
  /** Establish the actual WebSocket connection to the DolphinDB corresponding to the URL
1411
1414
  - options?:
1412
1415
  - url?: DolphinDB WebSocket URL. By default, the WebSocket URL passed in when the instance is initialized is used
@@ -1434,30 +1437,7 @@ class DDB {
1434
1437
  await this.rpc('connect', {});
1435
1438
  },
1436
1439
  on_message: event => {
1437
- const buf = new Uint8Array(event.data);
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
- }
1440
+ this.on_message(event);
1461
1441
  }
1462
1442
  });
1463
1443
  await this.eval(this.python ?
@@ -1535,45 +1515,64 @@ class DDB {
1535
1515
  disconnect() {
1536
1516
  if (this.connected)
1537
1517
  this.websocket.close(1000);
1538
- this.presolver = buf => { };
1539
- this.prejector = error => { };
1540
- this.presult = Promise.resolve(null);
1518
+ this.on_message = () => { };
1519
+ this.promise = Promise.resolve(null);
1541
1520
  }
1542
1521
  /** rpc through websocket (function/script/variable command)
1543
1522
  - type: API 类型: 'script' | 'function' | 'variable'
1544
1523
  - options:
1545
1524
  - urgent?: 决定 `行为标识` 那一行字符串的取值(只适用于 script 和 function)
1546
1525
  - vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
1547
- - handler?: 处理本次 rpc 期间的消息
1526
+ - handler?: Process messages during this rpc (DdbMessage)
1548
1527
  - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
1549
1528
  不做解析,以便后续转发、序列化
1550
1529
  */
1551
- async rpc(type, { script, func, args = [], vars = [], urgent, handler, parse_object, }) {
1530
+ async rpc(type, { script, func, args = [], vars = [], urgent, listener, parse_object, }) {
1552
1531
  if (!this.websocket)
1553
1532
  await this.connect();
1554
1533
  if (!this.connected)
1555
1534
  throw new Error(`${this.url} is already disconnected`);
1535
+ // this 上的当前配置需要在 message 到达后使用,先保存起来
1536
+ const _handlers = [...this.listeners].reverse();
1556
1537
  // 临界区:保证多个 rpc 并发时形成 promise 链
1557
1538
  // ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
1558
1539
  // 违反世界观可能造成:
1559
1540
  // 1. 并发多个请求只返回第一个结果(阻塞,需后续请求疏通)
1560
1541
  // 2. windows 下 ddb server 返回多个相同的结果
1561
- const ptail = this.presult;
1562
- let presolver;
1563
- let prejector;
1564
- const presult = this.presult = new Promise((resolve, reject) => {
1565
- presolver = resolve;
1566
- prejector = reject;
1542
+ const ptail = this.promise;
1543
+ let resolve;
1544
+ let reject;
1545
+ const promise = this.promise = new Promise((_resolve, _reject) => {
1546
+ resolve = _resolve;
1547
+ reject = _reject;
1567
1548
  });
1568
1549
  try {
1569
1550
  await ptail;
1570
1551
  }
1571
1552
  catch { }
1572
- this.presolver = presolver;
1573
- this.prejector = prejector;
1574
- // 临界区结束,只有一个 rpc 请求可以写 WebSocket
1575
- if (urgent && type !== 'script' && type !== 'function')
1576
- throw new Error('urgent 只适用于 script 和 funciton');
1553
+ // 临界区结束,只有一个 rpc 函数调用运行到这里,可以独占 this.on_message 然后写 WebSocket
1554
+ this.on_message = ({ data: buffer }) => {
1555
+ const buf = new Uint8Array(buffer);
1556
+ if (this.print_message_buffer)
1557
+ console.log((0, utils_js_1.typed_array_to_buffer)(buf));
1558
+ const message = this.parse_message(buf, parse_object);
1559
+ listener?.(message, this);
1560
+ for (const listener of _handlers)
1561
+ listener(message, this);
1562
+ const { type, data } = message;
1563
+ switch (type) {
1564
+ case 'print':
1565
+ if (this.print_message)
1566
+ console.log(data);
1567
+ return;
1568
+ case 'object':
1569
+ resolve(data);
1570
+ return;
1571
+ case 'error':
1572
+ reject(data);
1573
+ return;
1574
+ }
1575
+ };
1577
1576
  args = this.to_ddbobjs(args);
1578
1577
  const command = this.enc.encode((() => {
1579
1578
  switch (type) {
@@ -1594,51 +1593,40 @@ class DDB {
1594
1593
  return 'connect\n';
1595
1594
  }
1596
1595
  })());
1597
- const message = (0, utils_js_1.concat)([
1596
+ this.websocket.send((0, utils_js_1.concat)([
1598
1597
  this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
1599
1598
  command,
1600
1599
  ...args.map((arg) => arg.pack())
1601
- ]);
1602
- const _parse_object = this.parse_object;
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
- }
1600
+ ]));
1601
+ return promise;
1616
1602
  }
1617
1603
  /** eval script through websocket (script command)
1618
- - script?: 执行的脚本
1619
- - options?: 执行选项
1620
- - urgent?: 紧急 flag,确保提交的脚本使用 urgent worker 处理,防止被其它作业阻塞
1621
- - handler?: 处理本次 rpc 期间的消息
1622
- - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
1623
- 不做解析,以便后续转发、序列化
1604
+ - script?: Script to execute
1605
+ - options?: execution options
1606
+ - urgent?: Urgent flag to ensure that submitted scripts are processed by urgent workers to prevent being blocked by other jobs
1607
+ - listener?: Process messages during this rpc (DdbMessage)
1608
+ - parse_object?: Set parse_object during this rpc, and restore the original after the end.
1609
+ When it is false, the returned DdbObj only contains buffer and le without parsing,
1610
+ so as to facilitate subsequent forwarding and serialization
1624
1611
  */
1625
- async eval(script, { urgent, handler, parse_object, } = {}) {
1626
- return this.rpc('script', { script, urgent, handler, parse_object });
1612
+ async eval(script, { urgent, listener, parse_object, } = {}) {
1613
+ return this.rpc('script', { script, urgent, listener, parse_object });
1627
1614
  }
1628
1615
  /** call function through websocket (function command)
1629
- - func: 函数名
1630
- - args?: `[ ]` 调用参数 (传入的原生 string 和 boolean 会被自动转换为 DdbObj<string> 和 DdbObj<boolean>)
1631
- - options?: 调用选项
1632
- - urgent?: 紧急 flag。使用 urgent worker 执行,防止被其它作业阻塞
1633
- - node?: 设置结点 alias 时发送到集群中对应的结点执行 (使用 DolphinDB 中的 rpc 方法)
1634
- - nodes?: 设置多个结点 alias 时发送到集群中对应的多个结点执行 (使用 DolphinDB 中的 pnodeRun 方法)
1635
- - func_type?: 设置 node 参数时必传,需指定函数类型,其它情况下不传
1636
- - add_node_alias?: 设置 nodes 参数时选传,其它情况不传
1637
- - handler?: 处理本次 rpc 期间的消息
1638
- - parse_object?: 在该次 rpc 期间设置 parse_object, 结束后恢复原有,为 false 时返回的 DdbObj 仅含有 buffer 和 le,
1639
- 不做解析,以便后续转发、序列化
1616
+ - func: function name
1617
+ - args?: `[ ]` Call parameters (the incoming native string and boolean will be automatically converted to DdbObj<string> and DdbObj<boolean>)
1618
+ - options?: call options
1619
+ - urgent?: Emergency flag. Use urgent worker execution to prevent being blocked by other jobs
1620
+ - 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)
1621
+ - nodes?: When setting multiple node aliases, send them to the corresponding multiple nodes in the cluster for execution (using the pnodeRun method in DolphinDB)
1622
+ - 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
1623
+ - add_node_alias?: Select to pass when setting the nodes parameter, otherwise not pass
1624
+ - listener?: Process messages during this rpc (DdbMessage)
1625
+ - parse_object?: Set parse_object during this rpc, and restore the original after the end.
1626
+ When it is false, the returned DdbObj only contains buffer and le without parsing,
1627
+ so as to facilitate subsequent forwarding and serialization
1640
1628
  */
1641
- async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, handler, parse_object, } = {}) {
1629
+ async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, } = {}) {
1642
1630
  if (node) {
1643
1631
  if (typeof func_type === 'undefined')
1644
1632
  throw new Error('指定 node 时必须设置 func_type');
@@ -1668,7 +1656,7 @@ class DDB {
1668
1656
  func,
1669
1657
  args,
1670
1658
  urgent,
1671
- handler,
1659
+ listener,
1672
1660
  parse_object
1673
1661
  });
1674
1662
  }
@@ -1677,10 +1665,10 @@ class DDB {
1677
1665
  /** Uploaded variables' name */
1678
1666
  vars,
1679
1667
  /** Uploaded variables' value */
1680
- args, { handler, parse_object, } = {}) {
1668
+ args, { listener, parse_object, } = {}) {
1681
1669
  if (!args.length || args.length !== vars.length)
1682
1670
  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, handler, parse_object });
1671
+ return this.rpc('variable', { vars, args, listener, parse_object });
1684
1672
  }
1685
1673
  /** 解析服务端响应报文,返回去掉 header 的 data buf */
1686
1674
  parse_message(buf, parse_object = this.parse_object) {
@@ -1718,10 +1706,12 @@ class DDB {
1718
1706
  data: new Error(message)
1719
1707
  };
1720
1708
  const buf_obj = buf.subarray(i_lf_1 + 1);
1709
+ if (this.print_object_buffer)
1710
+ console.log((0, utils_js_1.typed_array_to_buffer)(buf_obj));
1721
1711
  return {
1722
1712
  type: 'object',
1723
1713
  data: parse_object ?
1724
- Object.assign(DdbObj.parse(buf_obj, this.le), { buffer: buf_obj })
1714
+ DdbObj.parse(buf_obj, this.le)
1725
1715
  :
1726
1716
  new DdbObj({
1727
1717
  form: DdbForm.scalar,