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