@uwdata/mosaic-core 0.10.0 → 0.12.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/README.md +1 -1
- package/dist/mosaic-core.js +12960 -21458
- package/dist/mosaic-core.min.js +7 -16
- package/dist/types/Coordinator.d.ts +169 -0
- package/dist/types/MosaicClient.d.ts +94 -0
- package/dist/types/Param.d.ts +47 -0
- package/dist/types/QueryConsolidator.d.ts +9 -0
- package/dist/types/QueryManager.d.ts +64 -0
- package/dist/types/Selection.d.ts +224 -0
- package/dist/types/SelectionClause.d.ts +105 -0
- package/dist/types/connectors/rest.d.ts +17 -0
- package/dist/types/connectors/socket.d.ts +18 -0
- package/dist/types/connectors/wasm.d.ts +16 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/preagg/PreAggregator.d.ts +178 -0
- package/dist/types/preagg/preagg-columns.d.ts +14 -0
- package/dist/types/preagg/sufficient-statistics.d.ts +13 -0
- package/dist/types/util/AsyncDispatch.d.ts +100 -0
- package/dist/types/util/cache.d.ts +13 -0
- package/dist/types/util/decode-ipc.d.ts +7 -0
- package/dist/types/util/distinct.d.ts +2 -0
- package/dist/types/util/field-info.d.ts +13 -0
- package/dist/types/util/hash.d.ts +1 -0
- package/dist/types/util/is-arrow-table.d.ts +8 -0
- package/dist/types/util/js-type.d.ts +1 -0
- package/dist/types/util/priority-queue.d.ts +37 -0
- package/dist/types/util/query-result.d.ts +44 -0
- package/dist/types/util/selection-types.d.ts +114 -0
- package/dist/types/util/synchronizer.d.ts +29 -0
- package/dist/types/util/throttle.d.ts +11 -0
- package/dist/types/util/to-data-columns.d.ts +29 -0
- package/dist/types/util/void-logger.d.ts +7 -0
- package/jsconfig.json +11 -0
- package/package.json +10 -8
- package/src/Coordinator.js +66 -41
- package/src/MosaicClient.js +14 -4
- package/src/QueryConsolidator.js +32 -39
- package/src/QueryManager.js +85 -48
- package/src/Selection.js +49 -15
- package/src/SelectionClause.js +19 -22
- package/src/connectors/rest.js +6 -4
- package/src/connectors/socket.js +7 -4
- package/src/connectors/wasm.js +20 -4
- package/src/index.js +16 -8
- package/src/preagg/PreAggregator.js +407 -0
- package/src/preagg/preagg-columns.js +103 -0
- package/src/preagg/sufficient-statistics.js +439 -0
- package/src/util/decode-ipc.js +11 -0
- package/src/util/field-info.js +19 -16
- package/src/util/hash.js +1 -1
- package/src/util/is-arrow-table.js +10 -0
- package/src/util/priority-queue.js +75 -76
- package/src/util/query-result.js +44 -2
- package/src/util/selection-types.ts +3 -3
- package/src/util/throttle.js +21 -9
- package/src/util/to-data-columns.js +4 -15
- package/src/util/void-logger.js +6 -5
- package/tsconfig.json +11 -0
- package/src/DataCubeIndexer.js +0 -320
- package/src/util/convert-arrow.js +0 -145
- package/src/util/index-columns.js +0 -540
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { ExprNode } from '@uwdata/mosaic-sql';
|
|
2
|
+
import { MosaicClient } from '../MosaicClient.js';
|
|
3
|
+
/**
|
|
4
|
+
* Selection clause metadata to guide possible query optimizations.
|
|
5
|
+
* Sub-interfaces provide more information about the specifics of a
|
|
6
|
+
* given selection based on the selection type.
|
|
7
|
+
*/
|
|
8
|
+
export interface ClauseMetadata {
|
|
9
|
+
/**
|
|
10
|
+
* The selection type, such as `'point'`, `'interval'`, or `'match'`.
|
|
11
|
+
*/
|
|
12
|
+
type: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Selection clause metadata indicating selection of one or more discrete
|
|
16
|
+
* point values, typically based on equality or is distinctiveness checks.
|
|
17
|
+
*/
|
|
18
|
+
export interface PointMetadata extends ClauseMetadata {
|
|
19
|
+
type: 'point';
|
|
20
|
+
}
|
|
21
|
+
/** Text search matching methods. */
|
|
22
|
+
export type MatchMethod = 'contains' | 'prefix' | 'suffix' | 'regexp' | (string & {});
|
|
23
|
+
/**
|
|
24
|
+
* Selection clause metadata indicating text search matching.
|
|
25
|
+
*/
|
|
26
|
+
export interface MatchMetadata extends ClauseMetadata {
|
|
27
|
+
type: MatchMethod;
|
|
28
|
+
/** The text search matching method used. */
|
|
29
|
+
method?: 'contains' | 'prefix' | 'suffix' | 'regexp' | (string & {});
|
|
30
|
+
}
|
|
31
|
+
/** Quantitative scale types. */
|
|
32
|
+
export type ScaleType = 'identity' | 'linear' | 'log' | 'sqrt' | 'pow' | 'symlog' | 'time' | 'utc';
|
|
33
|
+
/** A data value interval extent. */
|
|
34
|
+
export type Extent = [number, number] | [Date, Date];
|
|
35
|
+
/**
|
|
36
|
+
* Descriptor for a scale that maps a data domain to screen pixels.
|
|
37
|
+
*/
|
|
38
|
+
export interface Scale {
|
|
39
|
+
/** The scale type, such as `'linear'`, `'log'`, etc. */
|
|
40
|
+
type: ScaleType;
|
|
41
|
+
/** The scale domain, as an array of start and end data values. */
|
|
42
|
+
domain: Extent;
|
|
43
|
+
/**
|
|
44
|
+
* The scale range, as an array of start and end screen pixels.
|
|
45
|
+
* The range may be omitted for *identity* scales.
|
|
46
|
+
*/
|
|
47
|
+
range?: [number, number];
|
|
48
|
+
/** The base of the logarithm. For `'log'` scales only. */
|
|
49
|
+
base?: number;
|
|
50
|
+
/** The constant parameter. For `'symlog'` scales only. */
|
|
51
|
+
constant?: number;
|
|
52
|
+
/** The exponent parameter. For `'pow'` scales only. */
|
|
53
|
+
exponent?: number;
|
|
54
|
+
}
|
|
55
|
+
/** A binning method name. */
|
|
56
|
+
export type BinMethod = 'floor' | 'ceil' | 'round';
|
|
57
|
+
/**
|
|
58
|
+
* Selection clause metadata for one or more selected intervals. This
|
|
59
|
+
* metadata can be used to determine appropriate data-space binning
|
|
60
|
+
* schemes that correspond to pixel-level bins in screen space.
|
|
61
|
+
*/
|
|
62
|
+
export interface IntervalMetadata extends ClauseMetadata {
|
|
63
|
+
type: 'interval';
|
|
64
|
+
/**
|
|
65
|
+
* The interactive pixel size used by the generating component.
|
|
66
|
+
* Values larger than one indicate intervals that "snap-to" values
|
|
67
|
+
* greater than a single pixel. If unspecified, assumed to be `1`.
|
|
68
|
+
*/
|
|
69
|
+
pixelSize?: number;
|
|
70
|
+
/**
|
|
71
|
+
* An array of one or more scale descriptors that describe the
|
|
72
|
+
* mapping from data values to screen pixels.
|
|
73
|
+
*/
|
|
74
|
+
scales?: Scale[];
|
|
75
|
+
/**
|
|
76
|
+
* A hint for the binning method to use when discretizing the
|
|
77
|
+
* interval domain. If unspecified, the default is `'floor'`.
|
|
78
|
+
*/
|
|
79
|
+
bin?: BinMethod;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* A selection clause representing filtering criteria
|
|
83
|
+
* to apply within a Mosiac Selection.
|
|
84
|
+
*/
|
|
85
|
+
export interface SelectionClause {
|
|
86
|
+
/**
|
|
87
|
+
* A unique identifier (according to object equality) for the source
|
|
88
|
+
* component that generated this clause. In many cases, this is a
|
|
89
|
+
* reference to the originating component itself.
|
|
90
|
+
*/
|
|
91
|
+
source: any;
|
|
92
|
+
/**
|
|
93
|
+
* A set of Mosaic clients associated with this clause that should not
|
|
94
|
+
* be updated when this clause is applied in a cross-filtering context.
|
|
95
|
+
*/
|
|
96
|
+
clients?: Set<MosaicClient>;
|
|
97
|
+
/**
|
|
98
|
+
* A selected value associated with this clause. For example, for a 1D
|
|
99
|
+
* interval selection clause the value may be a [lo, hi] array.
|
|
100
|
+
*/
|
|
101
|
+
value: any;
|
|
102
|
+
/**
|
|
103
|
+
* A predicate SQL expression suitable for use in a query WHERE clause.
|
|
104
|
+
* The predicate should apply filtering criteria consistent with this
|
|
105
|
+
* clause's *value* property.
|
|
106
|
+
*/
|
|
107
|
+
predicate: ExprNode | null;
|
|
108
|
+
/**
|
|
109
|
+
* Optional clause metadata that varies based on the selection type.
|
|
110
|
+
* The metadata can be used to optimize selection queries, for example
|
|
111
|
+
* by creating materialized views of pre-aggregated data when applicable.
|
|
112
|
+
*/
|
|
113
|
+
meta?: ClauseMetadata;
|
|
114
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a new synchronizer instance to aid synchronization
|
|
3
|
+
* of updates on multiple pending operations.
|
|
4
|
+
*/
|
|
5
|
+
export function synchronizer(): {
|
|
6
|
+
/**
|
|
7
|
+
* Mark an item as pending.
|
|
8
|
+
* @param {*} item An item to synchronize on.
|
|
9
|
+
*/
|
|
10
|
+
pending(item: any): void;
|
|
11
|
+
/**
|
|
12
|
+
* Mark a pending item as ready, indicating it is
|
|
13
|
+
* ready for a synchronized update.
|
|
14
|
+
* @param {*} item An item to synchronize on.
|
|
15
|
+
* @returns {boolean} True if the synchronizer is ready to
|
|
16
|
+
* resolve, false otherwise.
|
|
17
|
+
*/
|
|
18
|
+
ready(item: any): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the current synchronization cycle, causing the synchronize
|
|
21
|
+
* promise to resolve and thereby trigger downstream updates.
|
|
22
|
+
*/
|
|
23
|
+
resolve(): void;
|
|
24
|
+
/**
|
|
25
|
+
* The promise for the current synchronization cycle.
|
|
26
|
+
* @return {Promise} The synchronization promise.
|
|
27
|
+
*/
|
|
28
|
+
readonly promise: Promise<any>;
|
|
29
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Throttle invocations of a callback function. The callback must return
|
|
3
|
+
* a Promise. Upon repeated invocation, the callback will not be invoked
|
|
4
|
+
* until a prior Promise resolves. If multiple invocations occurs while
|
|
5
|
+
* waiting, only the most recent invocation will be pending.
|
|
6
|
+
* @param {(event: *) => Promise} callback The callback function.
|
|
7
|
+
* @param {boolean} [debounce=true] Flag indicating if invocations
|
|
8
|
+
* should also be debounced within the current animation frame.
|
|
9
|
+
* @returns A new function that throttles access to the callback.
|
|
10
|
+
*/
|
|
11
|
+
export function throttle(callback: (event: any) => Promise<any>, debounce?: boolean): (event: any) => void;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @typedef {Array | Int8Array | Uint8Array | Uint8ClampedArray
|
|
3
|
+
* | Int16Array | Uint16Array | Int32Array | Uint32Array
|
|
4
|
+
* | Float32Array | Float64Array
|
|
5
|
+
* } Arrayish - an Array or TypedArray
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* @typedef {
|
|
9
|
+
* | { numRows: number, columns: Record<string,Arrayish> }
|
|
10
|
+
* | { numRows: number, values: Arrayish; }
|
|
11
|
+
* } DataColumns
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Convert input data to a set of column arrays.
|
|
15
|
+
* @param {any} data The input data.
|
|
16
|
+
* @returns {DataColumns} An object with named column arrays.
|
|
17
|
+
*/
|
|
18
|
+
export function toDataColumns(data: any): DataColumns;
|
|
19
|
+
/**
|
|
20
|
+
* - an Array or TypedArray
|
|
21
|
+
*/
|
|
22
|
+
export type Arrayish = any[] | Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array;
|
|
23
|
+
export type DataColumns = any | {
|
|
24
|
+
numRows: number;
|
|
25
|
+
columns: Record<string, Arrayish>;
|
|
26
|
+
} | {
|
|
27
|
+
numRows: number;
|
|
28
|
+
values: Arrayish;
|
|
29
|
+
};
|
package/jsconfig.json
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uwdata/mosaic-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Scalable and extensible linked data views.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mosaic",
|
|
@@ -16,24 +16,26 @@
|
|
|
16
16
|
"module": "src/index.js",
|
|
17
17
|
"jsdelivr": "dist/mosaic-core.min.js",
|
|
18
18
|
"unpkg": "dist/mosaic-core.min.js",
|
|
19
|
+
"types": "dist/types/index.d.ts",
|
|
19
20
|
"repository": {
|
|
20
21
|
"type": "git",
|
|
21
22
|
"url": "https://github.com/uwdata/mosaic.git"
|
|
22
23
|
},
|
|
23
24
|
"scripts": {
|
|
24
25
|
"prebuild": "rimraf dist && mkdir dist",
|
|
25
|
-
"build": "node ../../esbuild.js mosaic-core",
|
|
26
|
+
"build": "npm run types && node ../../esbuild.js mosaic-core",
|
|
27
|
+
"types": "tsc",
|
|
26
28
|
"lint": "eslint src test",
|
|
27
|
-
"test": "
|
|
29
|
+
"test": "vitest run && tsc -p jsconfig.json",
|
|
28
30
|
"prepublishOnly": "npm run test && npm run lint && npm run build"
|
|
29
31
|
},
|
|
30
32
|
"dependencies": {
|
|
31
|
-
"@duckdb/duckdb-wasm": "^1.
|
|
32
|
-
"@uwdata/
|
|
33
|
-
"
|
|
33
|
+
"@duckdb/duckdb-wasm": "^1.29.0",
|
|
34
|
+
"@uwdata/flechette": "^1.1.1",
|
|
35
|
+
"@uwdata/mosaic-sql": "^0.12.0"
|
|
34
36
|
},
|
|
35
37
|
"devDependencies": {
|
|
36
|
-
"@uwdata/mosaic-duckdb": "^0.
|
|
38
|
+
"@uwdata/mosaic-duckdb": "^0.12.0"
|
|
37
39
|
},
|
|
38
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "523b1afe2a0880291c92f81e4a7b91829362d285"
|
|
39
41
|
}
|
package/src/Coordinator.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { socketConnector } from './connectors/socket.js';
|
|
2
|
-
import {
|
|
3
|
-
import { QueryManager, Priority } from './QueryManager.js';
|
|
2
|
+
import { PreAggregator } from './preagg/PreAggregator.js';
|
|
4
3
|
import { queryFieldInfo } from './util/field-info.js';
|
|
4
|
+
import { QueryResult } from './util/query-result.js';
|
|
5
5
|
import { voidLogger } from './util/void-logger.js';
|
|
6
|
+
import { MosaicClient } from './MosaicClient.js';
|
|
7
|
+
import { QueryManager, Priority } from './QueryManager.js';
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* The singleton Coordinator instance.
|
|
@@ -24,17 +26,22 @@ export function coordinator(instance) {
|
|
|
24
26
|
return _instance;
|
|
25
27
|
}
|
|
26
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @typedef {import('@uwdata/mosaic-sql').Query | string} QueryType
|
|
31
|
+
*/
|
|
32
|
+
|
|
27
33
|
/**
|
|
28
34
|
* A Mosaic Coordinator manages all database communication for clients and
|
|
29
35
|
* handles selection updates. The Coordinator also performs optimizations
|
|
30
|
-
* including query caching, consolidation, and
|
|
36
|
+
* including query caching, consolidation, and pre-aggregation.
|
|
31
37
|
* @param {*} [db] Database connector. Defaults to a web socket connection.
|
|
32
38
|
* @param {object} [options] Coordinator options.
|
|
33
39
|
* @param {*} [options.logger=console] The logger to use, defaults to `console`.
|
|
34
40
|
* @param {*} [options.manager] The query manager to use.
|
|
35
41
|
* @param {boolean} [options.cache=true] Boolean flag to enable/disable query caching.
|
|
36
42
|
* @param {boolean} [options.consolidate=true] Boolean flag to enable/disable query consolidation.
|
|
37
|
-
* @param {
|
|
43
|
+
* @param {import('./preagg/PreAggregator.js').PreAggregateOptions} [options.preagg]
|
|
44
|
+
* Options for the Pre-aggregator.
|
|
38
45
|
*/
|
|
39
46
|
export class Coordinator {
|
|
40
47
|
constructor(db = socketConnector(), {
|
|
@@ -42,15 +49,16 @@ export class Coordinator {
|
|
|
42
49
|
manager = new QueryManager(),
|
|
43
50
|
cache = true,
|
|
44
51
|
consolidate = true,
|
|
45
|
-
|
|
52
|
+
preagg = {}
|
|
46
53
|
} = {}) {
|
|
54
|
+
/** @type {QueryManager} */
|
|
47
55
|
this.manager = manager;
|
|
48
56
|
this.manager.cache(cache);
|
|
49
57
|
this.manager.consolidate(consolidate);
|
|
50
|
-
this.dataCubeIndexer = new DataCubeIndexer(this, indexes);
|
|
51
|
-
this.logger(logger);
|
|
52
58
|
this.databaseConnector(db);
|
|
59
|
+
this.logger(logger);
|
|
53
60
|
this.clear();
|
|
61
|
+
this.preaggregator = new PreAggregator(this, preagg);
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
/**
|
|
@@ -97,7 +105,7 @@ export class Coordinator {
|
|
|
97
105
|
/**
|
|
98
106
|
* Cancel previosuly submitted query requests. These queries will be
|
|
99
107
|
* canceled if they are queued but have not yet been submitted.
|
|
100
|
-
* @param {
|
|
108
|
+
* @param {QueryResult[]} requests An array
|
|
101
109
|
* of query result objects, such as those returned by the `query` method.
|
|
102
110
|
*/
|
|
103
111
|
cancel(requests) {
|
|
@@ -106,29 +114,30 @@ export class Coordinator {
|
|
|
106
114
|
|
|
107
115
|
/**
|
|
108
116
|
* Issue a query for which no result (return value) is needed.
|
|
109
|
-
* @param {
|
|
117
|
+
* @param {QueryType | QueryType[]} query The query or an array of queries.
|
|
118
|
+
* Each query should be either a Query builder object or a SQL string.
|
|
110
119
|
* @param {object} [options] An options object.
|
|
111
120
|
* @param {number} [options.priority] The query priority, defaults to
|
|
112
121
|
* `Priority.Normal`.
|
|
113
|
-
* @returns {
|
|
122
|
+
* @returns {QueryResult} A query result
|
|
114
123
|
* promise.
|
|
115
124
|
*/
|
|
116
125
|
exec(query, { priority = Priority.Normal } = {}) {
|
|
117
|
-
query = Array.isArray(query) ? query.join(';\n') : query;
|
|
126
|
+
query = Array.isArray(query) ? query.filter(x => x).join(';\n') : query;
|
|
118
127
|
return this.manager.request({ type: 'exec', query }, priority);
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
/**
|
|
122
131
|
* Issue a query to the backing database. The submitted query may be
|
|
123
132
|
* consolidate with other queries and its results may be cached.
|
|
124
|
-
* @param {
|
|
133
|
+
* @param {QueryType} query The query as either a Query builder object
|
|
134
|
+
* or a SQL string.
|
|
125
135
|
* @param {object} [options] An options object.
|
|
126
136
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
127
137
|
* @param {boolean} [options.cache=true] If true, cache the query result.
|
|
128
138
|
* @param {number} [options.priority] The query priority, defaults to
|
|
129
139
|
* `Priority.Normal`.
|
|
130
|
-
* @returns {
|
|
131
|
-
* promise.
|
|
140
|
+
* @returns {QueryResult} A query result promise.
|
|
132
141
|
*/
|
|
133
142
|
query(query, {
|
|
134
143
|
type = 'arrow',
|
|
@@ -142,21 +151,35 @@ export class Coordinator {
|
|
|
142
151
|
/**
|
|
143
152
|
* Issue a query to prefetch data for later use. The query result is cached
|
|
144
153
|
* for efficient future access.
|
|
145
|
-
* @param {
|
|
154
|
+
* @param {QueryType} query The query as either a Query builder object
|
|
155
|
+
* or a SQL string.
|
|
146
156
|
* @param {object} [options] An options object.
|
|
147
157
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
148
|
-
* @returns {
|
|
149
|
-
* promise.
|
|
158
|
+
* @returns {QueryResult} A query result promise.
|
|
150
159
|
*/
|
|
151
160
|
prefetch(query, options = {}) {
|
|
152
161
|
return this.query(query, { ...options, cache: true, priority: Priority.Low });
|
|
153
162
|
}
|
|
154
163
|
|
|
164
|
+
/**
|
|
165
|
+
* Create a bundle of queries that can be loaded into the cache.
|
|
166
|
+
*
|
|
167
|
+
* @param {string} name The name of the bundle.
|
|
168
|
+
* @param {[string | {sql: string}, {alias: string}]} queries The queries to save into the bundle.
|
|
169
|
+
* @param {number} priority Request priority.
|
|
170
|
+
* @returns {QueryResult} A query result promise.
|
|
171
|
+
*/
|
|
155
172
|
createBundle(name, queries, priority = Priority.Low) {
|
|
156
|
-
const options = { name, queries };
|
|
173
|
+
const options = { name, queries: queries.map(q => typeof q == 'string' ? {sql: q} : q) };
|
|
157
174
|
return this.manager.request({ type: 'create-bundle', options }, priority);
|
|
158
175
|
}
|
|
159
176
|
|
|
177
|
+
/**
|
|
178
|
+
* Load a bundle into the cache.
|
|
179
|
+
* @param {string} name The name of the bundle.
|
|
180
|
+
* @param {number} priority Request priority.
|
|
181
|
+
* @returns {QueryResult} A query result promise.
|
|
182
|
+
*/
|
|
160
183
|
loadBundle(name, priority = Priority.High) {
|
|
161
184
|
const options = { name };
|
|
162
185
|
return this.manager.request({ type: 'load-bundle', options }, priority);
|
|
@@ -167,8 +190,8 @@ export class Coordinator {
|
|
|
167
190
|
/**
|
|
168
191
|
* Update client data by submitting the given query and returning the
|
|
169
192
|
* data (or error) to the client.
|
|
170
|
-
* @param {
|
|
171
|
-
* @param {
|
|
193
|
+
* @param {MosaicClient} client A Mosaic client.
|
|
194
|
+
* @param {QueryType} query The data query.
|
|
172
195
|
* @param {number} [priority] The query priority.
|
|
173
196
|
* @returns {Promise} A Promise that resolves upon completion of the update.
|
|
174
197
|
*/
|
|
@@ -185,23 +208,20 @@ export class Coordinator {
|
|
|
185
208
|
/**
|
|
186
209
|
* Issue a query request for a client. If the query is null or undefined,
|
|
187
210
|
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
188
|
-
* side effect, this method clears the current
|
|
189
|
-
* @param {
|
|
190
|
-
*
|
|
191
|
-
* @param {import('@uwdata/mosaic-sql').Query | string | null} [query]
|
|
192
|
-
* The query to issue.
|
|
211
|
+
* side effect, this method clears the current preaggregator state.
|
|
212
|
+
* @param {MosaicClient} client The client to update.
|
|
213
|
+
* @param {QueryType | null} [query] The query to issue.
|
|
193
214
|
*/
|
|
194
215
|
requestQuery(client, query) {
|
|
195
|
-
this.
|
|
216
|
+
this.preaggregator.clear();
|
|
196
217
|
return query
|
|
197
218
|
? this.updateClient(client, query)
|
|
198
|
-
: client.update();
|
|
219
|
+
: Promise.resolve(client.update());
|
|
199
220
|
}
|
|
200
221
|
|
|
201
222
|
/**
|
|
202
223
|
* Connect a client to the coordinator.
|
|
203
|
-
* @param {
|
|
204
|
-
* client to connect.
|
|
224
|
+
* @param {MosaicClient} client The Mosaic client to connect.
|
|
205
225
|
*/
|
|
206
226
|
async connect(client) {
|
|
207
227
|
const { clients } = this;
|
|
@@ -212,22 +232,27 @@ export class Coordinator {
|
|
|
212
232
|
clients.add(client); // mark as connected
|
|
213
233
|
client.coordinator = this;
|
|
214
234
|
|
|
235
|
+
// initialize client lifecycle
|
|
236
|
+
this.initializeClient(client);
|
|
237
|
+
|
|
238
|
+
// connect filter selection
|
|
239
|
+
connectSelection(this, client.filterBy, client);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async initializeClient(client) {
|
|
215
243
|
// retrieve field statistics
|
|
216
244
|
const fields = client.fields();
|
|
217
245
|
if (fields?.length) {
|
|
218
246
|
client.fieldInfo(await queryFieldInfo(this, fields));
|
|
219
247
|
}
|
|
220
248
|
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
client.requestQuery();
|
|
249
|
+
// request data query
|
|
250
|
+
return client.requestQuery();
|
|
225
251
|
}
|
|
226
252
|
|
|
227
253
|
/**
|
|
228
254
|
* Disconnect a client from the coordinator.
|
|
229
|
-
* @param {
|
|
230
|
-
* client to disconnect.
|
|
255
|
+
* @param {MosaicClient} client The Mosaic client to disconnect.
|
|
231
256
|
*/
|
|
232
257
|
disconnect(client) {
|
|
233
258
|
const { clients, filterGroups } = this;
|
|
@@ -246,8 +271,8 @@ export class Coordinator {
|
|
|
246
271
|
* Connect a selection-client pair to the coordinator to process updates.
|
|
247
272
|
* @param {Coordinator} mc The Mosaic coordinator.
|
|
248
273
|
* @param {import('./Selection.js').Selection} selection A selection.
|
|
249
|
-
* @param {
|
|
250
|
-
*
|
|
274
|
+
* @param {MosaicClient} client A Mosiac client that is filtered by the
|
|
275
|
+
* given selection.
|
|
251
276
|
*/
|
|
252
277
|
function connectSelection(mc, selection, client) {
|
|
253
278
|
if (!selection) return;
|
|
@@ -282,10 +307,10 @@ function connectSelection(mc, selection, client) {
|
|
|
282
307
|
* selection clause representative of the activation.
|
|
283
308
|
*/
|
|
284
309
|
function activateSelection(mc, selection, clause) {
|
|
285
|
-
const {
|
|
310
|
+
const { preaggregator, filterGroups } = mc;
|
|
286
311
|
const { clients } = filterGroups.get(selection);
|
|
287
312
|
for (const client of clients) {
|
|
288
|
-
|
|
313
|
+
preaggregator.request(client, selection, clause);
|
|
289
314
|
}
|
|
290
315
|
}
|
|
291
316
|
|
|
@@ -297,11 +322,11 @@ function activateSelection(mc, selection, clause) {
|
|
|
297
322
|
* @returns {Promise} A Promise that resolves when the update completes.
|
|
298
323
|
*/
|
|
299
324
|
function updateSelection(mc, selection) {
|
|
300
|
-
const {
|
|
325
|
+
const { preaggregator, filterGroups } = mc;
|
|
301
326
|
const { clients } = filterGroups.get(selection);
|
|
302
327
|
const { active } = selection;
|
|
303
328
|
return Promise.allSettled(Array.from(clients, client => {
|
|
304
|
-
const info =
|
|
329
|
+
const info = preaggregator.request(client, selection, active);
|
|
305
330
|
const filter = info ? null : selection.predicate(client);
|
|
306
331
|
|
|
307
332
|
// skip due to cross-filtering
|
package/src/MosaicClient.js
CHANGED
|
@@ -38,11 +38,12 @@ export class MosaicClient {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* Return a boolean indicating if the client query can be
|
|
42
|
-
*
|
|
43
|
-
* groupby domain of the client
|
|
41
|
+
* Return a boolean indicating if the client query can be sped up with
|
|
42
|
+
* materialized views of pre-aggregated data. Should return true if changes to
|
|
43
|
+
* the filterBy selection does not change the groupby domain of the client
|
|
44
|
+
* query.
|
|
44
45
|
*/
|
|
45
|
-
get
|
|
46
|
+
get filterStable() {
|
|
46
47
|
return true;
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -103,6 +104,7 @@ export class MosaicClient {
|
|
|
103
104
|
* Request the coordinator to execute a query for this client.
|
|
104
105
|
* If an explicit query is not provided, the client query method will
|
|
105
106
|
* be called, filtered by the current filterBy selection.
|
|
107
|
+
* @returns {Promise}
|
|
106
108
|
*/
|
|
107
109
|
requestQuery(query) {
|
|
108
110
|
const q = query || this.query(this.filterBy?.predicate(this));
|
|
@@ -119,6 +121,14 @@ export class MosaicClient {
|
|
|
119
121
|
this._requestUpdate();
|
|
120
122
|
}
|
|
121
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Reset this client, initiating new field info and query requests.
|
|
126
|
+
* @returns {Promise}
|
|
127
|
+
*/
|
|
128
|
+
initialize() {
|
|
129
|
+
return this._coordinator.initializeClient(this);
|
|
130
|
+
}
|
|
131
|
+
|
|
122
132
|
/**
|
|
123
133
|
* Requests a client update.
|
|
124
134
|
* For example to (re-)render an interface component.
|