@uwdata/mosaic-core 0.12.2 → 0.13.0
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 +14 -15
- package/dist/types/MosaicClient.d.ts +20 -6
- package/dist/types/QueryManager.d.ts +3 -1
- package/dist/types/index-types.d.ts +3 -0
- package/dist/types/index.d.ts +2 -10
- package/dist/types/make-client.d.ts +48 -0
- package/dist/types/types.d.ts +12 -1
- package/dist/types/util/is-activatable.d.ts +6 -0
- package/dist/types/util/throttle.d.ts +5 -3
- package/package.json +12 -12
- package/src/Coordinator.js +14 -17
- package/src/MosaicClient.js +20 -1
- package/src/QueryManager.js +3 -1
- package/src/connectors/rest.js +9 -2
- package/src/index-types.ts +3 -0
- package/src/index.js +2 -13
- package/src/make-client.js +64 -0
- package/src/preagg/sufficient-statistics.js +21 -1
- package/src/types.ts +17 -1
- package/src/util/is-activatable.js +8 -0
- package/src/util/throttle.js +4 -2
- package/vitest.config.ts +3 -0
- package/dist/mosaic-core.js +0 -18788
- package/dist/mosaic-core.min.js +0 -11
|
@@ -70,22 +70,22 @@ export class Coordinator {
|
|
|
70
70
|
cancel(requests: QueryResult[]): void;
|
|
71
71
|
/**
|
|
72
72
|
* Issue a query for which no result (return value) is needed.
|
|
73
|
-
* @param {
|
|
73
|
+
* @param { import('./types.js').QueryType[] |
|
|
74
|
+
* import('./types.js').QueryType} query The query or an array of queries.
|
|
74
75
|
* Each query should be either a Query builder object or a SQL string.
|
|
75
76
|
* @param {object} [options] An options object.
|
|
76
77
|
* @param {number} [options.priority] The query priority, defaults to
|
|
77
78
|
* `Priority.Normal`.
|
|
78
|
-
* @returns {QueryResult} A query result
|
|
79
|
-
* promise.
|
|
79
|
+
* @returns {QueryResult} A query result promise.
|
|
80
80
|
*/
|
|
81
|
-
exec(query: QueryType | QueryType
|
|
81
|
+
exec(query: import("./types.js").QueryType[] | import("./types.js").QueryType, { priority }?: {
|
|
82
82
|
priority?: number;
|
|
83
83
|
}): QueryResult;
|
|
84
84
|
/**
|
|
85
85
|
* Issue a query to the backing database. The submitted query may be
|
|
86
86
|
* consolidate with other queries and its results may be cached.
|
|
87
|
-
* @param {QueryType} query The query as either a Query
|
|
88
|
-
* or a SQL string.
|
|
87
|
+
* @param {import('./types.js').QueryType} query The query as either a Query
|
|
88
|
+
* builder object or a SQL string.
|
|
89
89
|
* @param {object} [options] An options object.
|
|
90
90
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
91
91
|
* @param {boolean} [options.cache=true] If true, cache the query result
|
|
@@ -96,7 +96,7 @@ export class Coordinator {
|
|
|
96
96
|
* `Priority.Normal`.
|
|
97
97
|
* @returns {QueryResult} A query result promise.
|
|
98
98
|
*/
|
|
99
|
-
query(query: QueryType, { type, cache, priority, ...options }?: {
|
|
99
|
+
query(query: import("./types.js").QueryType, { type, cache, priority, ...options }?: {
|
|
100
100
|
type?: "arrow" | "json";
|
|
101
101
|
cache?: boolean;
|
|
102
102
|
persist?: boolean;
|
|
@@ -105,13 +105,13 @@ export class Coordinator {
|
|
|
105
105
|
/**
|
|
106
106
|
* Issue a query to prefetch data for later use. The query result is cached
|
|
107
107
|
* for efficient future access.
|
|
108
|
-
* @param {QueryType} query The query as either a Query
|
|
109
|
-
* or a SQL string.
|
|
108
|
+
* @param {import('./types.js').QueryType} query The query as either a Query
|
|
109
|
+
* builder object or a SQL string.
|
|
110
110
|
* @param {object} [options] An options object.
|
|
111
111
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
112
112
|
* @returns {QueryResult} A query result promise.
|
|
113
113
|
*/
|
|
114
|
-
prefetch(query: QueryType, options?: {
|
|
114
|
+
prefetch(query: import("./types.js").QueryType, options?: {
|
|
115
115
|
type?: "arrow" | "json";
|
|
116
116
|
}): QueryResult;
|
|
117
117
|
/**
|
|
@@ -138,19 +138,19 @@ export class Coordinator {
|
|
|
138
138
|
* Update client data by submitting the given query and returning the
|
|
139
139
|
* data (or error) to the client.
|
|
140
140
|
* @param {MosaicClient} client A Mosaic client.
|
|
141
|
-
* @param {QueryType} query The data query.
|
|
141
|
+
* @param {import('./types.js').QueryType} query The data query.
|
|
142
142
|
* @param {number} [priority] The query priority.
|
|
143
143
|
* @returns {Promise} A Promise that resolves upon completion of the update.
|
|
144
144
|
*/
|
|
145
|
-
updateClient(client: MosaicClient, query: QueryType, priority?: number): Promise<any>;
|
|
145
|
+
updateClient(client: MosaicClient, query: import("./types.js").QueryType, priority?: number): Promise<any>;
|
|
146
146
|
/**
|
|
147
147
|
* Issue a query request for a client. If the query is null or undefined,
|
|
148
148
|
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
149
149
|
* side effect, this method clears the current preaggregator state.
|
|
150
150
|
* @param {MosaicClient} client The client to update.
|
|
151
|
-
* @param {QueryType | null} [query] The query to issue.
|
|
151
|
+
* @param {import('./types.js').QueryType | null} [query] The query to issue.
|
|
152
152
|
*/
|
|
153
|
-
requestQuery(client: MosaicClient, query?: QueryType | null): Promise<any>;
|
|
153
|
+
requestQuery(client: MosaicClient, query?: import("./types.js").QueryType | null): Promise<any>;
|
|
154
154
|
/**
|
|
155
155
|
* Connect a client to the coordinator.
|
|
156
156
|
* @param {MosaicClient} client The Mosaic client to connect.
|
|
@@ -163,7 +163,6 @@ export class Coordinator {
|
|
|
163
163
|
*/
|
|
164
164
|
disconnect(client: MosaicClient): void;
|
|
165
165
|
}
|
|
166
|
-
export type QueryType = import("@uwdata/mosaic-sql").Query | import("@uwdata/mosaic-sql").DescribeQuery | string;
|
|
167
166
|
import { QueryManager } from './QueryManager.js';
|
|
168
167
|
import { PreAggregator } from './preagg/PreAggregator.js';
|
|
169
168
|
import { QueryResult } from './util/query-result.js';
|
|
@@ -9,21 +9,29 @@ export class MosaicClient {
|
|
|
9
9
|
* the client when the selection updates.
|
|
10
10
|
*/
|
|
11
11
|
constructor(filterSelection: any);
|
|
12
|
-
|
|
12
|
+
/** @type {Selection} */
|
|
13
|
+
_filterBy: Selection;
|
|
13
14
|
_requestUpdate: (event: any) => void;
|
|
14
|
-
|
|
15
|
+
/** @type {Coordinator} */
|
|
16
|
+
_coordinator: Coordinator;
|
|
17
|
+
/** @type {Promise<any>} */
|
|
18
|
+
_pending: Promise<any>;
|
|
15
19
|
/**
|
|
16
20
|
* Set this client's connected coordinator.
|
|
17
21
|
*/
|
|
18
|
-
set coordinator(coordinator:
|
|
22
|
+
set coordinator(coordinator: Coordinator);
|
|
19
23
|
/**
|
|
20
24
|
* Return this client's connected coordinator.
|
|
21
25
|
*/
|
|
22
|
-
get coordinator():
|
|
26
|
+
get coordinator(): Coordinator;
|
|
27
|
+
/**
|
|
28
|
+
* Return a Promise that resolves once the client has updated.
|
|
29
|
+
*/
|
|
30
|
+
get pending(): Promise<any>;
|
|
23
31
|
/**
|
|
24
32
|
* Return this client's filter selection.
|
|
25
33
|
*/
|
|
26
|
-
get filterBy():
|
|
34
|
+
get filterBy(): Selection;
|
|
27
35
|
/**
|
|
28
36
|
* Return a boolean indicating if the client query can be sped up with
|
|
29
37
|
* materialized views of pre-aggregated data. Should return true if changes to
|
|
@@ -43,6 +51,10 @@ export class MosaicClient {
|
|
|
43
51
|
* @returns {this}
|
|
44
52
|
*/
|
|
45
53
|
fieldInfo(info: import("./types.js").FieldInfo[]): this;
|
|
54
|
+
/**
|
|
55
|
+
* Prepare the client before the query() method is called.
|
|
56
|
+
*/
|
|
57
|
+
prepare(): Promise<void>;
|
|
46
58
|
/**
|
|
47
59
|
* Return a query specifying the data needed by this client.
|
|
48
60
|
* @param {*} [filter] The filtering criteria to apply in the query.
|
|
@@ -81,7 +93,7 @@ export class MosaicClient {
|
|
|
81
93
|
*/
|
|
82
94
|
requestUpdate(): void;
|
|
83
95
|
/**
|
|
84
|
-
* Reset this client, initiating new field info and query requests.
|
|
96
|
+
* Reset this client, initiating new field info, call the prepare method, and query requests.
|
|
85
97
|
* @returns {Promise}
|
|
86
98
|
*/
|
|
87
99
|
initialize(): Promise<any>;
|
|
@@ -93,3 +105,5 @@ export class MosaicClient {
|
|
|
93
105
|
*/
|
|
94
106
|
update(): this | Promise<any>;
|
|
95
107
|
}
|
|
108
|
+
import { Selection } from './Selection.js';
|
|
109
|
+
import { Coordinator } from './Coordinator.js';
|
|
@@ -5,6 +5,7 @@ export const Priority: Readonly<{
|
|
|
5
5
|
}>;
|
|
6
6
|
export class QueryManager {
|
|
7
7
|
constructor(maxConcurrentRequests?: number);
|
|
8
|
+
/** @type {PriorityQueue} */
|
|
8
9
|
queue: PriorityQueue;
|
|
9
10
|
db: any;
|
|
10
11
|
clientCache: any;
|
|
@@ -21,11 +22,12 @@ export class QueryManager {
|
|
|
21
22
|
};
|
|
22
23
|
/**
|
|
23
24
|
* Requests pending with the query manager.
|
|
24
|
-
*
|
|
25
25
|
* @type {QueryResult[]}
|
|
26
26
|
*/
|
|
27
27
|
pendingResults: QueryResult[];
|
|
28
|
+
/** @type {number} */
|
|
28
29
|
maxConcurrentRequests: number;
|
|
30
|
+
/** @type {boolean} */
|
|
29
31
|
pendingExec: boolean;
|
|
30
32
|
next(): void;
|
|
31
33
|
/**
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { MosaicClient } from "./MosaicClient.js";
|
|
2
|
+
export { makeClient } from "./make-client.js";
|
|
2
3
|
export { Priority } from "./QueryManager.js";
|
|
3
4
|
export { restConnector } from "./connectors/rest.js";
|
|
4
5
|
export { socketConnector } from "./connectors/socket.js";
|
|
@@ -11,16 +12,7 @@ export { throttle } from "./util/throttle.js";
|
|
|
11
12
|
export { toDataColumns } from "./util/to-data-columns.js";
|
|
12
13
|
export { queryFieldInfo } from "./util/field-info.js";
|
|
13
14
|
export { jsType } from "./util/js-type.js";
|
|
14
|
-
export
|
|
15
|
-
export type PointMetadata = import("./util/selection-types.js").PointMetadata;
|
|
16
|
-
export type MatchMethod = import("./util/selection-types.js").MatchMethod;
|
|
17
|
-
export type MatchMetadata = import("./util/selection-types.js").MatchMetadata;
|
|
18
|
-
export type ScaleType = import("./util/selection-types.js").ScaleType;
|
|
19
|
-
export type Extent = import("./util/selection-types.js").Extent;
|
|
20
|
-
export type Scale = import("./util/selection-types.js").Scale;
|
|
21
|
-
export type BinMethod = import("./util/selection-types.js").BinMethod;
|
|
22
|
-
export type IntervalMetadata = import("./util/selection-types.js").IntervalMetadata;
|
|
23
|
-
export type SelectionClause = import("./util/selection-types.js").SelectionClause;
|
|
15
|
+
export { isActivatable } from "./util/is-activatable.js";
|
|
24
16
|
export { Coordinator, coordinator } from "./Coordinator.js";
|
|
25
17
|
export { Selection, isSelection } from "./Selection.js";
|
|
26
18
|
export { Param, isParam } from "./Param.js";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Object} MakeClientOptions
|
|
3
|
+
* @property {import('./Coordinator.js').Coordinator} [coordinator] - Mosaic coordinator. Default to the global coordinator.
|
|
4
|
+
* @property {import('./Selection.js').Selection|null} [selection] - A selection whose predicates will be fed into the query function to produce the SQL query.
|
|
5
|
+
* @property {function(): Promise<void>} [prepare] - An async function to prepare the client before running queries.
|
|
6
|
+
* @property {function(any): any} query - A function that returns a query from a list of selection predicates.
|
|
7
|
+
* @property {function(any): void} [queryResult] - Called by the coordinator to return a query result.
|
|
8
|
+
* @property {function(): void} [queryPending] - Called by the coordinator to report a query execution error.
|
|
9
|
+
* @property {function(any): void} [queryError] - Called by the coordinator to inform the client that a query is pending.
|
|
10
|
+
*/
|
|
11
|
+
/** Make a new client with the given options, and connect the client to the provided coordinator.
|
|
12
|
+
* @param {MakeClientOptions} options - The options for making the client
|
|
13
|
+
* @returns {MosaicClient & { destroy: () => void }} - The result object with methods to request an update or destroy the client.
|
|
14
|
+
*/
|
|
15
|
+
export function makeClient(options: MakeClientOptions): MosaicClient & {
|
|
16
|
+
destroy: () => void;
|
|
17
|
+
};
|
|
18
|
+
export type MakeClientOptions = {
|
|
19
|
+
/**
|
|
20
|
+
* - Mosaic coordinator. Default to the global coordinator.
|
|
21
|
+
*/
|
|
22
|
+
coordinator?: import("./Coordinator.js").Coordinator;
|
|
23
|
+
/**
|
|
24
|
+
* - A selection whose predicates will be fed into the query function to produce the SQL query.
|
|
25
|
+
*/
|
|
26
|
+
selection?: import("./Selection.js").Selection | null;
|
|
27
|
+
/**
|
|
28
|
+
* - An async function to prepare the client before running queries.
|
|
29
|
+
*/
|
|
30
|
+
prepare?: () => Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* - A function that returns a query from a list of selection predicates.
|
|
33
|
+
*/
|
|
34
|
+
query: (arg0: any) => any;
|
|
35
|
+
/**
|
|
36
|
+
* - Called by the coordinator to return a query result.
|
|
37
|
+
*/
|
|
38
|
+
queryResult?: (arg0: any) => void;
|
|
39
|
+
/**
|
|
40
|
+
* - Called by the coordinator to report a query execution error.
|
|
41
|
+
*/
|
|
42
|
+
queryPending?: () => void;
|
|
43
|
+
/**
|
|
44
|
+
* - Called by the coordinator to inform the client that a query is pending.
|
|
45
|
+
*/
|
|
46
|
+
queryError?: (arg0: any) => void;
|
|
47
|
+
};
|
|
48
|
+
import { MosaicClient } from "./MosaicClient.js";
|
package/dist/types/types.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import type { ExprNode } from '@uwdata/mosaic-sql';
|
|
1
|
+
import type { DescribeQuery, ExprNode, Query } from '@uwdata/mosaic-sql';
|
|
2
|
+
/** Query type accepted by a coordinator. */
|
|
3
|
+
export type QueryType = string | Query | DescribeQuery;
|
|
2
4
|
/** String indicating a JavaScript data type. */
|
|
3
5
|
export type JSType = 'number' | 'date' | 'boolean' | 'string' | 'array' | 'object';
|
|
4
6
|
/** String indicating a requested summary statistic. */
|
|
@@ -29,3 +31,12 @@ export interface ColumnDescription {
|
|
|
29
31
|
column_type: string;
|
|
30
32
|
null: 'YES' | 'NO';
|
|
31
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Interface for components that perform selection activation.
|
|
36
|
+
*/
|
|
37
|
+
export interface Activatable {
|
|
38
|
+
/**
|
|
39
|
+
* Activate the selection that this component publishes to.
|
|
40
|
+
*/
|
|
41
|
+
activate(): void;
|
|
42
|
+
}
|
|
@@ -3,9 +3,11 @@
|
|
|
3
3
|
* a Promise. Upon repeated invocation, the callback will not be invoked
|
|
4
4
|
* until a prior Promise resolves. If multiple invocations occurs while
|
|
5
5
|
* waiting, only the most recent invocation will be pending.
|
|
6
|
-
* @
|
|
6
|
+
* @template E, T
|
|
7
|
+
* @param {(event: E) => Promise<T>} callback The callback function.
|
|
7
8
|
* @param {boolean} [debounce=true] Flag indicating if invocations
|
|
8
9
|
* should also be debounced within the current animation frame.
|
|
9
|
-
* @returns A new function that throttles
|
|
10
|
+
* @returns {(event: E) => void} A new function that throttles
|
|
11
|
+
* access to the callback.
|
|
10
12
|
*/
|
|
11
|
-
export function throttle(callback: (event:
|
|
13
|
+
export function throttle<E, T>(callback: (event: E) => Promise<T>, debounce?: boolean): (event: E) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uwdata/mosaic-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Scalable and extensible linked data views.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mosaic",
|
|
@@ -12,30 +12,30 @@
|
|
|
12
12
|
"license": "BSD-3-Clause",
|
|
13
13
|
"author": "Jeffrey Heer (https://idl.uw.edu)",
|
|
14
14
|
"type": "module",
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"types": "dist/types/index.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
"types": "./dist/types/index-types.d.ts",
|
|
17
|
+
"default": "./src/index.js"
|
|
18
|
+
},
|
|
20
19
|
"repository": {
|
|
21
20
|
"type": "git",
|
|
22
21
|
"url": "https://github.com/uwdata/mosaic.git"
|
|
23
22
|
},
|
|
24
23
|
"scripts": {
|
|
25
24
|
"prebuild": "rimraf dist && mkdir dist",
|
|
26
|
-
"build": "npm run types
|
|
25
|
+
"build": "npm run types",
|
|
27
26
|
"types": "tsc",
|
|
28
27
|
"lint": "eslint src test",
|
|
29
|
-
"test": "vitest run &&
|
|
28
|
+
"test": "vitest run && npm run tsc",
|
|
29
|
+
"tsc": "tsc -p jsconfig.json",
|
|
30
30
|
"prepublishOnly": "npm run test && npm run lint && npm run build"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@duckdb/duckdb-wasm": "^1.29.0",
|
|
34
|
-
"@uwdata/flechette": "^
|
|
35
|
-
"@uwdata/mosaic-sql": "^0.
|
|
34
|
+
"@uwdata/flechette": "^2.0.0",
|
|
35
|
+
"@uwdata/mosaic-sql": "^0.13.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@uwdata/mosaic-duckdb": "^0.
|
|
38
|
+
"@uwdata/mosaic-duckdb": "^0.13.0"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "b5a0e03e200c0f04c46562a288f084ffc9f6ad55"
|
|
41
41
|
}
|
package/src/Coordinator.js
CHANGED
|
@@ -6,12 +6,6 @@ import { voidLogger } from './util/void-logger.js';
|
|
|
6
6
|
import { MosaicClient } from './MosaicClient.js';
|
|
7
7
|
import { QueryManager, Priority } from './QueryManager.js';
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* @typedef {import('@uwdata/mosaic-sql').Query
|
|
11
|
-
* | import('@uwdata/mosaic-sql').DescribeQuery
|
|
12
|
-
* | string} QueryType
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
9
|
/**
|
|
16
10
|
* The singleton Coordinator instance.
|
|
17
11
|
* @type {Coordinator}
|
|
@@ -116,13 +110,13 @@ export class Coordinator {
|
|
|
116
110
|
|
|
117
111
|
/**
|
|
118
112
|
* Issue a query for which no result (return value) is needed.
|
|
119
|
-
* @param {
|
|
113
|
+
* @param { import('./types.js').QueryType[] |
|
|
114
|
+
* import('./types.js').QueryType} query The query or an array of queries.
|
|
120
115
|
* Each query should be either a Query builder object or a SQL string.
|
|
121
116
|
* @param {object} [options] An options object.
|
|
122
117
|
* @param {number} [options.priority] The query priority, defaults to
|
|
123
118
|
* `Priority.Normal`.
|
|
124
|
-
* @returns {QueryResult} A query result
|
|
125
|
-
* promise.
|
|
119
|
+
* @returns {QueryResult} A query result promise.
|
|
126
120
|
*/
|
|
127
121
|
exec(query, { priority = Priority.Normal } = {}) {
|
|
128
122
|
query = Array.isArray(query) ? query.filter(x => x).join(';\n') : query;
|
|
@@ -132,8 +126,8 @@ export class Coordinator {
|
|
|
132
126
|
/**
|
|
133
127
|
* Issue a query to the backing database. The submitted query may be
|
|
134
128
|
* consolidate with other queries and its results may be cached.
|
|
135
|
-
* @param {QueryType} query The query as either a Query
|
|
136
|
-
* or a SQL string.
|
|
129
|
+
* @param {import('./types.js').QueryType} query The query as either a Query
|
|
130
|
+
* builder object or a SQL string.
|
|
137
131
|
* @param {object} [options] An options object.
|
|
138
132
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
139
133
|
* @param {boolean} [options.cache=true] If true, cache the query result
|
|
@@ -156,8 +150,8 @@ export class Coordinator {
|
|
|
156
150
|
/**
|
|
157
151
|
* Issue a query to prefetch data for later use. The query result is cached
|
|
158
152
|
* for efficient future access.
|
|
159
|
-
* @param {QueryType} query The query as either a Query
|
|
160
|
-
* or a SQL string.
|
|
153
|
+
* @param {import('./types.js').QueryType} query The query as either a Query
|
|
154
|
+
* builder object or a SQL string.
|
|
161
155
|
* @param {object} [options] An options object.
|
|
162
156
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
163
157
|
* @returns {QueryResult} A query result promise.
|
|
@@ -196,13 +190,13 @@ export class Coordinator {
|
|
|
196
190
|
* Update client data by submitting the given query and returning the
|
|
197
191
|
* data (or error) to the client.
|
|
198
192
|
* @param {MosaicClient} client A Mosaic client.
|
|
199
|
-
* @param {QueryType} query The data query.
|
|
193
|
+
* @param {import('./types.js').QueryType} query The data query.
|
|
200
194
|
* @param {number} [priority] The query priority.
|
|
201
195
|
* @returns {Promise} A Promise that resolves upon completion of the update.
|
|
202
196
|
*/
|
|
203
197
|
updateClient(client, query, priority = Priority.Normal) {
|
|
204
198
|
client.queryPending();
|
|
205
|
-
return this.query(query, { priority })
|
|
199
|
+
return client._pending = this.query(query, { priority })
|
|
206
200
|
.then(
|
|
207
201
|
data => client.queryResult(data).update(),
|
|
208
202
|
err => { this._logger.error(err); client.queryError(err); }
|
|
@@ -215,7 +209,7 @@ export class Coordinator {
|
|
|
215
209
|
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
216
210
|
* side effect, this method clears the current preaggregator state.
|
|
217
211
|
* @param {MosaicClient} client The client to update.
|
|
218
|
-
* @param {QueryType | null} [query] The query to issue.
|
|
212
|
+
* @param {import('./types.js').QueryType | null} [query] The query to issue.
|
|
219
213
|
*/
|
|
220
214
|
requestQuery(client, query) {
|
|
221
215
|
this.preaggregator.clear();
|
|
@@ -238,7 +232,7 @@ export class Coordinator {
|
|
|
238
232
|
client.coordinator = this;
|
|
239
233
|
|
|
240
234
|
// initialize client lifecycle
|
|
241
|
-
this.initializeClient(client);
|
|
235
|
+
client._pending = this.initializeClient(client);
|
|
242
236
|
|
|
243
237
|
// connect filter selection
|
|
244
238
|
connectSelection(this, client.filterBy, client);
|
|
@@ -251,6 +245,9 @@ export class Coordinator {
|
|
|
251
245
|
client.fieldInfo(await queryFieldInfo(this, fields));
|
|
252
246
|
}
|
|
253
247
|
|
|
248
|
+
// prepare the client
|
|
249
|
+
await client.prepare();
|
|
250
|
+
|
|
254
251
|
// request data query
|
|
255
252
|
return client.requestQuery();
|
|
256
253
|
}
|
package/src/MosaicClient.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Coordinator } from './Coordinator.js';
|
|
2
|
+
import { Selection } from './Selection.js';
|
|
1
3
|
import { throttle } from './util/throttle.js';
|
|
2
4
|
|
|
3
5
|
/**
|
|
@@ -11,9 +13,13 @@ export class MosaicClient {
|
|
|
11
13
|
* the client when the selection updates.
|
|
12
14
|
*/
|
|
13
15
|
constructor(filterSelection) {
|
|
16
|
+
/** @type {Selection} */
|
|
14
17
|
this._filterBy = filterSelection;
|
|
15
18
|
this._requestUpdate = throttle(() => this.requestQuery(), true);
|
|
19
|
+
/** @type {Coordinator} */
|
|
16
20
|
this._coordinator = null;
|
|
21
|
+
/** @type {Promise<any>} */
|
|
22
|
+
this._pending = Promise.resolve();
|
|
17
23
|
}
|
|
18
24
|
|
|
19
25
|
/**
|
|
@@ -30,6 +36,13 @@ export class MosaicClient {
|
|
|
30
36
|
this._coordinator = coordinator;
|
|
31
37
|
}
|
|
32
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Return a Promise that resolves once the client has updated.
|
|
41
|
+
*/
|
|
42
|
+
get pending() {
|
|
43
|
+
return this._pending;
|
|
44
|
+
}
|
|
45
|
+
|
|
33
46
|
/**
|
|
34
47
|
* Return this client's filter selection.
|
|
35
48
|
*/
|
|
@@ -65,6 +78,12 @@ export class MosaicClient {
|
|
|
65
78
|
return this;
|
|
66
79
|
}
|
|
67
80
|
|
|
81
|
+
/**
|
|
82
|
+
* Prepare the client before the query() method is called.
|
|
83
|
+
*/
|
|
84
|
+
async prepare() {
|
|
85
|
+
}
|
|
86
|
+
|
|
68
87
|
/**
|
|
69
88
|
* Return a query specifying the data needed by this client.
|
|
70
89
|
* @param {*} [filter] The filtering criteria to apply in the query.
|
|
@@ -123,7 +142,7 @@ export class MosaicClient {
|
|
|
123
142
|
}
|
|
124
143
|
|
|
125
144
|
/**
|
|
126
|
-
* Reset this client, initiating new field info and query requests.
|
|
145
|
+
* Reset this client, initiating new field info, call the prepare method, and query requests.
|
|
127
146
|
* @returns {Promise}
|
|
128
147
|
*/
|
|
129
148
|
initialize() {
|
package/src/QueryManager.js
CHANGED
|
@@ -10,6 +10,7 @@ export class QueryManager {
|
|
|
10
10
|
constructor(
|
|
11
11
|
maxConcurrentRequests = 32
|
|
12
12
|
) {
|
|
13
|
+
/** @type {PriorityQueue} */
|
|
13
14
|
this.queue = new PriorityQueue(3);
|
|
14
15
|
this.db = null;
|
|
15
16
|
this.clientCache = null;
|
|
@@ -18,11 +19,12 @@ export class QueryManager {
|
|
|
18
19
|
this._consolidate = null;
|
|
19
20
|
/**
|
|
20
21
|
* Requests pending with the query manager.
|
|
21
|
-
*
|
|
22
22
|
* @type {QueryResult[]}
|
|
23
23
|
*/
|
|
24
24
|
this.pendingResults = [];
|
|
25
|
+
/** @type {number} */
|
|
25
26
|
this.maxConcurrentRequests = maxConcurrentRequests;
|
|
27
|
+
/** @type {boolean} */
|
|
26
28
|
this.pendingExec = false;
|
|
27
29
|
}
|
|
28
30
|
|
package/src/connectors/rest.js
CHANGED
|
@@ -21,9 +21,16 @@ export function restConnector(uri = 'http://localhost:3000/') {
|
|
|
21
21
|
body: JSON.stringify(query)
|
|
22
22
|
});
|
|
23
23
|
|
|
24
|
+
|
|
25
|
+
const res = await req;
|
|
26
|
+
|
|
27
|
+
if (!res.ok) {
|
|
28
|
+
throw new Error(`Query failed with HTTP status ${res.status}: ${await res.text()}`);
|
|
29
|
+
}
|
|
30
|
+
|
|
24
31
|
return query.type === 'exec' ? req
|
|
25
|
-
: query.type === 'arrow' ? decodeIPC(await
|
|
26
|
-
:
|
|
32
|
+
: query.type === 'arrow' ? decodeIPC(await res.arrayBuffer())
|
|
33
|
+
: res.json();
|
|
27
34
|
}
|
|
28
35
|
};
|
|
29
36
|
}
|
package/src/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { MosaicClient } from './MosaicClient.js';
|
|
2
|
+
export { makeClient } from './make-client.js';
|
|
2
3
|
export { Coordinator, coordinator } from './Coordinator.js';
|
|
3
4
|
export { Selection, isSelection } from './Selection.js';
|
|
4
5
|
export { Param, isParam } from './Param.js';
|
|
@@ -24,16 +25,4 @@ export { throttle } from './util/throttle.js';
|
|
|
24
25
|
export { toDataColumns } from './util/to-data-columns.js';
|
|
25
26
|
export { queryFieldInfo } from './util/field-info.js';
|
|
26
27
|
export { jsType } from './util/js-type.js';
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @typedef {import('./util/selection-types.js').ClauseMetadata} ClauseMetadata
|
|
30
|
-
* @typedef {import('./util/selection-types.js').PointMetadata} PointMetadata
|
|
31
|
-
* @typedef {import('./util/selection-types.js').MatchMethod} MatchMethod
|
|
32
|
-
* @typedef {import('./util/selection-types.js').MatchMetadata} MatchMetadata
|
|
33
|
-
* @typedef {import('./util/selection-types.js').ScaleType} ScaleType
|
|
34
|
-
* @typedef {import('./util/selection-types.js').Extent} Extent
|
|
35
|
-
* @typedef {import('./util/selection-types.js').Scale} Scale
|
|
36
|
-
* @typedef {import('./util/selection-types.js').BinMethod} BinMethod
|
|
37
|
-
* @typedef {import('./util/selection-types.js').IntervalMetadata} IntervalMetadata
|
|
38
|
-
* @typedef {import('./util/selection-types.js').SelectionClause} SelectionClause
|
|
39
|
-
*/
|
|
28
|
+
export { isActivatable } from './util/is-activatable.js';
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { MosaicClient } from "./MosaicClient.js";
|
|
2
|
+
import {
|
|
3
|
+
coordinator as defaultCoordinator,
|
|
4
|
+
} from "./Coordinator.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} MakeClientOptions
|
|
8
|
+
* @property {import('./Coordinator.js').Coordinator} [coordinator] - Mosaic coordinator. Default to the global coordinator.
|
|
9
|
+
* @property {import('./Selection.js').Selection|null} [selection] - A selection whose predicates will be fed into the query function to produce the SQL query.
|
|
10
|
+
* @property {function(): Promise<void>} [prepare] - An async function to prepare the client before running queries.
|
|
11
|
+
* @property {function(any): any} query - A function that returns a query from a list of selection predicates.
|
|
12
|
+
* @property {function(any): void} [queryResult] - Called by the coordinator to return a query result.
|
|
13
|
+
* @property {function(): void} [queryPending] - Called by the coordinator to report a query execution error.
|
|
14
|
+
* @property {function(any): void} [queryError] - Called by the coordinator to inform the client that a query is pending.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Make a new client with the given options, and connect the client to the provided coordinator.
|
|
18
|
+
* @param {MakeClientOptions} options - The options for making the client
|
|
19
|
+
* @returns {MosaicClient & { destroy: () => void }} - The result object with methods to request an update or destroy the client.
|
|
20
|
+
*/
|
|
21
|
+
export function makeClient(options) {
|
|
22
|
+
const coordinator = options.coordinator ?? defaultCoordinator();
|
|
23
|
+
const client = new ProxyClient({ ...options, coordinator });
|
|
24
|
+
coordinator.connect(client);
|
|
25
|
+
return client;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** An internal class used to implement the makeClient API */
|
|
29
|
+
class ProxyClient extends MosaicClient {
|
|
30
|
+
/** @param {MakeClientOptions} options */
|
|
31
|
+
constructor(options) {
|
|
32
|
+
super(options.selection);
|
|
33
|
+
|
|
34
|
+
/** @type {MakeClientOptions} */
|
|
35
|
+
this._options = { ...options };
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async prepare() {
|
|
39
|
+
await this._options.prepare?.();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
query(filter) {
|
|
43
|
+
return this._options.query(filter);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
queryResult(data) {
|
|
47
|
+
this._options.queryResult?.(data);
|
|
48
|
+
return this;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
queryPending() {
|
|
52
|
+
this._options.queryPending?.();
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
queryError(error) {
|
|
57
|
+
this._options.queryError?.(error);
|
|
58
|
+
return this;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
destroy() {
|
|
62
|
+
this._options.coordinator.disconnect(this);
|
|
63
|
+
}
|
|
64
|
+
}
|