dolphindb 2.0.947 → 2.0.949
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 +5 -0
- package/README.zh.md +4 -0
- package/browser.d.ts +18 -9
- package/browser.js +181 -216
- package/browser.js.map +1 -1
- package/docs.en.json +89 -170
- package/docs.zh.json +61 -51
- package/index.d.ts +18 -10
- package/index.js +181 -216
- package/index.js.map +1 -1
- package/package.json +5 -5
- package/test.d.ts +1 -1
- package/test.js +1 -1
- package/test.js.map +1 -1
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import DayjsCustomParseFormat from 'dayjs/plugin/customParseFormat.js';
|
|
|
4
4
|
dayjs.extend(DayjsCustomParseFormat);
|
|
5
5
|
import ipaddrjs from 'ipaddr.js';
|
|
6
6
|
const { fromByteArray: buf2ipaddr } = ipaddrjs;
|
|
7
|
-
import { concat, assert, inspect, typed_array_to_buffer, connect_websocket, WebSocket,
|
|
7
|
+
import { concat, assert, inspect, typed_array_to_buffer, connect_websocket, WebSocket, Lock } from 'xshell';
|
|
8
8
|
import { t } from './i18n/index.js';
|
|
9
9
|
export var DdbForm;
|
|
10
10
|
(function (DdbForm) {
|
|
@@ -119,7 +119,7 @@ export const nulls = {
|
|
|
119
119
|
bytes16: Uint8Array.from(new Array(16).fill(0))
|
|
120
120
|
};
|
|
121
121
|
/** 可以表示所有 DolphinDB 数据库中的数据类型 Can represent data types in all DolphinDB databases */
|
|
122
|
-
|
|
122
|
+
class DdbObj {
|
|
123
123
|
static dec = new TextDecoder('utf-8');
|
|
124
124
|
static enc = new TextEncoder();
|
|
125
125
|
/** 维护已解析的 symbol base,比如流数据中后续的 symbol 向量可能只发送一个 base.id, base.size == 0, 依赖之前发送的 symbol base ?
|
|
@@ -1275,6 +1275,7 @@ export class DdbObj {
|
|
|
1275
1275
|
return obj;
|
|
1276
1276
|
}
|
|
1277
1277
|
}
|
|
1278
|
+
export { DdbObj };
|
|
1278
1279
|
/** 整数一定用这个 number formatter, InspectOptions.decimals 不传也用这个 */
|
|
1279
1280
|
let default_formatter = Intl.NumberFormat('en-US', { maximumFractionDigits: 20 });
|
|
1280
1281
|
let _decimals = 20;
|
|
@@ -2158,7 +2159,7 @@ export class DdbDatabaseError extends Error {
|
|
|
2158
2159
|
this.options = options;
|
|
2159
2160
|
}
|
|
2160
2161
|
}
|
|
2161
|
-
|
|
2162
|
+
class DDB {
|
|
2162
2163
|
/** 当前的 session id (http 或 tcp) */
|
|
2163
2164
|
sid = '0';
|
|
2164
2165
|
/** utf-8 text decoder */
|
|
@@ -2173,7 +2174,8 @@ export class DDB {
|
|
|
2173
2174
|
e.g. `ws://127.0.0.1:8848/`, `wss://dolphindb.com`
|
|
2174
2175
|
*/
|
|
2175
2176
|
url;
|
|
2176
|
-
websocket
|
|
2177
|
+
/** 为所有 websocket 操作加锁,包括设置 this.on_message, this.on_error, websocket.send */
|
|
2178
|
+
lwebsocket = new Lock();
|
|
2177
2179
|
/** little endian (server) */
|
|
2178
2180
|
le = true;
|
|
2179
2181
|
/** little endian (client) */
|
|
@@ -2203,15 +2205,15 @@ export class DDB {
|
|
|
2203
2205
|
error;
|
|
2204
2206
|
/** DdbMessage listeners */
|
|
2205
2207
|
listeners = [];
|
|
2206
|
-
/**
|
|
2207
|
-
|
|
2208
|
-
/**
|
|
2209
|
-
ppnode_run
|
|
2208
|
+
/** 首次 connect 连接的 promise, 后面的 connect 调用都返回这个 */
|
|
2209
|
+
pconnect;
|
|
2210
|
+
/** 首次定义 pnode_run 的 promise,保证并发调用 rpc 时只定义一次 pnode_run */
|
|
2211
|
+
ppnode_run;
|
|
2210
2212
|
get connected() {
|
|
2211
|
-
return !this.error && this.
|
|
2213
|
+
return !this.error && this.lwebsocket.resource?.readyState === WebSocket.OPEN;
|
|
2212
2214
|
}
|
|
2213
2215
|
get errored() {
|
|
2214
|
-
return this.error || (this.
|
|
2216
|
+
return Boolean(this.error || (this.lwebsocket.resource && this.lwebsocket.resource.readyState !== WebSocket.OPEN));
|
|
2215
2217
|
}
|
|
2216
2218
|
/**
|
|
2217
2219
|
使用 WebSocket URL 初始化连接到 DolphinDB 的实例(不建立实际的网络连接)
|
|
@@ -2277,62 +2279,46 @@ export class DDB {
|
|
|
2277
2279
|
throw this.error || new DdbConnectionError(this);
|
|
2278
2280
|
if (this.connected)
|
|
2279
2281
|
return;
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
}
|
|
2321
|
-
});
|
|
2322
|
-
}
|
|
2323
|
-
catch (error) {
|
|
2324
|
-
this.error ??= new DdbConnectionError(this, error);
|
|
2325
|
-
pwebsocket.reject(error);
|
|
2326
|
-
throw this.error;
|
|
2327
|
-
}
|
|
2328
|
-
assert(this.connected);
|
|
2329
|
-
pwebsocket.resolve();
|
|
2330
|
-
// websocket 临界区结束
|
|
2331
|
-
await this.rpc('connect', {});
|
|
2332
|
-
if (this.autologin)
|
|
2333
|
-
await this.call('login', [this.username, this.password], { urgent: true });
|
|
2334
|
-
if (this.streaming)
|
|
2335
|
-
await this.subscribe();
|
|
2282
|
+
return this.pconnect ??= new Promise(async (resolve, reject) => {
|
|
2283
|
+
this.on_error = () => {
|
|
2284
|
+
reject(this.error /* 一定有,不需要再 || new DdbConnectionError(this) */);
|
|
2285
|
+
};
|
|
2286
|
+
try {
|
|
2287
|
+
// 连接建立之前应该不会有别的调用占用 this.lwebsocket
|
|
2288
|
+
this.lwebsocket.resource = await connect_websocket(this.url, {
|
|
2289
|
+
protocols: (() => {
|
|
2290
|
+
if (this.streaming)
|
|
2291
|
+
return 'streaming';
|
|
2292
|
+
if (this.python)
|
|
2293
|
+
return 'python';
|
|
2294
|
+
})(),
|
|
2295
|
+
on_message: (buffer, websocket) => {
|
|
2296
|
+
this.on_message(buffer, websocket);
|
|
2297
|
+
},
|
|
2298
|
+
on_error: error => {
|
|
2299
|
+
this.error ??= new DdbConnectionError(this, error);
|
|
2300
|
+
this.on_error();
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
catch (error) {
|
|
2305
|
+
this.error ??= new DdbConnectionError(this, error);
|
|
2306
|
+
reject(this.error);
|
|
2307
|
+
return;
|
|
2308
|
+
}
|
|
2309
|
+
try {
|
|
2310
|
+
assert(this.connected);
|
|
2311
|
+
await this.rpc('connect', { skip_connection_check: true });
|
|
2312
|
+
if (this.autologin)
|
|
2313
|
+
await this.call('login', [this.username, this.password], { urgent: true, skip_connection_check: true });
|
|
2314
|
+
if (this.streaming)
|
|
2315
|
+
await this.subscribe();
|
|
2316
|
+
resolve();
|
|
2317
|
+
}
|
|
2318
|
+
catch (error) {
|
|
2319
|
+
reject(error);
|
|
2320
|
+
}
|
|
2321
|
+
});
|
|
2336
2322
|
}
|
|
2337
2323
|
get_rpc_options({ urgent = false, secondary = false, async: _async = false, pickle = false, clear = false, api = false, compress = false, cancellable = true, priority = urgent ? 8 : 4, parallelism = 8, root_id = '', limit, } = {}) {
|
|
2338
2324
|
let flag = 0;
|
|
@@ -2367,7 +2353,8 @@ export class DDB {
|
|
|
2367
2353
|
}
|
|
2368
2354
|
disconnect() {
|
|
2369
2355
|
if (this.connected)
|
|
2370
|
-
|
|
2356
|
+
// 这里不获取 lock,直接关闭连接
|
|
2357
|
+
this.lwebsocket.resource.close(1000);
|
|
2371
2358
|
}
|
|
2372
2359
|
/** (内部使用的方法) rpc through websocket (function/script/variable command)
|
|
2373
2360
|
未连接到 DDB 时调用会自动连接,连接断开时调用会抛出 DdbConnectionError
|
|
@@ -2378,165 +2365,138 @@ export class DDB {
|
|
|
2378
2365
|
- vars?: type === 'variable' 时必传,variable 指令中待上传的变量名
|
|
2379
2366
|
- listener?: 处理本次 rpc 期间的消息 (DdbMessage)
|
|
2380
2367
|
- parse_object?: 在本次 rpc 期间设置 parse_object, 结束后恢复原有
|
|
2381
|
-
为 false 时返回的 DdbObj 仅含有 buffer 和 le,不做解析,以便后续转发、序列化
|
|
2368
|
+
为 false 时返回的 DdbObj 仅含有 buffer 和 le,不做解析,以便后续转发、序列化
|
|
2369
|
+
- skip_connection_check?: 在首次 await ddb.connect() 建立连接时不能再次调用 await this.connect() 确保连接状态,会导致循环依赖,
|
|
2370
|
+
将这个 flag 设为 true 跳过连接状态检查 */
|
|
2382
2371
|
async rpc(type, options) {
|
|
2383
2372
|
// 保留调用栈信息
|
|
2384
2373
|
let error = new DdbDatabaseError('', this, type, options);
|
|
2385
|
-
|
|
2374
|
+
if (!options.skip_connection_check)
|
|
2375
|
+
await this.connect();
|
|
2386
2376
|
const { script, func, args: _args = [], vars = [], urgent, listener, } = options;
|
|
2387
|
-
if (func === 'pnode_run'
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
' return pnodeRun(func, nodes, add_node_alias)\n' +
|
|
2429
|
-
' \n' +
|
|
2430
|
-
' args_partial = array(any, 1 + nargs, 1 + nargs)\n' +
|
|
2431
|
-
' args_partial[0] = func\n' +
|
|
2432
|
-
' args_partial[1:] = args\n' +
|
|
2433
|
-
' return pnodeRun(\n' +
|
|
2434
|
-
' unifiedCall(partial, args_partial),\n' +
|
|
2435
|
-
' nodes,\n' +
|
|
2436
|
-
' add_node_alias\n' +
|
|
2437
|
-
' )\n' +
|
|
2438
|
-
'}\n', { urgent: true });
|
|
2439
|
-
this.pnode_run_defined = true;
|
|
2440
|
-
ppnode_run.resolve();
|
|
2441
|
-
}
|
|
2442
|
-
catch (error) {
|
|
2443
|
-
// 这次失败了,之后的执行肯定也会失败
|
|
2444
|
-
ppnode_run.reject(error);
|
|
2445
|
-
throw error;
|
|
2446
|
-
}
|
|
2447
|
-
}
|
|
2377
|
+
if (func === 'pnode_run')
|
|
2378
|
+
await (this.ppnode_run ??= this.eval(this.python ?
|
|
2379
|
+
'\n' +
|
|
2380
|
+
'def pnode_run (nodes, func_name, args, add_node_alias):\n' +
|
|
2381
|
+
' nargs = size(args)\n' +
|
|
2382
|
+
' func = funcByName(func_name)\n' +
|
|
2383
|
+
' \n' +
|
|
2384
|
+
' if not nargs:\n' +
|
|
2385
|
+
' return pnodeRun(func, nodes, add_node_alias)\n' +
|
|
2386
|
+
' \n' +
|
|
2387
|
+
' args_partial = [ ]\n' +
|
|
2388
|
+
' args_partial.append(func)\n' +
|
|
2389
|
+
' for a in args:\n' +
|
|
2390
|
+
' args_partial.append(a)\n' +
|
|
2391
|
+
' \n' +
|
|
2392
|
+
' return pnodeRun(\n' +
|
|
2393
|
+
' unifiedCall(partial, args_partial),\n' +
|
|
2394
|
+
' nodes,\n' +
|
|
2395
|
+
' add_node_alias\n' +
|
|
2396
|
+
' )\n'
|
|
2397
|
+
:
|
|
2398
|
+
// 这个开头的空行很重要,应该可以绕过 webLoginRequired = true 时禁止执行代码
|
|
2399
|
+
// 搜一下 APISocketConsole::execute
|
|
2400
|
+
// https://dolphindb1.atlassian.net/browse/D20-4991
|
|
2401
|
+
'\n' +
|
|
2402
|
+
'def pnode_run (nodes, func_name, args, add_node_alias = true) {\n' +
|
|
2403
|
+
' nargs = size(args)\n' +
|
|
2404
|
+
' func = funcByName(func_name)\n' +
|
|
2405
|
+
' \n' +
|
|
2406
|
+
' if (!nargs)\n' +
|
|
2407
|
+
' return pnodeRun(func, nodes, add_node_alias)\n' +
|
|
2408
|
+
' \n' +
|
|
2409
|
+
' args_partial = array(any, 1 + nargs, 1 + nargs)\n' +
|
|
2410
|
+
' args_partial[0] = func\n' +
|
|
2411
|
+
' args_partial[1:] = args\n' +
|
|
2412
|
+
' return pnodeRun(\n' +
|
|
2413
|
+
' unifiedCall(partial, args_partial),\n' +
|
|
2414
|
+
' nodes,\n' +
|
|
2415
|
+
' add_node_alias\n' +
|
|
2416
|
+
' )\n' +
|
|
2417
|
+
'}\n', { urgent: true }));
|
|
2448
2418
|
// this 上的当前配置需要在 message 到达后使用,先保存起来
|
|
2449
2419
|
const _listeners = [...this.listeners].reverse();
|
|
2450
|
-
//
|
|
2420
|
+
// rpc 请求期间需要独占 websocket,所以设计了一个锁,申请之后才能使用
|
|
2451
2421
|
// ddb 世界观:需要等待上一个 rpc 结果从 server 返回之后才能发起下一个调用
|
|
2452
2422
|
// 违反世界观可能造成:
|
|
2453
2423
|
// 1. 并发多个请求只返回第一个结果(阻塞,需后续请求疏通)
|
|
2454
2424
|
// 2. windows 下 ddb server 返回多个相同的结果
|
|
2455
|
-
const ptail = this.pwebsocket;
|
|
2456
|
-
let pwebsocket = this.pwebsocket = defer();
|
|
2457
|
-
// 避免 pwebsocket.reject 后出现 triggerUncaughtException
|
|
2458
|
-
pwebsocket.catch(() => { });
|
|
2459
|
-
// 上一个请求出现了 websocket 错误,那么直接抛出异常,且通过 reject 当前锁 (pwebsocket),安全退出临界区
|
|
2460
|
-
try {
|
|
2461
|
-
await ptail;
|
|
2462
|
-
// 已进入临界区,只有一个 rpc 函数调用运行到这里,可以独占 this.on_message 然后写 WebSocket
|
|
2463
|
-
}
|
|
2464
|
-
catch (error) {
|
|
2465
|
-
pwebsocket.reject(error);
|
|
2466
|
-
throw error;
|
|
2467
|
-
}
|
|
2468
2425
|
// 既然上一个请求没有出现 websocket error,且函数开头已经调用了 await this.connect() 检查过,
|
|
2469
2426
|
// 这里也乐观的认为 this.connected && !this.errored 为 true
|
|
2470
|
-
return
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2427
|
+
return this.lwebsocket.request(async (websocket) => {
|
|
2428
|
+
// 独占资源后先检查状态
|
|
2429
|
+
if (this.errored || !this.connected)
|
|
2430
|
+
throw this.error || new DdbConnectionError(this);
|
|
2431
|
+
// 使用资源发送请求并等待请求完成
|
|
2432
|
+
return new Promise((resolve, reject) => {
|
|
2433
|
+
this.on_error = () => {
|
|
2434
|
+
// 这里一定有了 this.error, 不需要再 || new DdbConnectionError(this)
|
|
2435
|
+
reject(this.error);
|
|
2436
|
+
};
|
|
2437
|
+
this.on_message = buffer => {
|
|
2438
|
+
try {
|
|
2439
|
+
const buf = new Uint8Array(buffer);
|
|
2440
|
+
if (this.print_message_buffer)
|
|
2441
|
+
console.log(typed_array_to_buffer(buf));
|
|
2442
|
+
const message = this.parse_message(buf, error);
|
|
2443
|
+
listener?.(message, this);
|
|
2444
|
+
for (const listener of _listeners)
|
|
2445
|
+
listener(message, this);
|
|
2446
|
+
const { type, data } = message;
|
|
2447
|
+
switch (type) {
|
|
2448
|
+
case 'print':
|
|
2449
|
+
if (this.print_message)
|
|
2450
|
+
console.log(data);
|
|
2451
|
+
break;
|
|
2452
|
+
case 'object':
|
|
2453
|
+
resolve(data);
|
|
2454
|
+
break;
|
|
2455
|
+
case 'error':
|
|
2456
|
+
reject(data);
|
|
2457
|
+
break;
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
catch (error) {
|
|
2461
|
+
// 这里的错误并非 websocket 错误,而是 rpc 错误
|
|
2462
|
+
reject(error);
|
|
2463
|
+
}
|
|
2464
|
+
};
|
|
2465
|
+
const args = DdbObj.to_ddbobjs(_args);
|
|
2466
|
+
const command = this.enc.encode((() => {
|
|
2485
2467
|
switch (type) {
|
|
2486
|
-
case '
|
|
2487
|
-
if (this.
|
|
2488
|
-
console.log(
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2468
|
+
case 'function':
|
|
2469
|
+
if (this.verbose)
|
|
2470
|
+
console.log(func + inspect(args, { colors: false }));
|
|
2471
|
+
return 'function\n' +
|
|
2472
|
+
`${func}\n` +
|
|
2473
|
+
`${args.length}\n` +
|
|
2474
|
+
`${Number(DDB.le_client)}\n`;
|
|
2475
|
+
case 'script':
|
|
2476
|
+
if (this.verbose)
|
|
2477
|
+
console.log(script);
|
|
2478
|
+
return 'script\n' +
|
|
2479
|
+
script;
|
|
2480
|
+
case 'variable':
|
|
2481
|
+
if (this.verbose)
|
|
2482
|
+
for (let i = 0; i < vars.length; i++)
|
|
2483
|
+
console.log(`${vars[i]} = ${inspect(args[i], { colors: false })}`);
|
|
2484
|
+
return 'variable\n' +
|
|
2485
|
+
`${vars.join(',')}\n` +
|
|
2486
|
+
`${vars.length}\n` +
|
|
2487
|
+
`${Number(DDB.le_client)}\n`;
|
|
2488
|
+
case 'connect':
|
|
2489
|
+
if (this.verbose)
|
|
2490
|
+
console.log('connect()');
|
|
2491
|
+
return 'connect\n';
|
|
2498
2492
|
}
|
|
2499
|
-
}
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
};
|
|
2506
|
-
const args = DdbObj.to_ddbobjs(_args);
|
|
2507
|
-
const command = this.enc.encode((() => {
|
|
2508
|
-
switch (type) {
|
|
2509
|
-
case 'function':
|
|
2510
|
-
if (this.verbose)
|
|
2511
|
-
console.log(func + inspect(args, { colors: false }));
|
|
2512
|
-
return 'function\n' +
|
|
2513
|
-
`${func}\n` +
|
|
2514
|
-
`${args.length}\n` +
|
|
2515
|
-
`${Number(DDB.le_client)}\n`;
|
|
2516
|
-
case 'script':
|
|
2517
|
-
if (this.verbose)
|
|
2518
|
-
console.log(script);
|
|
2519
|
-
return 'script\n' +
|
|
2520
|
-
script;
|
|
2521
|
-
case 'variable':
|
|
2522
|
-
if (this.verbose)
|
|
2523
|
-
for (let i = 0; i < vars.length; i++)
|
|
2524
|
-
console.log(`${vars[i]} = ${inspect(args[i], { colors: false })}`);
|
|
2525
|
-
return 'variable\n' +
|
|
2526
|
-
`${vars.join(',')}\n` +
|
|
2527
|
-
`${vars.length}\n` +
|
|
2528
|
-
`${Number(DDB.le_client)}\n`;
|
|
2529
|
-
case 'connect':
|
|
2530
|
-
if (this.verbose)
|
|
2531
|
-
console.log('connect()');
|
|
2532
|
-
return 'connect\n';
|
|
2533
|
-
}
|
|
2534
|
-
})());
|
|
2535
|
-
this.websocket.send(concat([
|
|
2536
|
-
this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
|
|
2537
|
-
command,
|
|
2538
|
-
...args.map(arg => arg.pack())
|
|
2539
|
-
]));
|
|
2493
|
+
})());
|
|
2494
|
+
websocket.send(concat([
|
|
2495
|
+
this.enc.encode(`API2 ${this.sid} ${command.length} / ${this.get_rpc_options({ urgent })}\n`),
|
|
2496
|
+
command,
|
|
2497
|
+
...args.map(arg => arg.pack())
|
|
2498
|
+
]));
|
|
2499
|
+
});
|
|
2540
2500
|
});
|
|
2541
2501
|
}
|
|
2542
2502
|
/** eval script through websocket (script command)
|
|
@@ -2576,8 +2536,11 @@ export class DDB {
|
|
|
2576
2536
|
Set parse_object during this rpc, and restore the original after the end.
|
|
2577
2537
|
When it is false, the returned DdbObj only contains buffer and le without parsing,
|
|
2578
2538
|
so as to facilitate subsequent forwarding and serialization
|
|
2579
|
-
|
|
2580
|
-
|
|
2539
|
+
- skip_connection_check?: (内部使用) 在首次 await ddb.connect() 建立连接时不能再次调用 await this.connect() 确保连接状态,会导致循环依赖,
|
|
2540
|
+
将这个 flag 设为 true 跳过连接状态检查
|
|
2541
|
+
(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.
|
|
2542
|
+
Set this flag to true to skip connection status checks */
|
|
2543
|
+
async call(func, args = [], { urgent, node, nodes, func_type, add_node_alias, listener, parse_object, skip_connection_check } = {}) {
|
|
2581
2544
|
if (node) {
|
|
2582
2545
|
assert(func_type in DdbFunctionType, t('指定 node 时必须设置 func_type'));
|
|
2583
2546
|
args = [
|
|
@@ -2607,7 +2570,8 @@ export class DDB {
|
|
|
2607
2570
|
args,
|
|
2608
2571
|
urgent,
|
|
2609
2572
|
listener,
|
|
2610
|
-
parse_object
|
|
2573
|
+
parse_object,
|
|
2574
|
+
skip_connection_check
|
|
2611
2575
|
});
|
|
2612
2576
|
}
|
|
2613
2577
|
/** upload variable through websocket (variable command) */
|
|
@@ -2699,7 +2663,7 @@ export class DDB {
|
|
|
2699
2663
|
// new DdbInt(-1), // offset
|
|
2700
2664
|
// filter
|
|
2701
2665
|
// allow exists
|
|
2702
|
-
])).value);
|
|
2666
|
+
], { skip_connection_check: true })).value);
|
|
2703
2667
|
this.streaming.window = {
|
|
2704
2668
|
offset: 0,
|
|
2705
2669
|
rows: 0,
|
|
@@ -2741,6 +2705,7 @@ export class DDB {
|
|
|
2741
2705
|
return this.streaming;
|
|
2742
2706
|
}
|
|
2743
2707
|
}
|
|
2708
|
+
export { DDB };
|
|
2744
2709
|
// const ddb_gateway = {
|
|
2745
2710
|
// server: null as SocketServer,
|
|
2746
2711
|
// clients: new Set<Socket>(),
|