dolphindb 2.0.1022 → 2.0.1024

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.js CHANGED
@@ -2255,7 +2255,7 @@ export class DDB {
2255
2255
  this.lwebsocket.resource = await connect_websocket(this.url, {
2256
2256
  protocols: this.streaming ? ['streaming'] : this.python ? ['python'] : undefined,
2257
2257
  on_message: (buffer, websocket) => {
2258
- this.on_message(buffer, websocket);
2258
+ this.on_message(new Uint8Array(buffer), websocket);
2259
2259
  },
2260
2260
  on_error: error => {
2261
2261
  this.error ??= new DdbConnectionError(this.url, error);
@@ -2341,7 +2341,7 @@ export class DDB {
2341
2341
  let error = new DdbDatabaseError('', this.url, type, options, id);
2342
2342
  if (!options.skip_connection_check)
2343
2343
  await this.connect();
2344
- const { script, func, args: _args = [], vars = [], urgent, listener, } = options;
2344
+ const { script, func, args: _args = [], vars = [], urgent, listener, on_more_messages, } = options;
2345
2345
  if (func === 'pnode_run')
2346
2346
  await (this.ppnode_run ??= this.eval(this.python ?
2347
2347
  '\n' +
@@ -2442,37 +2442,42 @@ export class DDB {
2442
2442
  })());
2443
2443
  // 使用资源发送请求并等待请求完成
2444
2444
  const result = await new Promise((resolve, reject) => {
2445
+ let first_message = true;
2445
2446
  this.on_error = () => {
2446
2447
  // 这里一定有了 this.error, 不需要再 || new DdbConnectionError(this)
2447
2448
  reject(this.error);
2448
2449
  };
2449
2450
  this.on_message = buffer => {
2450
- try {
2451
- const buf = new Uint8Array(buffer);
2452
- if (this.print_message_buffer)
2453
- console.log(typed_array_to_buffer(buf));
2454
- const message = this.parse_message(buf, error);
2455
- listener?.(message, this);
2456
- for (const listener of _listeners)
2457
- listener(message, this);
2458
- const { type, data } = message;
2459
- switch (type) {
2460
- case 'print':
2461
- if (this.print_message)
2462
- console.log(data);
2463
- break;
2464
- case 'object':
2465
- resolve(data);
2466
- break;
2467
- case 'error':
2468
- reject(data);
2469
- break;
2451
+ if (!on_more_messages || first_message)
2452
+ try {
2453
+ if (this.print_message_buffer)
2454
+ console.log(typed_array_to_buffer(buffer));
2455
+ const message = this.parse_message(buffer, error);
2456
+ listener?.(message, this);
2457
+ for (const listener of _listeners)
2458
+ listener(message, this);
2459
+ const { type, data } = message;
2460
+ switch (type) {
2461
+ case 'print':
2462
+ if (this.print_message)
2463
+ console.log(data);
2464
+ break;
2465
+ case 'object':
2466
+ first_message = false;
2467
+ resolve(data);
2468
+ break;
2469
+ case 'error':
2470
+ first_message = false;
2471
+ reject(data);
2472
+ break;
2473
+ }
2470
2474
  }
2471
- }
2472
- catch (error) {
2473
- // 这里的错误并非 websocket 错误,而是 rpc 错误
2474
- reject(error);
2475
- }
2475
+ catch (error) {
2476
+ // 这里的错误并非 websocket 错误,而是 rpc 错误
2477
+ reject(error);
2478
+ }
2479
+ else
2480
+ on_more_messages(buffer);
2476
2481
  };
2477
2482
  websocket.send(concat([
2478
2483
  this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
@@ -2526,7 +2531,7 @@ export class DDB {
2526
2531
  将这个 flag 设为 true 跳过连接状态检查
2527
2532
  (internal use) When await ddb.connect() establishes a connection for the first time, you cannot call await this.connect() again to ensure the connection status, which will lead to circular dependencies.
2528
2533
  Set this flag to true to skip connection status checks */
2529
- async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, skip_connection_check } = {}) {
2534
+ async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, skip_connection_check, on_more_messages } = {}) {
2530
2535
  if (node) {
2531
2536
  assert(func_type in DdbFunctionType, t('指定 node 时必须设置 func_type'));
2532
2537
  args = [
@@ -2557,7 +2562,8 @@ export class DDB {
2557
2562
  urgent,
2558
2563
  listener,
2559
2564
  parse_object,
2560
- skip_connection_check
2565
+ skip_connection_check,
2566
+ on_more_messages
2561
2567
  });
2562
2568
  }
2563
2569
  /** upload variable through websocket (variable command) */
@@ -2639,6 +2645,12 @@ export class DDB {
2639
2645
  }
2640
2646
  /** 内部的流订阅方法 Internal stream subscription method */
2641
2647
  async subscribe() {
2648
+ let win = {
2649
+ offset: 0,
2650
+ rows: 0,
2651
+ segments: [],
2652
+ };
2653
+ let schema;
2642
2654
  const { value: colnames } = await this.call('publishTable', [
2643
2655
  'localhost',
2644
2656
  new DdbInt(0),
@@ -2647,58 +2659,54 @@ export class DDB {
2647
2659
  // new DdbInt(-1), // offset
2648
2660
  // filter
2649
2661
  // allow exists
2650
- ], { skip_connection_check: true });
2651
- console.log(t('订阅流表成功') + ', colnames:',
2652
- // string[3](['time', 'stock', 'price'])
2653
- colnames);
2654
- let win = {
2655
- offset: 0,
2656
- rows: 0,
2657
- segments: [],
2658
- };
2659
- let schema;
2660
- // 先准备好收到 websocket message 的 callback
2661
- this.on_message = buffer => {
2662
- try {
2663
- const dv = new DataView(buffer);
2664
- const buf = new Uint8Array(buffer);
2665
- const i_topic_end = buf.indexOf(0, 17);
2666
- // 首个 message 可能是 table schema, 后续消息是 column 片段组成的 any vector
2667
- const data = DdbObj.parse(buf.subarray(i_topic_end + 1), this.le);
2668
- if (data.form === DdbForm.table) {
2669
- schema = data;
2670
- return;
2662
+ ], {
2663
+ skip_connection_check: true,
2664
+ // 先准备好收到 websocket message 的 callback
2665
+ on_more_messages: buffer => {
2666
+ try {
2667
+ const dv = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
2668
+ const i_topic_end = buffer.indexOf(0, 17);
2669
+ // 首个 message 一定是 table schema, 后续消息是 column 片段组成的 any vector
2670
+ const data = DdbObj.parse(buffer.subarray(i_topic_end + 1), this.le);
2671
+ if (data.form === DdbForm.table) {
2672
+ schema = data;
2673
+ return;
2674
+ }
2675
+ assert(schema, t('流数据订阅后一定先返回 schema'));
2676
+ const { rows } = data.value[0];
2677
+ win.rows += rows;
2678
+ win.segments.push(data);
2679
+ if (win.rows >= winsize * 2 && win.segments.length >= 2) {
2680
+ let winsize_ = 0;
2681
+ let i = win.segments.length - 1;
2682
+ // 往前移动至首个累计 winsize_ 超过 winsize 的位置
2683
+ for (; winsize_ < winsize; i--)
2684
+ winsize_ += win.segments[i].value[0].rows;
2685
+ win.segments = win.segments.slice(i);
2686
+ win.offset += win.rows - winsize_;
2687
+ win.rows = winsize_;
2688
+ }
2689
+ this.streaming.handler({
2690
+ ...this.streaming,
2691
+ id: dv.getBigInt64(9, this.le),
2692
+ time: dv.getBigInt64(1, this.le),
2693
+ rows,
2694
+ topic: this.dec.decode(buffer.subarray(17, i_topic_end)),
2695
+ colnames,
2696
+ schema,
2697
+ data,
2698
+ window: win,
2699
+ });
2671
2700
  }
2672
- const { rows } = data.value[0];
2673
- win.rows += rows;
2674
- win.segments.push(data);
2675
- if (win.rows >= winsize * 2 && win.segments.length >= 2) {
2676
- let winsize_ = 0;
2677
- let i = win.segments.length - 1;
2678
- // 往前移动至首个累计 winsize_ 超过 winsize 的位置
2679
- for (; winsize_ < winsize; i--)
2680
- winsize_ += win.segments[i].value[0].rows;
2681
- win.segments = win.segments.slice(i);
2682
- win.offset += win.rows - winsize_;
2683
- win.rows = winsize_;
2701
+ catch (error) {
2702
+ // 将 error 交给 handler 处理
2703
+ this.streaming.handler({ ...this.streaming, error });
2684
2704
  }
2685
- this.streaming.handler({
2686
- ...this.streaming,
2687
- id: dv.getBigInt64(9, this.le),
2688
- time: dv.getBigInt64(1, this.le),
2689
- rows,
2690
- topic: this.dec.decode(buf.subarray(17, i_topic_end)),
2691
- colnames,
2692
- schema,
2693
- data,
2694
- window: win,
2695
- });
2696
2705
  }
2697
- catch (error) {
2698
- // 将 error 交给 handler 处理
2699
- this.streaming.handler({ ...this.streaming, error });
2700
- }
2701
- };
2706
+ });
2707
+ console.log(t('订阅流表成功') + ', colnames:',
2708
+ // string[3](['time', 'stock', 'price'])
2709
+ colnames);
2702
2710
  }
2703
2711
  }
2704
2712
  // const ddb_gateway = {