@uwdata/mosaic-core 0.15.0 → 0.16.2
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/dist/types/Coordinator.d.ts +22 -25
- package/dist/types/MosaicClient.d.ts +20 -11
- package/dist/types/QueryManager.d.ts +42 -17
- package/dist/types/Selection.d.ts +1 -1
- package/dist/types/SelectionClause.d.ts +1 -1
- package/dist/types/connectors/Connector.d.ts +25 -0
- package/dist/types/connectors/rest.d.ts +13 -17
- package/dist/types/connectors/socket.d.ts +98 -16
- package/dist/types/connectors/wasm.d.ts +133 -14
- package/dist/types/index-types.d.ts +1 -0
- package/dist/types/preagg/PreAggregator.d.ts +1 -1
- package/dist/types/preagg/preagg-columns.d.ts +2 -2
- package/dist/types/preagg/sufficient-statistics.d.ts +2 -2
- package/dist/types/types.d.ts +21 -0
- package/dist/types/util/cache.d.ts +14 -10
- package/dist/types/util/decode-ipc.d.ts +9 -4
- package/dist/types/util/void-logger.d.ts +3 -0
- package/package.json +4 -4
- package/src/Coordinator.js +15 -12
- package/src/MosaicClient.js +17 -5
- package/src/QueryConsolidator.js +2 -1
- package/src/QueryManager.js +31 -0
- package/src/Selection.js +4 -2
- package/src/SelectionClause.js +5 -2
- package/src/connectors/Connector.ts +30 -0
- package/src/connectors/rest.js +14 -12
- package/src/connectors/socket.js +112 -77
- package/src/connectors/wasm.js +118 -55
- package/src/index-types.ts +1 -0
- package/src/make-client.js +0 -4
- package/src/preagg/PreAggregator.js +8 -6
- package/src/preagg/preagg-columns.js +5 -2
- package/src/preagg/sufficient-statistics.js +2 -1
- package/src/types.ts +23 -0
- package/src/util/cache.js +20 -5
- package/src/util/decode-ipc.js +9 -5
- package/src/util/field-info.js +2 -1
- package/src/util/js-type.js +3 -1
- package/src/util/void-logger.js +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uwdata/mosaic-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.2",
|
|
4
4
|
"description": "Scalable and extensible linked data views.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mosaic",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@duckdb/duckdb-wasm": "^1.29.0",
|
|
34
34
|
"@uwdata/flechette": "^2.0.0",
|
|
35
|
-
"@uwdata/mosaic-sql": "^0.
|
|
35
|
+
"@uwdata/mosaic-sql": "^0.16.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@uwdata/mosaic-duckdb": "^0.
|
|
38
|
+
"@uwdata/mosaic-duckdb": "^0.16.2"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "26d2719f4bcab471d2831145e1f03f39f3509869"
|
|
41
41
|
}
|
package/src/Coordinator.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
/** @import { Connector } from './connectors/Connector.js' */
|
|
1
2
|
/** @import { PreAggregateOptions } from './preagg/PreAggregator.js' */
|
|
2
3
|
/** @import { QueryResult } from './util/query-result.js' */
|
|
3
4
|
/** @import { SelectionClause } from './util/selection-types.js' */
|
|
4
5
|
/** @import { MosaicClient } from './MosaicClient.js' */
|
|
5
6
|
/** @import { Selection } from './Selection.js' */
|
|
6
|
-
/** @import { QueryType } from './types.js' */
|
|
7
|
+
/** @import { Logger, QueryType } from './types.js' */
|
|
7
8
|
import { socketConnector } from './connectors/socket.js';
|
|
8
9
|
import { PreAggregator } from './preagg/PreAggregator.js';
|
|
9
10
|
import { voidLogger } from './util/void-logger.js';
|
|
@@ -33,15 +34,17 @@ export function coordinator(instance) {
|
|
|
33
34
|
* A Mosaic Coordinator manages all database communication for clients and
|
|
34
35
|
* handles selection updates. The Coordinator also performs optimizations
|
|
35
36
|
* including query caching, consolidation, and pre-aggregation.
|
|
36
|
-
* @param {*} [db] Database connector. Defaults to a web socket connection.
|
|
37
|
-
* @param {object} [options] Coordinator options.
|
|
38
|
-
* @param {*} [options.logger=console] The logger to use, defaults to `console`.
|
|
39
|
-
* @param {*} [options.manager] The query manager to use.
|
|
40
|
-
* @param {boolean} [options.cache=true] Boolean flag to enable/disable query caching.
|
|
41
|
-
* @param {boolean} [options.consolidate=true] Boolean flag to enable/disable query consolidation.
|
|
42
|
-
* @param {PreAggregateOptions} [options.preagg] Options for the Pre-aggregator.
|
|
43
37
|
*/
|
|
44
38
|
export class Coordinator {
|
|
39
|
+
/**
|
|
40
|
+
* @param {Connector} [db] Database connector. Defaults to a web socket connection.
|
|
41
|
+
* @param {object} [options] Coordinator options.
|
|
42
|
+
* @param {Logger} [options.logger=console] The logger to use, defaults to `console`.
|
|
43
|
+
* @param {QueryManager} [options.manager] The query manager to use.
|
|
44
|
+
* @param {boolean} [options.cache=true] Boolean flag to enable/disable query caching.
|
|
45
|
+
* @param {boolean} [options.consolidate=true] Boolean flag to enable/disable query consolidation.
|
|
46
|
+
* @param {PreAggregateOptions} [options.preagg] Options for the Pre-aggregator.
|
|
47
|
+
*/
|
|
45
48
|
constructor(db = socketConnector(), {
|
|
46
49
|
logger = console,
|
|
47
50
|
manager = new QueryManager(),
|
|
@@ -78,8 +81,8 @@ export class Coordinator {
|
|
|
78
81
|
|
|
79
82
|
/**
|
|
80
83
|
* Get or set the database connector.
|
|
81
|
-
* @param {
|
|
82
|
-
* @returns The current database connector.
|
|
84
|
+
* @param {Connector} [db] The database connector to use.
|
|
85
|
+
* @returns {Connector} The current database connector.
|
|
83
86
|
*/
|
|
84
87
|
databaseConnector(db) {
|
|
85
88
|
return this.manager.connector(db);
|
|
@@ -87,8 +90,8 @@ export class Coordinator {
|
|
|
87
90
|
|
|
88
91
|
/**
|
|
89
92
|
* Get or set the logger.
|
|
90
|
-
* @param {
|
|
91
|
-
* @returns The current logger
|
|
93
|
+
* @param {Logger} [logger] The logger to use.
|
|
94
|
+
* @returns {Logger} The current logger
|
|
92
95
|
*/
|
|
93
96
|
logger(logger) {
|
|
94
97
|
if (arguments.length) {
|
package/src/MosaicClient.js
CHANGED
|
@@ -27,10 +27,10 @@ export class MosaicClient {
|
|
|
27
27
|
* will re-query and update the client when the selection updates.
|
|
28
28
|
*/
|
|
29
29
|
constructor(filterSelection) {
|
|
30
|
-
/** @type {Selection} */
|
|
30
|
+
/** @type {Selection | undefined} */
|
|
31
31
|
this._filterBy = filterSelection;
|
|
32
32
|
this._requestUpdate = throttle(() => this.requestQuery(), true);
|
|
33
|
-
/** @type {Coordinator} */
|
|
33
|
+
/** @type {Coordinator | null} */
|
|
34
34
|
this._coordinator = null;
|
|
35
35
|
/** @type {Promise<any>} */
|
|
36
36
|
this._pending = Promise.resolve();
|
|
@@ -38,12 +38,12 @@ export class MosaicClient {
|
|
|
38
38
|
this._enabled = true;
|
|
39
39
|
/** @type {boolean} */
|
|
40
40
|
this._initialized = false;
|
|
41
|
-
/** @type {Query | boolean} */
|
|
41
|
+
/** @type {Query | boolean | null} */
|
|
42
42
|
this._request = null;
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
|
-
*
|
|
46
|
+
* @returns {Coordinator | null} this client's connected coordinator.
|
|
47
47
|
*/
|
|
48
48
|
get coordinator() {
|
|
49
49
|
return this._coordinator;
|
|
@@ -91,7 +91,7 @@ export class MosaicClient {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/**
|
|
94
|
-
*
|
|
94
|
+
* @returns {Selection | undefined} this client's filter selection.
|
|
95
95
|
*/
|
|
96
96
|
get filterBy() {
|
|
97
97
|
return this._filterBy;
|
|
@@ -204,6 +204,18 @@ export class MosaicClient {
|
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/**
|
|
208
|
+
* Remove this client: disconnect from the coordinator and free up any
|
|
209
|
+
* resource use. This method has no effect if the client is not connected
|
|
210
|
+
* to a coordinator.
|
|
211
|
+
*
|
|
212
|
+
* If overriding this method in a client subclass, be sure to also
|
|
213
|
+
* disconnect from the coordinator.
|
|
214
|
+
*/
|
|
215
|
+
destroy() {
|
|
216
|
+
this.coordinator?.disconnect(this);
|
|
217
|
+
}
|
|
218
|
+
|
|
207
219
|
/**
|
|
208
220
|
* Requests a client update, for example to (re-)render an interface
|
|
209
221
|
* component.
|
package/src/QueryConsolidator.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { DescribeQuery,
|
|
1
|
+
/** @import { DescribeQuery, Query } from '@uwdata/mosaic-sql' */
|
|
2
|
+
import { isAggregateExpression, isColumnRef, isDescribeQuery, isSelectQuery } from '@uwdata/mosaic-sql';
|
|
2
3
|
import { QueryResult } from './util/query-result.js';
|
|
3
4
|
|
|
4
5
|
function wait(callback) {
|
package/src/QueryManager.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** @import { Connector } from './connectors/Connector.js' */
|
|
2
|
+
/** @import { Cache, Logger } from './types.js' */
|
|
1
3
|
import { consolidator } from './QueryConsolidator.js';
|
|
2
4
|
import { lruCache, voidCache } from './util/cache.js';
|
|
3
5
|
import { PriorityQueue } from './util/priority-queue.js';
|
|
@@ -12,10 +14,15 @@ export class QueryManager {
|
|
|
12
14
|
) {
|
|
13
15
|
/** @type {PriorityQueue} */
|
|
14
16
|
this.queue = new PriorityQueue(3);
|
|
17
|
+
/** @type {Connector} */
|
|
15
18
|
this.db = null;
|
|
19
|
+
/** @type {Cache} */
|
|
16
20
|
this.clientCache = null;
|
|
21
|
+
/** @type {Logger} */
|
|
17
22
|
this._logger = voidLogger();
|
|
23
|
+
/** @type {boolean} */
|
|
18
24
|
this._logQueries = false;
|
|
25
|
+
/** @type {ReturnType<typeof consolidator> | null} */
|
|
19
26
|
this._consolidate = null;
|
|
20
27
|
/**
|
|
21
28
|
* Requests pending with the query manager.
|
|
@@ -106,24 +113,48 @@ export class QueryManager {
|
|
|
106
113
|
}
|
|
107
114
|
}
|
|
108
115
|
|
|
116
|
+
/**
|
|
117
|
+
* Get or set the current query cache.
|
|
118
|
+
* @param {Cache | boolean} [value]
|
|
119
|
+
* @returns {Cache}
|
|
120
|
+
*/
|
|
109
121
|
cache(value) {
|
|
110
122
|
return value !== undefined
|
|
111
123
|
? (this.clientCache = value === true ? lruCache() : (value || voidCache()))
|
|
112
124
|
: this.clientCache;
|
|
113
125
|
}
|
|
114
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Get or set the current logger.
|
|
129
|
+
* @param {Logger} [value]
|
|
130
|
+
* @returns {Logger}
|
|
131
|
+
*/
|
|
115
132
|
logger(value) {
|
|
116
133
|
return value ? (this._logger = value) : this._logger;
|
|
117
134
|
}
|
|
118
135
|
|
|
136
|
+
/**
|
|
137
|
+
* Get or set if queries should be logged.
|
|
138
|
+
* @param {boolean} [value]
|
|
139
|
+
* @returns {boolean}
|
|
140
|
+
*/
|
|
119
141
|
logQueries(value) {
|
|
120
142
|
return value !== undefined ? this._logQueries = !!value : this._logQueries;
|
|
121
143
|
}
|
|
122
144
|
|
|
145
|
+
/**
|
|
146
|
+
* Get or set the database connector.
|
|
147
|
+
* @param {Connector} [connector]
|
|
148
|
+
* @returns {Connector}
|
|
149
|
+
*/
|
|
123
150
|
connector(connector) {
|
|
124
151
|
return connector ? (this.db = connector) : this.db;
|
|
125
152
|
}
|
|
126
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Indicate if query consolidation should be performed.
|
|
156
|
+
* @param {boolean} flag
|
|
157
|
+
*/
|
|
127
158
|
consolidate(flag) {
|
|
128
159
|
if (flag && !this._consolidate) {
|
|
129
160
|
this._consolidate = consolidator(this.enqueue.bind(this), this.clientCache);
|
package/src/Selection.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* @import { MosaicClient } from './MosaicClient.js'
|
|
3
|
+
* @import { SelectionClause } from './util/selection-types.js'
|
|
4
|
+
*/
|
|
2
5
|
import { literal, or } from '@uwdata/mosaic-sql';
|
|
3
6
|
import { Param } from './Param.js';
|
|
4
|
-
import { MosaicClient } from './MosaicClient.js';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Test if a value is a Selection instance.
|
package/src/SelectionClause.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/**
|
|
2
|
+
* @import { ExprNode } from '@uwdata/mosaic-sql'
|
|
3
|
+
* @import { MosaicClient } from './MosaicClient.js'
|
|
4
|
+
*/
|
|
5
|
+
import { and, contains, isBetween, isIn, isNotDistinct, literal, or, prefix, regexp_matches, suffix } from '@uwdata/mosaic-sql';
|
|
3
6
|
|
|
4
7
|
/**
|
|
5
8
|
* @typedef {import('./util/selection-types.js').SelectionClause} SelectionClause
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Table } from '@uwdata/flechette';
|
|
2
|
+
|
|
3
|
+
export interface QueryRequest {
|
|
4
|
+
/** The query type. */
|
|
5
|
+
type?: string;
|
|
6
|
+
/** A SQL query string. */
|
|
7
|
+
sql: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface ArrowQueryRequest extends QueryRequest {
|
|
11
|
+
/** The query type. */
|
|
12
|
+
type?: 'arrow';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ExecQueryRequest extends QueryRequest {
|
|
16
|
+
/** The query type. */
|
|
17
|
+
type: 'exec';
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface JSONQueryRequest extends QueryRequest {
|
|
21
|
+
/** The query type. */
|
|
22
|
+
type: 'json';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface Connector {
|
|
26
|
+
/** Issue a query and return the result. */
|
|
27
|
+
query(query: ArrowQueryRequest): Promise<Table>;
|
|
28
|
+
query(query: ExecQueryRequest): Promise<void>;
|
|
29
|
+
query(query: JSONQueryRequest): Promise<Record<string, any>[]>;
|
|
30
|
+
}
|
package/src/connectors/rest.js
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
|
+
/** @import { ExtractionOptions } from '@uwdata/flechette' */
|
|
2
|
+
/** @import { Connector } from './Connector.js' */
|
|
1
3
|
import { decodeIPC } from '../util/decode-ipc.js';
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Connect to a DuckDB server over an HTTP REST interface.
|
|
7
|
+
* @param {object} [options] Connector options.
|
|
8
|
+
* @param {string} [options.uri] The URI for the DuckDB REST server.
|
|
9
|
+
* @param {ExtractionOptions} [options.ipc] Arrow IPC extraction options.
|
|
10
|
+
* @returns {Connector} A connector instance.
|
|
11
|
+
*/
|
|
12
|
+
export function restConnector({
|
|
13
|
+
uri = 'http://localhost:3000/',
|
|
14
|
+
ipc = undefined,
|
|
15
|
+
} = {}) {
|
|
4
16
|
return {
|
|
5
|
-
/**
|
|
6
|
-
* Query the DuckDB server.
|
|
7
|
-
* @param {object} query
|
|
8
|
-
* @param {'exec' | 'arrow' | 'json' | 'create-bundle' | 'load-bundle'} [query.type] The query type.
|
|
9
|
-
* @param {string} [query.sql] A SQL query string.
|
|
10
|
-
* @param {string[]} [query.queries] The queries used to create a bundle.
|
|
11
|
-
* @param {string} [query.name] The name of a bundle to create or load.
|
|
12
|
-
* @returns the query result
|
|
13
|
-
*/
|
|
14
17
|
async query(query) {
|
|
15
18
|
const req = fetch(uri, {
|
|
16
19
|
method: 'POST',
|
|
@@ -21,7 +24,6 @@ export function restConnector(uri = 'http://localhost:3000/') {
|
|
|
21
24
|
body: JSON.stringify(query)
|
|
22
25
|
});
|
|
23
26
|
|
|
24
|
-
|
|
25
27
|
const res = await req;
|
|
26
28
|
|
|
27
29
|
if (!res.ok) {
|
|
@@ -29,7 +31,7 @@ export function restConnector(uri = 'http://localhost:3000/') {
|
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
return query.type === 'exec' ? req
|
|
32
|
-
: query.type === 'arrow' ? decodeIPC(await res.arrayBuffer())
|
|
34
|
+
: query.type === 'arrow' ? decodeIPC(await res.arrayBuffer(), ipc)
|
|
33
35
|
: res.json();
|
|
34
36
|
}
|
|
35
37
|
};
|
package/src/connectors/socket.js
CHANGED
|
@@ -1,100 +1,135 @@
|
|
|
1
|
+
/** @import { ExtractionOptions, Table } from '@uwdata/flechette' */
|
|
2
|
+
/** @import { ArrowQueryRequest, Connector, ExecQueryRequest, JSONQueryRequest } from './Connector.js' */
|
|
1
3
|
import { decodeIPC } from '../util/decode-ipc.js';
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Connect to a DuckDB server over a WebSocket interface.
|
|
7
|
+
* @param {object} [options] Connector options.
|
|
8
|
+
* @param {string} [options.uri] The URI for the DuckDB REST server.
|
|
9
|
+
* @param {ExtractionOptions} [options.ipc] Arrow IPC extraction options.
|
|
10
|
+
* @returns {SocketConnector} A connector instance.
|
|
11
|
+
*/
|
|
12
|
+
export function socketConnector(options) {
|
|
13
|
+
return new SocketConnector(options);
|
|
14
|
+
}
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
16
|
+
/**
|
|
17
|
+
* DuckDB socket connector.
|
|
18
|
+
* @implements {Connector}
|
|
19
|
+
*/
|
|
20
|
+
export class SocketConnector {
|
|
21
|
+
/**
|
|
22
|
+
* @param {object} [options] Connector options.
|
|
23
|
+
* @param {string} [options.uri] The URI for the DuckDB REST server.
|
|
24
|
+
* @param {ExtractionOptions} [options.ipc] Arrow IPC extraction options.
|
|
25
|
+
*/
|
|
26
|
+
constructor({
|
|
27
|
+
uri = 'ws://localhost:3000/',
|
|
28
|
+
ipc = undefined,
|
|
29
|
+
} = {}) {
|
|
30
|
+
this._uri = uri;
|
|
31
|
+
this._queue = [];
|
|
32
|
+
this._connected = false;
|
|
33
|
+
this._request = null;
|
|
34
|
+
this._ws = null;
|
|
14
35
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
},
|
|
36
|
+
const c = this;
|
|
37
|
+
this._events = {
|
|
38
|
+
open() {
|
|
39
|
+
c._connected = true;
|
|
40
|
+
c.next();
|
|
41
|
+
},
|
|
23
42
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
},
|
|
43
|
+
close() {
|
|
44
|
+
c._connected = false;
|
|
45
|
+
c._request = null;
|
|
46
|
+
c._ws = null;
|
|
47
|
+
while (c._queue.length) {
|
|
48
|
+
c._queue.shift().reject('Socket closed');
|
|
49
|
+
}
|
|
50
|
+
},
|
|
34
51
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
52
|
+
error(event) {
|
|
53
|
+
if (c._request) {
|
|
54
|
+
const { reject } = c._request;
|
|
55
|
+
c._request = null;
|
|
56
|
+
c.next();
|
|
57
|
+
reject(event);
|
|
58
|
+
} else {
|
|
59
|
+
console.error('WebSocket error: ', event);
|
|
60
|
+
}
|
|
61
|
+
},
|
|
38
62
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
63
|
+
message({ data }) {
|
|
64
|
+
if (c._request) {
|
|
65
|
+
const { query, resolve, reject } = c._request;
|
|
42
66
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
67
|
+
// clear state, start next request
|
|
68
|
+
c._request = null;
|
|
69
|
+
c.next();
|
|
70
|
+
|
|
71
|
+
// process result
|
|
72
|
+
if (typeof data === 'string') {
|
|
73
|
+
const json = JSON.parse(data);
|
|
74
|
+
json.error ? reject(json.error) : resolve(json);
|
|
75
|
+
} else if (query.type === 'exec') {
|
|
76
|
+
resolve();
|
|
77
|
+
} else if (query.type === 'arrow') {
|
|
78
|
+
resolve(decodeIPC(data, ipc));
|
|
79
|
+
} else {
|
|
80
|
+
throw new Error(`Unexpected socket data: ${data}`);
|
|
81
|
+
}
|
|
51
82
|
} else {
|
|
52
|
-
|
|
83
|
+
console.log('WebSocket message: ', data);
|
|
53
84
|
}
|
|
54
|
-
} else {
|
|
55
|
-
console.log('WebSocket message: ', data);
|
|
56
85
|
}
|
|
57
86
|
}
|
|
58
87
|
}
|
|
59
88
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
89
|
+
get connected() {
|
|
90
|
+
return this._connected;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
init() {
|
|
94
|
+
this._ws = new WebSocket(this._uri);
|
|
95
|
+
this._ws.binaryType = 'arraybuffer';
|
|
96
|
+
for (const type in this._events) {
|
|
97
|
+
this._ws.addEventListener(type, this._events[type]);
|
|
65
98
|
}
|
|
66
99
|
}
|
|
67
100
|
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
if (
|
|
101
|
+
enqueue(query, resolve, reject) {
|
|
102
|
+
if (this._ws == null) this.init();
|
|
103
|
+
this._queue.push({ query, resolve, reject });
|
|
104
|
+
if (this._connected && !this._request) this.next();
|
|
72
105
|
}
|
|
73
106
|
|
|
74
|
-
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
|
|
107
|
+
next() {
|
|
108
|
+
if (this._queue.length) {
|
|
109
|
+
this._request = this._queue.shift();
|
|
110
|
+
this._ws.send(JSON.stringify(this._request.query));
|
|
78
111
|
}
|
|
79
112
|
}
|
|
80
113
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
114
|
+
/**
|
|
115
|
+
* @overload
|
|
116
|
+
* @param {ArrowQueryRequest} query
|
|
117
|
+
* @returns {Promise<Table>}
|
|
118
|
+
*
|
|
119
|
+
* @overload
|
|
120
|
+
* @param {ExecQueryRequest} query
|
|
121
|
+
* @returns {Promise<void>}
|
|
122
|
+
*
|
|
123
|
+
* @overload
|
|
124
|
+
* @param {JSONQueryRequest} query
|
|
125
|
+
* @returns {Promise<Record<string, any>[]>}
|
|
126
|
+
*
|
|
127
|
+
* @param {ArrowQueryRequest | ExecQueryRequest | JSONQueryRequest} query
|
|
128
|
+
* @returns {Promise<Table | void | Record<string, any>[]>}}
|
|
129
|
+
*/
|
|
130
|
+
query(query) {
|
|
131
|
+
return new Promise(
|
|
132
|
+
(resolve, reject) => this.enqueue(query, resolve, reject)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
100
135
|
}
|