dolphindb 2.0.801 → 2.0.901
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/README.md +80 -5
- package/README.zh.md +83 -9
- package/browser.d.ts +22 -25
- package/browser.js +155 -133
- package/browser.js.map +1 -1
- package/docs.en.json +492 -49
- package/docs.zh.json +433 -100
- package/index.d.ts +22 -25
- package/index.js +151 -130
- package/index.js.map +1 -1
- package/language.d.ts +5 -5
- package/language.js +3 -1
- package/language.js.map +1 -1
- package/package.json +7 -7
package/browser.js
CHANGED
|
@@ -118,15 +118,6 @@ export const nulls = {
|
|
|
118
118
|
double: -Number.MAX_VALUE,
|
|
119
119
|
bytes16: Uint8Array.from(new Array(16).fill(0))
|
|
120
120
|
};
|
|
121
|
-
export const timezone_offset = 1000 * 60 * new Date().getTimezoneOffset();
|
|
122
|
-
export var StreamingStatusCode;
|
|
123
|
-
(function (StreamingStatusCode) {
|
|
124
|
-
StreamingStatusCode[StreamingStatusCode["ok"] = 0] = "ok";
|
|
125
|
-
StreamingStatusCode[StreamingStatusCode["connection_existed"] = 1] = "connection_existed";
|
|
126
|
-
StreamingStatusCode[StreamingStatusCode["not_leader"] = 2] = "not_leader";
|
|
127
|
-
StreamingStatusCode[StreamingStatusCode["other"] = 3] = "other";
|
|
128
|
-
StreamingStatusCode[StreamingStatusCode["error"] = 4] = "error";
|
|
129
|
-
})(StreamingStatusCode = StreamingStatusCode || (StreamingStatusCode = {}));
|
|
130
121
|
/** 可以表示所有 DolphinDB 数据库中的数据类型 */
|
|
131
122
|
export class DdbObj {
|
|
132
123
|
static dec = new TextDecoder('utf-8');
|
|
@@ -522,8 +513,37 @@ export class DdbObj {
|
|
|
522
513
|
// 00 reserved
|
|
523
514
|
// 70 11 01 00 block.lengths = [70000 (0x00011170)]
|
|
524
515
|
// 01 00 00 00 02 00 00 00 ... 279992 more bytes> block.data
|
|
516
|
+
// decimal array vector
|
|
517
|
+
// a = array(DECIMAL32(2)[], 0, 10)
|
|
518
|
+
// append!(a, [
|
|
519
|
+
// [1, 2, 3],
|
|
520
|
+
// [4, 5],
|
|
521
|
+
// [6, 7, 8],
|
|
522
|
+
// [9, 10]
|
|
523
|
+
// ])
|
|
524
|
+
// print(a)
|
|
525
|
+
// a
|
|
526
|
+
// [[1.00,2.00,3.00],[4.00,5.00],[6.00,7.00,8.00],[9.00,10.00]]
|
|
527
|
+
// <Buffer 65 01 type = 101 = 64 + 37 (decimal32) , form = vector
|
|
528
|
+
// 04 00 00 00 0a 00 00 00 rows = 4, cols = 10
|
|
529
|
+
// scale (只有 decimal32 才有)
|
|
530
|
+
// 02 00 00 00 scale = 2
|
|
531
|
+
// block 0
|
|
532
|
+
// 04 00 block.rows = 4
|
|
533
|
+
// 01 block.unit = 1
|
|
534
|
+
// 00 reserved
|
|
535
|
+
// 03 02 03 02 block.lengths = [3, 2, 3, 2]
|
|
536
|
+
// 64 00 00 00 c8 00 00 00 2c 01 00 00 90 01 00 00 f4 01 00 00 58 02 00 00 bc 02 00 00 ... 12 more bytes> [100, 200, 300, ...]
|
|
537
|
+
// block 1
|
|
538
|
+
// ...
|
|
539
|
+
const type_ = type - 64;
|
|
525
540
|
const cols = dv.getUint32(4, le);
|
|
526
541
|
let blocks = [];
|
|
542
|
+
// decimal32/64 会在所有 blocks 之前多一个 scale
|
|
543
|
+
if (type_ === DdbType.decimal32 || type_ === DdbType.decimal64) {
|
|
544
|
+
blocks.scale = dv.getInt32(i_items_start, le);
|
|
545
|
+
i_items_start += 4;
|
|
546
|
+
}
|
|
527
547
|
let i_block_start = i_items_start;
|
|
528
548
|
// 解析一个 block
|
|
529
549
|
for (let i_row = 0; i_row < rows;) {
|
|
@@ -552,7 +572,20 @@ export class DdbObj {
|
|
|
552
572
|
let total_length = 0;
|
|
553
573
|
for (const x of lengths)
|
|
554
574
|
total_length += x;
|
|
555
|
-
|
|
575
|
+
let len_items;
|
|
576
|
+
let data;
|
|
577
|
+
switch (type_) {
|
|
578
|
+
case DdbType.decimal32:
|
|
579
|
+
len_items = total_length * 4;
|
|
580
|
+
data = new Int32Array(buf.buffer.slice(buf.byteOffset + i_data_start, buf.byteOffset + i_data_start + len_items));
|
|
581
|
+
break;
|
|
582
|
+
case DdbType.decimal64:
|
|
583
|
+
len_items = total_length * 8;
|
|
584
|
+
data = new BigInt64Array(buf.buffer.slice(buf.byteOffset + i_data_start, buf.byteOffset + i_data_start + len_items));
|
|
585
|
+
break;
|
|
586
|
+
default:
|
|
587
|
+
[len_items, data] = this.parse_vector_items(buf.subarray(i_data_start), le, type - 64, total_length);
|
|
588
|
+
}
|
|
556
589
|
blocks.push({
|
|
557
590
|
unit,
|
|
558
591
|
rows,
|
|
@@ -867,6 +900,10 @@ export class DdbObj {
|
|
|
867
900
|
if (form === DdbForm.vector && 64 <= type && type < 128)
|
|
868
901
|
return [
|
|
869
902
|
Uint32Array.of(this.rows, this.cols),
|
|
903
|
+
...(type - 64 === DdbType.decimal32 || type - 64 === DdbType.decimal64) ?
|
|
904
|
+
[Int32Array.of(this.value.scale)]
|
|
905
|
+
:
|
|
906
|
+
[],
|
|
870
907
|
...this.value.map(block => ([
|
|
871
908
|
Uint16Array.of(block.rows),
|
|
872
909
|
Uint8Array.of(block.unit, 0),
|
|
@@ -925,10 +962,7 @@ export class DdbObj {
|
|
|
925
962
|
})();
|
|
926
963
|
if (!body)
|
|
927
964
|
return new Uint8Array(0);
|
|
928
|
-
return concat([
|
|
929
|
-
header,
|
|
930
|
-
...body
|
|
931
|
-
]);
|
|
965
|
+
return concat([header, ...body]);
|
|
932
966
|
}
|
|
933
967
|
static pack_vector_body(value, type, length) {
|
|
934
968
|
switch (type) {
|
|
@@ -1054,7 +1088,18 @@ export class DdbObj {
|
|
|
1054
1088
|
for (const length of lengths) {
|
|
1055
1089
|
let _items = new Array(Math.min(limit, length));
|
|
1056
1090
|
for (let i = 0; i < _items.length; i++)
|
|
1057
|
-
|
|
1091
|
+
if (_type === DdbType.decimal32 || _type === DdbType.decimal64) {
|
|
1092
|
+
const x = data[acc_len + i];
|
|
1093
|
+
if (x === nulls.int64 && _type === DdbType.decimal64 ||
|
|
1094
|
+
x === nulls.int32 && _type === DdbType.decimal32)
|
|
1095
|
+
return '';
|
|
1096
|
+
const { scale } = this.value;
|
|
1097
|
+
const s = String(x < 0 ? -x : x).padStart(scale, '0');
|
|
1098
|
+
const str = (x < 0 ? '-' : '') + (scale ? `${s.slice(0, -scale) || '0'}.${s.slice(-scale)}` : s);
|
|
1099
|
+
_items[i] = options.colors ? green(str) : str;
|
|
1100
|
+
}
|
|
1101
|
+
else
|
|
1102
|
+
_items[i] = format(_type, data[acc_len + i], this.le, options);
|
|
1058
1103
|
items[i_items++] = format_array(_items, length > limit);
|
|
1059
1104
|
acc_len += length;
|
|
1060
1105
|
}
|
|
@@ -1436,6 +1481,7 @@ export function format(type, value, le, options = {}) {
|
|
|
1436
1481
|
}
|
|
1437
1482
|
/** formatted vector, the index-th item in the collection is a string */
|
|
1438
1483
|
export function formati(obj, index, options = {}) {
|
|
1484
|
+
assert(index < obj.rows, 'index < obj.rows');
|
|
1439
1485
|
if (64 <= obj.type && obj.type < 128) { // array vector
|
|
1440
1486
|
// 因为 array vector 目前只支持:Logical, Integral(不包括 INT128, COMPRESS 类型), Floating, Temporal
|
|
1441
1487
|
// 都对应 TypedArray 中的一格,所以 lengths.length 等于 block 中的 row 的个数
|
|
@@ -1463,7 +1509,18 @@ export function formati(obj, index, options = {}) {
|
|
|
1463
1509
|
const limit = 10;
|
|
1464
1510
|
let items = new Array(Math.min(limit, length));
|
|
1465
1511
|
for (let i = 0; i < items.length; i++)
|
|
1466
|
-
|
|
1512
|
+
if (_type === DdbType.decimal32 || _type === DdbType.decimal64) {
|
|
1513
|
+
const x = data[acc_len + i];
|
|
1514
|
+
if (x === nulls.int64 && _type === DdbType.decimal64 ||
|
|
1515
|
+
x === nulls.int32 && _type === DdbType.decimal32)
|
|
1516
|
+
return '';
|
|
1517
|
+
const { scale } = obj.value;
|
|
1518
|
+
const s = String(x < 0 ? -x : x).padStart(scale, '0');
|
|
1519
|
+
const str = (x < 0 ? '-' : '') + (scale ? `${s.slice(0, -scale) || '0'}.${s.slice(-scale)}` : s);
|
|
1520
|
+
items[i] = options.colors ? green(str) : str;
|
|
1521
|
+
}
|
|
1522
|
+
else
|
|
1523
|
+
items[i] = format(_type, data[acc_len + i], obj.le, options);
|
|
1467
1524
|
return (items.join(', ') + (length > limit ? ', ...' : '')).bracket('square');
|
|
1468
1525
|
}
|
|
1469
1526
|
}
|
|
@@ -1799,10 +1856,14 @@ export class DdbTable extends DdbObj {
|
|
|
1799
1856
|
}
|
|
1800
1857
|
}
|
|
1801
1858
|
export function date2ms(date) {
|
|
1859
|
+
// 将 server 的本地时间 (以 ms 为单位,1970.01.01 00:00:00 作为零点) 当成是客户端这里的本地的时间,然后根据本地的时区信息转换为 utc 时间
|
|
1860
|
+
// 本地的时区与实际的时间值相关,timezone offset 可能会受到夏令时 (DST) 的影响
|
|
1861
|
+
// 得到的 utc 毫秒数交给 js date 或者 dayjs 去格式化
|
|
1862
|
+
const ms = 1000 * 3600 * 24 * date;
|
|
1802
1863
|
return (date === null || date === nulls.int32) ?
|
|
1803
1864
|
null
|
|
1804
1865
|
:
|
|
1805
|
-
|
|
1866
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1806
1867
|
}
|
|
1807
1868
|
export function date2str(date, format = 'YYYY.MM.DD') {
|
|
1808
1869
|
return (date === null || date === nulls.int32) ?
|
|
@@ -1829,7 +1890,7 @@ export function time2ms(time) {
|
|
|
1829
1890
|
return (time === null || time === nulls.int32) ?
|
|
1830
1891
|
null
|
|
1831
1892
|
:
|
|
1832
|
-
|
|
1893
|
+
1000 * 60 * new Date(time).getTimezoneOffset() + time;
|
|
1833
1894
|
}
|
|
1834
1895
|
export function time2str(time, format = 'HH:mm:ss.SSS') {
|
|
1835
1896
|
return (time === null || time === nulls.int32) ?
|
|
@@ -1838,10 +1899,11 @@ export function time2str(time, format = 'HH:mm:ss.SSS') {
|
|
|
1838
1899
|
dayjs(time2ms(time)).format(format);
|
|
1839
1900
|
}
|
|
1840
1901
|
export function minute2ms(minute) {
|
|
1902
|
+
const ms = 60 * 1000 * minute;
|
|
1841
1903
|
return (minute === null || minute === nulls.int32) ?
|
|
1842
1904
|
null
|
|
1843
1905
|
:
|
|
1844
|
-
|
|
1906
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1845
1907
|
}
|
|
1846
1908
|
export function minute2str(minute, format = 'HH:mm[m]') {
|
|
1847
1909
|
return (minute === null || minute === nulls.int32) ?
|
|
@@ -1850,10 +1912,11 @@ export function minute2str(minute, format = 'HH:mm[m]') {
|
|
|
1850
1912
|
dayjs(minute2ms(minute)).format(format);
|
|
1851
1913
|
}
|
|
1852
1914
|
export function second2ms(second) {
|
|
1915
|
+
const ms = 1000 * second;
|
|
1853
1916
|
return (second === null || second === nulls.int32) ?
|
|
1854
1917
|
null
|
|
1855
1918
|
:
|
|
1856
|
-
|
|
1919
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1857
1920
|
}
|
|
1858
1921
|
export function second2str(second, format = 'HH:mm:ss') {
|
|
1859
1922
|
return (second === null || second === nulls.int32) ?
|
|
@@ -1862,10 +1925,11 @@ export function second2str(second, format = 'HH:mm:ss') {
|
|
|
1862
1925
|
dayjs(second2ms(second)).format(format);
|
|
1863
1926
|
}
|
|
1864
1927
|
export function datetime2ms(datetime) {
|
|
1928
|
+
const ms = 1000 * datetime;
|
|
1865
1929
|
return (datetime === null || datetime === nulls.int32) ?
|
|
1866
1930
|
null
|
|
1867
1931
|
:
|
|
1868
|
-
|
|
1932
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1869
1933
|
}
|
|
1870
1934
|
export function datetime2str(datetime, format = 'YYYY.MM.DD HH:mm:ss') {
|
|
1871
1935
|
return (datetime === null || datetime === nulls.int32) ?
|
|
@@ -1874,10 +1938,11 @@ export function datetime2str(datetime, format = 'YYYY.MM.DD HH:mm:ss') {
|
|
|
1874
1938
|
dayjs(datetime2ms(datetime)).format(format);
|
|
1875
1939
|
}
|
|
1876
1940
|
export function timestamp2ms(timestamp) {
|
|
1941
|
+
const ms = Number(timestamp);
|
|
1877
1942
|
return (timestamp === null || timestamp === nulls.int64) ?
|
|
1878
1943
|
null
|
|
1879
1944
|
:
|
|
1880
|
-
|
|
1945
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1881
1946
|
}
|
|
1882
1947
|
/** format timestamp (bigint) to string
|
|
1883
1948
|
- timestamp: bigint value
|
|
@@ -1892,16 +1957,18 @@ export function timestamp2str(timestamp, format = 'YYYY.MM.DD HH:mm:ss.SSS') {
|
|
|
1892
1957
|
dayjs(timestamp2ms(timestamp)).format(format);
|
|
1893
1958
|
}
|
|
1894
1959
|
export function datehour2ms(datehour) {
|
|
1960
|
+
const ms = 1000 * 3600 * datehour;
|
|
1895
1961
|
return (datehour === null || datehour === nulls.int32) ?
|
|
1896
1962
|
null
|
|
1897
1963
|
:
|
|
1898
|
-
|
|
1964
|
+
1000 * 60 * new Date(ms).getTimezoneOffset() + ms;
|
|
1899
1965
|
}
|
|
1900
1966
|
export function datehour2str(datehour, format = 'YYYY.MM.DDTHH') {
|
|
1967
|
+
const ms = 1000 * 3600 * datehour;
|
|
1901
1968
|
return (datehour === null || datehour === nulls.int32) ?
|
|
1902
1969
|
'null'
|
|
1903
1970
|
:
|
|
1904
|
-
dayjs(
|
|
1971
|
+
dayjs(1000 * 60 * new Date(ms).getTimezoneOffset() + ms).format(format);
|
|
1905
1972
|
}
|
|
1906
1973
|
/** parse timestamp string to bigint value
|
|
1907
1974
|
- str: timestamp string, If it is an empty string or 'null', it will return the corresponding empty value (nulls.int64)
|
|
@@ -1912,9 +1979,10 @@ export function datehour2str(datehour, format = 'YYYY.MM.DDTHH') {
|
|
|
1912
1979
|
export function str2timestamp(str, format = 'YYYY.MM.DD HH:mm:ss.SSS') {
|
|
1913
1980
|
if (!str || str === 'null')
|
|
1914
1981
|
return nulls.int64;
|
|
1915
|
-
assert('The length of the timestamp string must be equal to the length of the format string');
|
|
1916
|
-
|
|
1917
|
-
|
|
1982
|
+
assert(str.length === format.length, 'The length of the timestamp string must be equal to the length of the format string');
|
|
1983
|
+
const ms = dayjs(str, format).valueOf();
|
|
1984
|
+
return BigInt(-(1000 * 60 * new Date(ms).getTimezoneOffset()) +
|
|
1985
|
+
ms);
|
|
1918
1986
|
}
|
|
1919
1987
|
export function nanotime2ns(nanotime) {
|
|
1920
1988
|
return nanotimestamp2ns(nanotime);
|
|
@@ -1929,15 +1997,17 @@ export function nanotime2str(nanotime, format = 'HH:mm:ss.SSSSSSSSS') {
|
|
|
1929
1997
|
const i_second_end = i_second_start + 2;
|
|
1930
1998
|
const i_nanosecond_start = format.indexOf('SSSSSSSSS', i_second_end);
|
|
1931
1999
|
assert(i_nanosecond_start !== -1, 'Format string must contain nanosecond format (SSSSSSSSS)');
|
|
1932
|
-
|
|
2000
|
+
const ms = Number(nanotime) / 1000000;
|
|
2001
|
+
return (dayjs(1000 * 60 * new Date(ms).getTimezoneOffset() + ms).format(format.slice(0, i_second_end)) +
|
|
1933
2002
|
format.slice(i_second_end, i_nanosecond_start) +
|
|
1934
2003
|
String(nanotime % 1000000000n).padStart(9, '0'));
|
|
1935
2004
|
}
|
|
1936
2005
|
export function nanotimestamp2ns(nanotimestamp) {
|
|
2006
|
+
const ms = Number(nanotimestamp / 1000000n);
|
|
1937
2007
|
return (nanotimestamp === null || nanotimestamp === nulls.int64) ?
|
|
1938
2008
|
null
|
|
1939
2009
|
:
|
|
1940
|
-
BigInt(
|
|
2010
|
+
BigInt(1000 * 60 * new Date(ms).getTimezoneOffset()) * 1000000n + nanotimestamp;
|
|
1941
2011
|
}
|
|
1942
2012
|
/** format nanotimestamp value (bigint) to string
|
|
1943
2013
|
- nanotimestamp: bigint value
|
|
@@ -1962,7 +2032,8 @@ export function nanotimestamp2str(nanotimestamp, format = 'YYYY.MM.DD HH:mm:ss.S
|
|
|
1962
2032
|
assert(i_nanosecond_start !== -1, 'Format string must contain nanosecond format (SSSSSSSSS)');
|
|
1963
2033
|
const remainder = nanotimestamp % 1000000000n;
|
|
1964
2034
|
const borrow = remainder < 0n;
|
|
1965
|
-
|
|
2035
|
+
const ms = Number(nanotimestamp / 1000000n);
|
|
2036
|
+
return (dayjs(1000 * 60 * new Date(ms).getTimezoneOffset() +
|
|
1966
2037
|
// 去掉 9 位的纳秒部分,转化为毫秒
|
|
1967
2038
|
Number((nanotimestamp - remainder + (borrow ? -1000000000n : 0n)) / 1000000n)).format(format.slice(0, i_second_end)) +
|
|
1968
2039
|
format.slice(i_second_end, i_nanosecond_start) +
|
|
@@ -1987,8 +2058,9 @@ export function str2nanotimestamp(str, format = 'YYYY.MM.DD HH:mm:ss.SSSSSSSSS')
|
|
|
1987
2058
|
const i_second_end = i_second_start + 2;
|
|
1988
2059
|
const i_nanosecond_start = format.indexOf('SSSSSSSSS', i_second_end);
|
|
1989
2060
|
assert(i_nanosecond_start !== -1, 'Format string must contain nanosecond format (SSSSSSSSS)');
|
|
1990
|
-
|
|
1991
|
-
|
|
2061
|
+
const ms = dayjs(str.slice(0, i_second_end), format.slice(0, i_second_end)).valueOf();
|
|
2062
|
+
return (BigInt(-(1000 * 60 * new Date(ms).getTimezoneOffset()) +
|
|
2063
|
+
ms) * 1000000n
|
|
1992
2064
|
+
|
|
1993
2065
|
BigInt(str.slice(i_nanosecond_start, i_nanosecond_start + 9)));
|
|
1994
2066
|
}
|
|
@@ -2014,7 +2086,7 @@ export function int1282str(buffer, le = true) {
|
|
|
2014
2086
|
return [...buf].map(x => x.toString(16)
|
|
2015
2087
|
.padStart(2, '0')).join('');
|
|
2016
2088
|
}
|
|
2017
|
-
export const winsize =
|
|
2089
|
+
export const winsize = 10_0000;
|
|
2018
2090
|
export class ConnectionError extends Error {
|
|
2019
2091
|
ddb;
|
|
2020
2092
|
constructor(ddb) {
|
|
@@ -2086,9 +2158,10 @@ export class DDB {
|
|
|
2086
2158
|
constructor(url, options = {}) {
|
|
2087
2159
|
if (!url) {
|
|
2088
2160
|
const _url = new URL(location.href);
|
|
2089
|
-
const
|
|
2090
|
-
const
|
|
2091
|
-
|
|
2161
|
+
const dev = _url.pathname.endsWith('/console/');
|
|
2162
|
+
const hostname = _url.searchParams.get('hostname') || (dev ? '127.0.0.1' : location.hostname);
|
|
2163
|
+
const port = _url.searchParams.get('port') || (dev ? '8848' : location.port);
|
|
2164
|
+
url = `${dev ? (_url.searchParams.get('tls') === '1' ? 'wss' : 'ws') : (location.protocol === 'https:' ? 'wss' : 'ws')}://${hostname}${port ? `:${port}` : ''}/`;
|
|
2092
2165
|
}
|
|
2093
2166
|
this.url = url;
|
|
2094
2167
|
if (options.autologin !== undefined)
|
|
@@ -2393,8 +2466,9 @@ export class DDB {
|
|
|
2393
2466
|
async cancel() {
|
|
2394
2467
|
let ddb = new DDB(this.url, this);
|
|
2395
2468
|
try {
|
|
2469
|
+
// 因为是新建的连接,而且执行完脚本之后马上就关闭了,所以不用考虑变量泄漏的问题
|
|
2396
2470
|
await ddb.eval(`jobs = exec rootJobId from getConsoleJobs() where sessionId = ${this.sid}\n` +
|
|
2397
|
-
'if (size(jobs))\n' +
|
|
2471
|
+
(this.python ? 'if size(jobs):\n' : 'if (size(jobs))\n') +
|
|
2398
2472
|
' cancelConsoleJob(jobs)\n', { urgent: true });
|
|
2399
2473
|
}
|
|
2400
2474
|
finally {
|
|
@@ -2455,110 +2529,58 @@ export class DDB {
|
|
|
2455
2529
|
}
|
|
2456
2530
|
/** Internal stream subscription method */
|
|
2457
2531
|
async subscribe() {
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
// todo: 还有用吗?需要获取客户端 IP 吗
|
|
2532
|
+
await this.rpc('connect', {});
|
|
2533
|
+
if (this.autologin)
|
|
2534
|
+
await this.call('login', [this.username, this.password]);
|
|
2535
|
+
console.log('Subscribed to streaming table, colnames:',
|
|
2536
|
+
// string[3](['time', 'stock', 'price'])
|
|
2537
|
+
this.streaming.colnames = (await this.call('publishTable', [
|
|
2465
2538
|
'localhost',
|
|
2466
|
-
// todo: 端口还有用吗?
|
|
2467
2539
|
new DdbInt(0),
|
|
2468
2540
|
this.streaming.table,
|
|
2469
2541
|
(this.streaming.action ||= `api_js_${new Date().getTime()}`),
|
|
2470
2542
|
// new DdbInt(-1), // offset
|
|
2471
2543
|
// filter
|
|
2472
2544
|
// allow exists
|
|
2473
|
-
]);
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
reject(error);
|
|
2504
|
-
}
|
|
2505
|
-
}
|
|
2506
|
-
else {
|
|
2507
|
-
try {
|
|
2508
|
-
const dv = new DataView(buffer);
|
|
2509
|
-
const buf = new Uint8Array(buffer);
|
|
2510
|
-
let { streaming } = this;
|
|
2511
|
-
streaming.time = dv.getBigInt64(1, this.le);
|
|
2512
|
-
streaming.id = dv.getBigInt64(9, this.le);
|
|
2513
|
-
const i_topic_end = buf.indexOf(0, 17);
|
|
2514
|
-
streaming.topic = this.dec.decode(buf.subarray(17, i_topic_end));
|
|
2515
|
-
if (second) {
|
|
2516
|
-
second = false;
|
|
2517
|
-
// 是 table
|
|
2518
|
-
streaming.schema = DdbObj.parse(buf.subarray(i_topic_end + 1), this.le);
|
|
2519
|
-
console.log('Received streaming table schema:', streaming.schema);
|
|
2520
|
-
streaming.window = {
|
|
2521
|
-
offset: 0,
|
|
2522
|
-
rows: 0,
|
|
2523
|
-
segments: [],
|
|
2524
|
-
};
|
|
2525
|
-
assert(streaming.schema.rows === 0, 'schema.rows === 0');
|
|
2526
|
-
resolve(streaming.schema);
|
|
2527
|
-
}
|
|
2528
|
-
else {
|
|
2529
|
-
// 是 column 片段组成的 any vector
|
|
2530
|
-
const data = streaming.data = DdbObj.parse(buf.subarray(i_topic_end + 1), this.le);
|
|
2531
|
-
let { window: win } = streaming;
|
|
2532
|
-
win.rows += data.value[0].rows;
|
|
2533
|
-
win.segments.push(data);
|
|
2534
|
-
if (win.rows >= winsize * 2 && win.segments.length >= 2) {
|
|
2535
|
-
let winsize_ = 0;
|
|
2536
|
-
let i = win.segments.length - 1;
|
|
2537
|
-
// 往前移动至首个累计 winsize_ 超过 winsize 的位置
|
|
2538
|
-
for (; winsize_ < winsize; i--)
|
|
2539
|
-
winsize_ += win.segments[i].rows;
|
|
2540
|
-
win.segments = win.segments.slice(i);
|
|
2541
|
-
win.offset += win.rows - winsize_;
|
|
2542
|
-
win.rows = winsize_;
|
|
2543
|
-
console.log('exceeds winsize, shrink window.segments', win);
|
|
2544
|
-
}
|
|
2545
|
-
streaming.handler(streaming);
|
|
2546
|
-
}
|
|
2547
|
-
}
|
|
2548
|
-
catch (error) {
|
|
2549
|
-
reject(error);
|
|
2550
|
-
}
|
|
2545
|
+
])).value);
|
|
2546
|
+
this.streaming.window = {
|
|
2547
|
+
offset: 0,
|
|
2548
|
+
rows: 0,
|
|
2549
|
+
segments: [],
|
|
2550
|
+
};
|
|
2551
|
+
// 先准备好收到 websocket message 的 callback
|
|
2552
|
+
this.on_message = ({ data: buffer }) => {
|
|
2553
|
+
let { streaming } = this;
|
|
2554
|
+
try {
|
|
2555
|
+
const dv = new DataView(buffer);
|
|
2556
|
+
const buf = new Uint8Array(buffer);
|
|
2557
|
+
streaming.time = dv.getBigInt64(1, this.le);
|
|
2558
|
+
streaming.id = dv.getBigInt64(9, this.le);
|
|
2559
|
+
const i_topic_end = buf.indexOf(0, 17);
|
|
2560
|
+
streaming.topic = this.dec.decode(buf.subarray(17, i_topic_end));
|
|
2561
|
+
// 是 column 片段组成的 any vector
|
|
2562
|
+
const data = streaming.data = DdbObj.parse(buf.subarray(i_topic_end + 1), this.le);
|
|
2563
|
+
let { window: win } = streaming;
|
|
2564
|
+
win.rows += streaming.rows = data.value[0].rows;
|
|
2565
|
+
win.segments.push(data);
|
|
2566
|
+
if (win.rows >= winsize * 2 && win.segments.length >= 2) {
|
|
2567
|
+
let winsize_ = 0;
|
|
2568
|
+
let i = win.segments.length - 1;
|
|
2569
|
+
// 往前移动至首个累计 winsize_ 超过 winsize 的位置
|
|
2570
|
+
for (; winsize_ < winsize; i--)
|
|
2571
|
+
winsize_ += win.segments[i].value[0].rows;
|
|
2572
|
+
win.segments = win.segments.slice(i);
|
|
2573
|
+
win.offset += win.rows - winsize_;
|
|
2574
|
+
win.rows = winsize_;
|
|
2551
2575
|
}
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
]));
|
|
2561
|
-
});
|
|
2576
|
+
}
|
|
2577
|
+
catch (error) {
|
|
2578
|
+
// 将 error 交给 handler 处理
|
|
2579
|
+
streaming.error = error;
|
|
2580
|
+
}
|
|
2581
|
+
this.streaming.handler(streaming);
|
|
2582
|
+
};
|
|
2583
|
+
return this.streaming;
|
|
2562
2584
|
}
|
|
2563
2585
|
}
|
|
2564
2586
|
export let ddb = window.ddb = new DDB();
|