@uwdata/mosaic-core 0.14.1 → 0.15.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 +16 -18
- package/dist/types/MosaicClient.d.ts +58 -35
- package/dist/types/make-client.d.ts +51 -21
- package/dist/types/preagg/PreAggregator.d.ts +17 -15
- package/package.json +4 -4
- package/src/Coordinator.js +23 -34
- package/src/MosaicClient.js +94 -42
- package/src/make-client.js +69 -28
- package/src/preagg/PreAggregator.js +18 -17
|
@@ -14,8 +14,7 @@ export function coordinator(instance?: Coordinator): Coordinator;
|
|
|
14
14
|
* @param {*} [options.manager] The query manager to use.
|
|
15
15
|
* @param {boolean} [options.cache=true] Boolean flag to enable/disable query caching.
|
|
16
16
|
* @param {boolean} [options.consolidate=true] Boolean flag to enable/disable query consolidation.
|
|
17
|
-
* @param {
|
|
18
|
-
* Options for the Pre-aggregator.
|
|
17
|
+
* @param {PreAggregateOptions} [options.preagg] Options for the Pre-aggregator.
|
|
19
18
|
*/
|
|
20
19
|
export class Coordinator {
|
|
21
20
|
constructor(db?: {
|
|
@@ -70,22 +69,21 @@ export class Coordinator {
|
|
|
70
69
|
cancel(requests: QueryResult[]): void;
|
|
71
70
|
/**
|
|
72
71
|
* Issue a query for which no result (return value) is needed.
|
|
73
|
-
* @param {
|
|
74
|
-
* import('./types.js').QueryType} query The query or an array of queries.
|
|
72
|
+
* @param {QueryType[] | QueryType} query The query or an array of queries.
|
|
75
73
|
* Each query should be either a Query builder object or a SQL string.
|
|
76
74
|
* @param {object} [options] An options object.
|
|
77
75
|
* @param {number} [options.priority] The query priority, defaults to
|
|
78
76
|
* `Priority.Normal`.
|
|
79
77
|
* @returns {QueryResult} A query result promise.
|
|
80
78
|
*/
|
|
81
|
-
exec(query:
|
|
79
|
+
exec(query: QueryType[] | QueryType, { priority }?: {
|
|
82
80
|
priority?: number;
|
|
83
81
|
}): QueryResult;
|
|
84
82
|
/**
|
|
85
83
|
* Issue a query to the backing database. The submitted query may be
|
|
86
84
|
* consolidate with other queries and its results may be cached.
|
|
87
|
-
* @param {
|
|
88
|
-
*
|
|
85
|
+
* @param {QueryType} query The query as either a Query builder objec
|
|
86
|
+
* or a SQL string.
|
|
89
87
|
* @param {object} [options] An options object.
|
|
90
88
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
91
89
|
* @param {boolean} [options.cache=true] If true, cache the query result
|
|
@@ -96,7 +94,7 @@ export class Coordinator {
|
|
|
96
94
|
* `Priority.Normal`.
|
|
97
95
|
* @returns {QueryResult} A query result promise.
|
|
98
96
|
*/
|
|
99
|
-
query(query:
|
|
97
|
+
query(query: QueryType, { type, cache, priority, ...options }?: {
|
|
100
98
|
type?: "arrow" | "json";
|
|
101
99
|
cache?: boolean;
|
|
102
100
|
persist?: boolean;
|
|
@@ -105,13 +103,13 @@ export class Coordinator {
|
|
|
105
103
|
/**
|
|
106
104
|
* Issue a query to prefetch data for later use. The query result is cached
|
|
107
105
|
* for efficient future access.
|
|
108
|
-
* @param {
|
|
109
|
-
*
|
|
106
|
+
* @param {QueryType} query The query as either a Query builder object
|
|
107
|
+
* or a SQL string.
|
|
110
108
|
* @param {object} [options] An options object.
|
|
111
109
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
112
110
|
* @returns {QueryResult} A query result promise.
|
|
113
111
|
*/
|
|
114
|
-
prefetch(query:
|
|
112
|
+
prefetch(query: QueryType, options?: {
|
|
115
113
|
type?: "arrow" | "json";
|
|
116
114
|
}): QueryResult;
|
|
117
115
|
/**
|
|
@@ -138,25 +136,24 @@ export class Coordinator {
|
|
|
138
136
|
* Update client data by submitting the given query and returning the
|
|
139
137
|
* data (or error) to the client.
|
|
140
138
|
* @param {MosaicClient} client A Mosaic client.
|
|
141
|
-
* @param {
|
|
139
|
+
* @param {QueryType} query The data query.
|
|
142
140
|
* @param {number} [priority] The query priority.
|
|
143
141
|
* @returns {Promise} A Promise that resolves upon completion of the update.
|
|
144
142
|
*/
|
|
145
|
-
updateClient(client: MosaicClient, query:
|
|
143
|
+
updateClient(client: MosaicClient, query: QueryType, priority?: number): Promise<any>;
|
|
146
144
|
/**
|
|
147
145
|
* Issue a query request for a client. If the query is null or undefined,
|
|
148
146
|
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
149
147
|
* side effect, this method clears the current preaggregator state.
|
|
150
148
|
* @param {MosaicClient} client The client to update.
|
|
151
|
-
* @param {
|
|
149
|
+
* @param {QueryType | null} [query] The query to issue.
|
|
152
150
|
*/
|
|
153
|
-
requestQuery(client: MosaicClient, query?:
|
|
151
|
+
requestQuery(client: MosaicClient, query?: QueryType | null): Promise<any>;
|
|
154
152
|
/**
|
|
155
153
|
* Connect a client to the coordinator.
|
|
156
154
|
* @param {MosaicClient} client The Mosaic client to connect.
|
|
157
155
|
*/
|
|
158
156
|
connect(client: MosaicClient): void;
|
|
159
|
-
initializeClient(client: any): Promise<any>;
|
|
160
157
|
/**
|
|
161
158
|
* Disconnect a client from the coordinator.
|
|
162
159
|
* @param {MosaicClient} client The Mosaic client to disconnect.
|
|
@@ -165,5 +162,6 @@ export class Coordinator {
|
|
|
165
162
|
}
|
|
166
163
|
import { QueryManager } from './QueryManager.js';
|
|
167
164
|
import { PreAggregator } from './preagg/PreAggregator.js';
|
|
168
|
-
import { QueryResult } from './util/query-result.js';
|
|
169
|
-
import {
|
|
165
|
+
import type { QueryResult } from './util/query-result.js';
|
|
166
|
+
import type { QueryType } from './types.js';
|
|
167
|
+
import type { MosaicClient } from './MosaicClient.js';
|
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* A Mosaic client is a data consumer that indicates its data needs to a
|
|
3
|
+
* Mosaic coordinator via the query method. The coordinator is responsible
|
|
4
|
+
* for issuing queries and returning results to the client.
|
|
5
|
+
*
|
|
6
|
+
* The client life-cycle consists of connection to a coordinator,
|
|
7
|
+
* initialization (potentially involving queries for data schema and summary
|
|
8
|
+
* statistic information), and then interactive queries that may be driven by
|
|
9
|
+
* an associated selection. When no longer needed, a client should be
|
|
10
|
+
* disconnected from the coordinator.
|
|
11
|
+
*
|
|
12
|
+
* When enabled, a client will initialize and respond to query update requests.
|
|
13
|
+
* If disabled, the client will delay initialization and not respond to queries
|
|
14
|
+
* until enabled again. Disabling a client can improve system performance when
|
|
15
|
+
* associated interface elements are offscreen or disabled.
|
|
3
16
|
*/
|
|
4
17
|
export class MosaicClient {
|
|
5
18
|
/**
|
|
6
|
-
*
|
|
7
|
-
* @param {
|
|
8
|
-
* this client's data. If provided, a coordinator
|
|
9
|
-
* the client when the selection updates.
|
|
19
|
+
* Create a new client instance.
|
|
20
|
+
* @param {Selection} [filterSelection] An optional selection to
|
|
21
|
+
* interactively filter this client's data. If provided, a coordinator
|
|
22
|
+
* will re-query and update the client when the selection updates.
|
|
10
23
|
*/
|
|
11
|
-
constructor(filterSelection
|
|
24
|
+
constructor(filterSelection?: Selection);
|
|
12
25
|
/** @type {Selection} */
|
|
13
26
|
_filterBy: Selection;
|
|
14
27
|
_requestUpdate: (event: any) => void;
|
|
@@ -16,6 +29,12 @@ export class MosaicClient {
|
|
|
16
29
|
_coordinator: Coordinator;
|
|
17
30
|
/** @type {Promise<any>} */
|
|
18
31
|
_pending: Promise<any>;
|
|
32
|
+
/** @type {boolean} */
|
|
33
|
+
_enabled: boolean;
|
|
34
|
+
/** @type {boolean} */
|
|
35
|
+
_initialized: boolean;
|
|
36
|
+
/** @type {Query | boolean} */
|
|
37
|
+
_request: Query | boolean;
|
|
19
38
|
/**
|
|
20
39
|
* Set this client's connected coordinator.
|
|
21
40
|
*/
|
|
@@ -24,6 +43,14 @@ export class MosaicClient {
|
|
|
24
43
|
* Return this client's connected coordinator.
|
|
25
44
|
*/
|
|
26
45
|
get coordinator(): Coordinator;
|
|
46
|
+
/**
|
|
47
|
+
* Set this client's enabled state;
|
|
48
|
+
*/
|
|
49
|
+
set enabled(state: boolean);
|
|
50
|
+
/**
|
|
51
|
+
* Return this client's enabled state.
|
|
52
|
+
*/
|
|
53
|
+
get enabled(): boolean;
|
|
27
54
|
/**
|
|
28
55
|
* Return a Promise that resolves once the client has updated.
|
|
29
56
|
*/
|
|
@@ -34,25 +61,15 @@ export class MosaicClient {
|
|
|
34
61
|
get filterBy(): Selection;
|
|
35
62
|
/**
|
|
36
63
|
* Return a boolean indicating if the client query can be sped up with
|
|
37
|
-
* materialized views of pre-aggregated data. Should return true if changes
|
|
38
|
-
* the filterBy selection
|
|
64
|
+
* materialized views of pre-aggregated data. Should return true if changes
|
|
65
|
+
* to the filterBy selection do not change the groupby domain of the client
|
|
39
66
|
* query.
|
|
40
67
|
*/
|
|
41
68
|
get filterStable(): boolean;
|
|
42
69
|
/**
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*/
|
|
47
|
-
fields(): import("./types.js").FieldInfoRequest[] | null;
|
|
48
|
-
/**
|
|
49
|
-
* Called by the coordinator to set the field info for this client.
|
|
50
|
-
* @param {import('./types.js').FieldInfo[]} info The field info result.
|
|
51
|
-
* @returns {this}
|
|
52
|
-
*/
|
|
53
|
-
fieldInfo(info: import("./types.js").FieldInfo[]): this;
|
|
54
|
-
/**
|
|
55
|
-
* Prepare the client before the query() method is called.
|
|
70
|
+
* Prepare the client before the `query()` method is called. Subclasses
|
|
71
|
+
* should override this method as needed, potentially issuing one or more
|
|
72
|
+
* queries to gather data or metadata needed prior to `query` calls.
|
|
56
73
|
*/
|
|
57
74
|
prepare(): Promise<void>;
|
|
58
75
|
/**
|
|
@@ -80,26 +97,31 @@ export class MosaicClient {
|
|
|
80
97
|
queryError(error: any): this;
|
|
81
98
|
/**
|
|
82
99
|
* Request the coordinator to execute a query for this client.
|
|
83
|
-
* If an explicit query is not provided, the client query method will
|
|
84
|
-
* be called, filtered by the current filterBy selection. This method
|
|
85
|
-
*
|
|
100
|
+
* If an explicit query is not provided, the client `query` method will
|
|
101
|
+
* be called, filtered by the current `filterBy` selection. This method has
|
|
102
|
+
* no effect if the client is not connected to a coordinator. If the client
|
|
103
|
+
* is connected by currently disabled, the request will be serviced if the
|
|
104
|
+
* client is later enabled.
|
|
105
|
+
* @param {Query} [query] The query to request. If unspecified, the query
|
|
106
|
+
* will be determind by the client's `query` method and the current
|
|
107
|
+
* `filterBy` selection state.
|
|
86
108
|
* @returns {Promise}
|
|
87
109
|
*/
|
|
88
|
-
requestQuery(query
|
|
110
|
+
requestQuery(query?: Query): Promise<any>;
|
|
89
111
|
/**
|
|
90
112
|
* Request that the coordinator perform a throttled update of this client
|
|
91
|
-
* using the default query. Unlike requestQuery, for which every call
|
|
92
|
-
*
|
|
93
|
-
*
|
|
113
|
+
* using the default query. Unlike requestQuery, for which every call results
|
|
114
|
+
* in an executed query, multiple calls to requestUpdate may be consolidated
|
|
115
|
+
* into a single update. This method has no effect if the client is not
|
|
116
|
+
* connected to a coordinator. If the client is connected but currently
|
|
117
|
+
* disabled, the request will be serviced if the client is later enabled.
|
|
94
118
|
*/
|
|
95
119
|
requestUpdate(): void;
|
|
96
120
|
/**
|
|
97
|
-
* Reset this client,
|
|
98
|
-
*
|
|
99
|
-
* registered with a coordinator.
|
|
100
|
-
* @returns {Promise}
|
|
121
|
+
* Reset this client, calling the prepare method and query requests. This
|
|
122
|
+
* method has no effect if the client is not registered with a coordinator.
|
|
101
123
|
*/
|
|
102
|
-
initialize():
|
|
124
|
+
initialize(): void;
|
|
103
125
|
/**
|
|
104
126
|
* Requests a client update, for example to (re-)render an interface
|
|
105
127
|
* component.
|
|
@@ -107,5 +129,6 @@ export class MosaicClient {
|
|
|
107
129
|
*/
|
|
108
130
|
update(): this | Promise<any>;
|
|
109
131
|
}
|
|
110
|
-
import { Selection } from './Selection.js';
|
|
111
|
-
import { Coordinator } from './Coordinator.js';
|
|
132
|
+
import type { Selection } from './Selection.js';
|
|
133
|
+
import type { Coordinator } from './Coordinator.js';
|
|
134
|
+
import type { Query } from '@uwdata/mosaic-sql';
|
|
@@ -1,48 +1,78 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @typedef {Object} MakeClientOptions
|
|
3
|
-
* @property {
|
|
4
|
-
*
|
|
5
|
-
* @property {
|
|
6
|
-
*
|
|
7
|
-
* @property {
|
|
8
|
-
*
|
|
9
|
-
* @property {
|
|
3
|
+
* @property {Coordinator} [coordinator] Mosaic coordinator.
|
|
4
|
+
* Defaults to the global coordinator.
|
|
5
|
+
* @property {Selection|null} [selection] A selection whose predicates are
|
|
6
|
+
* fed into the query function to produce the SQL query.
|
|
7
|
+
* @property {boolean} [enabled] A flag (default `true`) indicating if the
|
|
8
|
+
* client should initially be enabled or not.
|
|
9
|
+
* @property {boolean} [filterStable] A flag (default `true`) indicating if the
|
|
10
|
+
* if client queries can be sped up using pre-aggregated data. Should be set
|
|
11
|
+
* to `false` if filtering changes the groupby domain of the query.
|
|
12
|
+
* @property {function(): Promise<void>} [prepare]
|
|
13
|
+
* An async function to prepare the client before running queries.
|
|
14
|
+
* @property {function(any): any} [query]
|
|
15
|
+
* A function that returns a query from a list of selection predicates.
|
|
16
|
+
* @property {function(any): void} [queryResult]
|
|
17
|
+
* Called by the coordinator to return a query result.
|
|
18
|
+
* @property {function(): void} [queryPending]
|
|
19
|
+
* Called by the coordinator to report a query execution error.
|
|
20
|
+
* @property {function(any): void} [queryError]
|
|
21
|
+
* Called by the coordinator to inform the client that a query is pending.
|
|
10
22
|
*/
|
|
11
|
-
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
23
|
+
/**
|
|
24
|
+
* Make a new client with the given options, and connect the client to the
|
|
25
|
+
* provided coordinator.
|
|
26
|
+
* @param {MakeClientOptions} options The options for making the client.
|
|
27
|
+
* @returns {MosaicClient & { destroy: () => void }} The resulting client,
|
|
28
|
+
* along with a method to destroy the client when no longer needed.
|
|
14
29
|
*/
|
|
15
30
|
export function makeClient(options: MakeClientOptions): MosaicClient & {
|
|
16
31
|
destroy: () => void;
|
|
17
32
|
};
|
|
18
33
|
export type MakeClientOptions = {
|
|
19
34
|
/**
|
|
20
|
-
*
|
|
35
|
+
* Mosaic coordinator.
|
|
36
|
+
* Defaults to the global coordinator.
|
|
37
|
+
*/
|
|
38
|
+
coordinator?: Coordinator;
|
|
39
|
+
/**
|
|
40
|
+
* A selection whose predicates are
|
|
41
|
+
* fed into the query function to produce the SQL query.
|
|
42
|
+
*/
|
|
43
|
+
selection?: Selection | null;
|
|
44
|
+
/**
|
|
45
|
+
* A flag (default `true`) indicating if the
|
|
46
|
+
* client should initially be enabled or not.
|
|
21
47
|
*/
|
|
22
|
-
|
|
48
|
+
enabled?: boolean;
|
|
23
49
|
/**
|
|
24
|
-
*
|
|
50
|
+
* A flag (default `true`) indicating if the
|
|
51
|
+
* if client queries can be sped up using pre-aggregated data. Should be set
|
|
52
|
+
* to `false` if filtering changes the groupby domain of the query.
|
|
25
53
|
*/
|
|
26
|
-
|
|
54
|
+
filterStable?: boolean;
|
|
27
55
|
/**
|
|
28
|
-
*
|
|
56
|
+
* An async function to prepare the client before running queries.
|
|
29
57
|
*/
|
|
30
58
|
prepare?: () => Promise<void>;
|
|
31
59
|
/**
|
|
32
|
-
*
|
|
60
|
+
* A function that returns a query from a list of selection predicates.
|
|
33
61
|
*/
|
|
34
|
-
query
|
|
62
|
+
query?: (arg0: any) => any;
|
|
35
63
|
/**
|
|
36
|
-
*
|
|
64
|
+
* Called by the coordinator to return a query result.
|
|
37
65
|
*/
|
|
38
66
|
queryResult?: (arg0: any) => void;
|
|
39
67
|
/**
|
|
40
|
-
*
|
|
68
|
+
* Called by the coordinator to report a query execution error.
|
|
41
69
|
*/
|
|
42
70
|
queryPending?: () => void;
|
|
43
71
|
/**
|
|
44
|
-
*
|
|
72
|
+
* Called by the coordinator to inform the client that a query is pending.
|
|
45
73
|
*/
|
|
46
74
|
queryError?: (arg0: any) => void;
|
|
47
75
|
};
|
|
48
|
-
import { MosaicClient } from
|
|
76
|
+
import { MosaicClient } from './MosaicClient.js';
|
|
77
|
+
import type { Coordinator } from './Coordinator.js';
|
|
78
|
+
import type { Selection } from './Selection.js';
|
|
@@ -27,17 +27,17 @@
|
|
|
27
27
|
export class PreAggregator {
|
|
28
28
|
/**
|
|
29
29
|
* Create a new manager of materialized views of pre-aggregated data.
|
|
30
|
-
* @param {
|
|
30
|
+
* @param {Coordinator} coordinator A Mosaic coordinator.
|
|
31
31
|
* @param {PreAggregateOptions} [options] Pre-aggregation options.
|
|
32
32
|
*/
|
|
33
|
-
constructor(coordinator:
|
|
34
|
-
/** @type {Map<
|
|
35
|
-
entries: Map<
|
|
33
|
+
constructor(coordinator: Coordinator, { schema, enabled }?: PreAggregateOptions);
|
|
34
|
+
/** @type {Map<MosaicClient, PreAggregateInfo | Skip | null>} */
|
|
35
|
+
entries: Map<MosaicClient, PreAggregateInfo | {
|
|
36
36
|
skip: boolean;
|
|
37
37
|
result: any;
|
|
38
38
|
} | null>;
|
|
39
39
|
active: any;
|
|
40
|
-
mc:
|
|
40
|
+
mc: Coordinator;
|
|
41
41
|
_schema: string;
|
|
42
42
|
_enabled: boolean;
|
|
43
43
|
/**
|
|
@@ -88,16 +88,14 @@ export class PreAggregator {
|
|
|
88
88
|
* client-selection pair, or null if the client has unstable filters.
|
|
89
89
|
* This method has multiple possible side effects, including materialized
|
|
90
90
|
* view creation and updating internal caches.
|
|
91
|
-
* @param {
|
|
92
|
-
* @param {
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* A representative active selection clause for which to (possibly) generate
|
|
96
|
-
* materialized views of pre-aggregates.
|
|
91
|
+
* @param {MosaicClient} client A Mosaic client.
|
|
92
|
+
* @param {Selection} selection A Mosaic selection to filter the client by.
|
|
93
|
+
* @param {SelectionClause} activeClause A representative active selection
|
|
94
|
+
* clause for which to generate materialized views of pre-aggregates.
|
|
97
95
|
* @returns {PreAggregateInfo | Skip | null} Information and query generator
|
|
98
96
|
* for pre-aggregated tables, or null if the client has unstable filters.
|
|
99
97
|
*/
|
|
100
|
-
request(client:
|
|
98
|
+
request(client: MosaicClient, selection: Selection, activeClause: SelectionClause): PreAggregateInfo | {
|
|
101
99
|
skip: boolean;
|
|
102
100
|
result: any;
|
|
103
101
|
} | null;
|
|
@@ -157,11 +155,10 @@ export class PreAggregateInfo {
|
|
|
157
155
|
skip: boolean;
|
|
158
156
|
/**
|
|
159
157
|
* Generate a materialized view query for the given predicate.
|
|
160
|
-
* @param {
|
|
161
|
-
* active clause predicate.
|
|
158
|
+
* @param {ExprNode} predicate The current active clause predicate.
|
|
162
159
|
* @returns {SelectQuery} A materialized view query.
|
|
163
160
|
*/
|
|
164
|
-
query(predicate:
|
|
161
|
+
query(predicate: ExprNode): SelectQuery;
|
|
165
162
|
}
|
|
166
163
|
export type PreAggregateOptions = {
|
|
167
164
|
/**
|
|
@@ -175,4 +172,9 @@ export type PreAggregateOptions = {
|
|
|
175
172
|
*/
|
|
176
173
|
enabled?: boolean;
|
|
177
174
|
};
|
|
175
|
+
import type { MosaicClient } from '../MosaicClient.js';
|
|
176
|
+
import type { Coordinator } from '../Coordinator.js';
|
|
177
|
+
import type { Selection } from '../Selection.js';
|
|
178
|
+
import type { SelectionClause } from '../util/selection-types.js';
|
|
178
179
|
import { SelectQuery } from '@uwdata/mosaic-sql';
|
|
180
|
+
import type { ExprNode } from '@uwdata/mosaic-sql';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uwdata/mosaic-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
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.15.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@uwdata/mosaic-duckdb": "^0.
|
|
38
|
+
"@uwdata/mosaic-duckdb": "^0.15.0"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "671ad1ba86749a8435bd4aa7e722e2a8553f2cb0"
|
|
41
41
|
}
|
package/src/Coordinator.js
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
/** @import { PreAggregateOptions } from './preagg/PreAggregator.js' */
|
|
2
|
+
/** @import { QueryResult } from './util/query-result.js' */
|
|
3
|
+
/** @import { SelectionClause } from './util/selection-types.js' */
|
|
4
|
+
/** @import { MosaicClient } from './MosaicClient.js' */
|
|
5
|
+
/** @import { Selection } from './Selection.js' */
|
|
6
|
+
/** @import { QueryType } from './types.js' */
|
|
1
7
|
import { socketConnector } from './connectors/socket.js';
|
|
2
8
|
import { PreAggregator } from './preagg/PreAggregator.js';
|
|
3
|
-
import { queryFieldInfo } from './util/field-info.js';
|
|
4
|
-
import { QueryResult } from './util/query-result.js';
|
|
5
9
|
import { voidLogger } from './util/void-logger.js';
|
|
6
|
-
import { MosaicClient } from './MosaicClient.js';
|
|
7
10
|
import { QueryManager, Priority } from './QueryManager.js';
|
|
8
11
|
|
|
9
12
|
/**
|
|
@@ -36,8 +39,7 @@ export function coordinator(instance) {
|
|
|
36
39
|
* @param {*} [options.manager] The query manager to use.
|
|
37
40
|
* @param {boolean} [options.cache=true] Boolean flag to enable/disable query caching.
|
|
38
41
|
* @param {boolean} [options.consolidate=true] Boolean flag to enable/disable query consolidation.
|
|
39
|
-
* @param {
|
|
40
|
-
* Options for the Pre-aggregator.
|
|
42
|
+
* @param {PreAggregateOptions} [options.preagg] Options for the Pre-aggregator.
|
|
41
43
|
*/
|
|
42
44
|
export class Coordinator {
|
|
43
45
|
constructor(db = socketConnector(), {
|
|
@@ -110,8 +112,7 @@ export class Coordinator {
|
|
|
110
112
|
|
|
111
113
|
/**
|
|
112
114
|
* Issue a query for which no result (return value) is needed.
|
|
113
|
-
* @param {
|
|
114
|
-
* import('./types.js').QueryType} query The query or an array of queries.
|
|
115
|
+
* @param {QueryType[] | QueryType} query The query or an array of queries.
|
|
115
116
|
* Each query should be either a Query builder object or a SQL string.
|
|
116
117
|
* @param {object} [options] An options object.
|
|
117
118
|
* @param {number} [options.priority] The query priority, defaults to
|
|
@@ -126,8 +127,8 @@ export class Coordinator {
|
|
|
126
127
|
/**
|
|
127
128
|
* Issue a query to the backing database. The submitted query may be
|
|
128
129
|
* consolidate with other queries and its results may be cached.
|
|
129
|
-
* @param {
|
|
130
|
-
*
|
|
130
|
+
* @param {QueryType} query The query as either a Query builder objec
|
|
131
|
+
* or a SQL string.
|
|
131
132
|
* @param {object} [options] An options object.
|
|
132
133
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
133
134
|
* @param {boolean} [options.cache=true] If true, cache the query result
|
|
@@ -150,8 +151,8 @@ export class Coordinator {
|
|
|
150
151
|
/**
|
|
151
152
|
* Issue a query to prefetch data for later use. The query result is cached
|
|
152
153
|
* for efficient future access.
|
|
153
|
-
* @param {
|
|
154
|
-
*
|
|
154
|
+
* @param {QueryType} query The query as either a Query builder object
|
|
155
|
+
* or a SQL string.
|
|
155
156
|
* @param {object} [options] An options object.
|
|
156
157
|
* @param {'arrow' | 'json'} [options.type] The query result format type.
|
|
157
158
|
* @returns {QueryResult} A query result promise.
|
|
@@ -190,7 +191,7 @@ export class Coordinator {
|
|
|
190
191
|
* Update client data by submitting the given query and returning the
|
|
191
192
|
* data (or error) to the client.
|
|
192
193
|
* @param {MosaicClient} client A Mosaic client.
|
|
193
|
-
* @param {
|
|
194
|
+
* @param {QueryType} query The data query.
|
|
194
195
|
* @param {number} [priority] The query priority.
|
|
195
196
|
* @returns {Promise} A Promise that resolves upon completion of the update.
|
|
196
197
|
*/
|
|
@@ -209,7 +210,7 @@ export class Coordinator {
|
|
|
209
210
|
* the client is simply updated. Otherwise `updateClient` is called. As a
|
|
210
211
|
* side effect, this method clears the current preaggregator state.
|
|
211
212
|
* @param {MosaicClient} client The client to update.
|
|
212
|
-
* @param {
|
|
213
|
+
* @param {QueryType | null} [query] The query to issue.
|
|
213
214
|
*/
|
|
214
215
|
requestQuery(client, query) {
|
|
215
216
|
this.preaggregator.clear();
|
|
@@ -236,26 +237,12 @@ export class Coordinator {
|
|
|
236
237
|
client.coordinator = this;
|
|
237
238
|
|
|
238
239
|
// initialize client lifecycle
|
|
239
|
-
client.
|
|
240
|
+
client.initialize();
|
|
240
241
|
|
|
241
242
|
// connect filter selection
|
|
242
243
|
connectSelection(this, client.filterBy, client);
|
|
243
244
|
}
|
|
244
245
|
|
|
245
|
-
async initializeClient(client) {
|
|
246
|
-
// retrieve field statistics
|
|
247
|
-
const fields = client.fields();
|
|
248
|
-
if (fields?.length) {
|
|
249
|
-
client.fieldInfo(await queryFieldInfo(this, fields));
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// prepare the client
|
|
253
|
-
await client.prepare();
|
|
254
|
-
|
|
255
|
-
// request data query
|
|
256
|
-
return client.requestQuery();
|
|
257
|
-
}
|
|
258
|
-
|
|
259
246
|
/**
|
|
260
247
|
* Disconnect a client from the coordinator.
|
|
261
248
|
* @param {MosaicClient} client The Mosaic client to disconnect.
|
|
@@ -276,7 +263,7 @@ export class Coordinator {
|
|
|
276
263
|
/**
|
|
277
264
|
* Connect a selection-client pair to the coordinator to process updates.
|
|
278
265
|
* @param {Coordinator} mc The Mosaic coordinator.
|
|
279
|
-
* @param {
|
|
266
|
+
* @param {Selection} selection A selection.
|
|
280
267
|
* @param {MosaicClient} client A Mosiac client that is filtered by the
|
|
281
268
|
* given selection.
|
|
282
269
|
*/
|
|
@@ -308,15 +295,16 @@ function connectSelection(mc, selection, client) {
|
|
|
308
295
|
* next updates. Activation provides a preview of likely next events,
|
|
309
296
|
* enabling potential precomputation to optimize updates.
|
|
310
297
|
* @param {Coordinator} mc The Mosaic coordinator.
|
|
311
|
-
* @param {
|
|
312
|
-
* @param {
|
|
313
|
-
* selection clause representative of the activation.
|
|
298
|
+
* @param {Selection} selection A selection.
|
|
299
|
+
* @param {SelectionClause} clause A selection clause for the activation.
|
|
314
300
|
*/
|
|
315
301
|
function activateSelection(mc, selection, clause) {
|
|
316
302
|
const { preaggregator, filterGroups } = mc;
|
|
317
303
|
const { clients } = filterGroups.get(selection);
|
|
318
304
|
for (const client of clients) {
|
|
319
|
-
|
|
305
|
+
if (client.enabled) {
|
|
306
|
+
preaggregator.request(client, selection, clause);
|
|
307
|
+
}
|
|
320
308
|
}
|
|
321
309
|
}
|
|
322
310
|
|
|
@@ -324,7 +312,7 @@ function activateSelection(mc, selection, clause) {
|
|
|
324
312
|
* Process an updated selection value, querying filtered data for any
|
|
325
313
|
* associated clients.
|
|
326
314
|
* @param {Coordinator} mc The Mosaic coordinator.
|
|
327
|
-
* @param {
|
|
315
|
+
* @param {Selection} selection A selection.
|
|
328
316
|
* @returns {Promise} A Promise that resolves when the update completes.
|
|
329
317
|
*/
|
|
330
318
|
function updateSelection(mc, selection) {
|
|
@@ -332,6 +320,7 @@ function updateSelection(mc, selection) {
|
|
|
332
320
|
const { clients } = filterGroups.get(selection);
|
|
333
321
|
const { active } = selection;
|
|
334
322
|
return Promise.allSettled(Array.from(clients, client => {
|
|
323
|
+
if (!client.enabled) return client.requestQuery();
|
|
335
324
|
const info = preaggregator.request(client, selection, active);
|
|
336
325
|
const filter = info ? null : selection.predicate(client);
|
|
337
326
|
|
package/src/MosaicClient.js
CHANGED
|
@@ -1,16 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
/** @import { Query } from '@uwdata/mosaic-sql' */
|
|
2
|
+
/** @import { Coordinator } from './Coordinator.js' */
|
|
3
|
+
/** @import { Selection } from './Selection.js' */
|
|
3
4
|
import { throttle } from './util/throttle.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
+
* A Mosaic client is a data consumer that indicates its data needs to a
|
|
8
|
+
* Mosaic coordinator via the query method. The coordinator is responsible
|
|
9
|
+
* for issuing queries and returning results to the client.
|
|
10
|
+
*
|
|
11
|
+
* The client life-cycle consists of connection to a coordinator,
|
|
12
|
+
* initialization (potentially involving queries for data schema and summary
|
|
13
|
+
* statistic information), and then interactive queries that may be driven by
|
|
14
|
+
* an associated selection. When no longer needed, a client should be
|
|
15
|
+
* disconnected from the coordinator.
|
|
16
|
+
*
|
|
17
|
+
* When enabled, a client will initialize and respond to query update requests.
|
|
18
|
+
* If disabled, the client will delay initialization and not respond to queries
|
|
19
|
+
* until enabled again. Disabling a client can improve system performance when
|
|
20
|
+
* associated interface elements are offscreen or disabled.
|
|
7
21
|
*/
|
|
8
22
|
export class MosaicClient {
|
|
9
23
|
/**
|
|
10
|
-
*
|
|
11
|
-
* @param {
|
|
12
|
-
* this client's data. If provided, a coordinator
|
|
13
|
-
* the client when the selection updates.
|
|
24
|
+
* Create a new client instance.
|
|
25
|
+
* @param {Selection} [filterSelection] An optional selection to
|
|
26
|
+
* interactively filter this client's data. If provided, a coordinator
|
|
27
|
+
* will re-query and update the client when the selection updates.
|
|
14
28
|
*/
|
|
15
29
|
constructor(filterSelection) {
|
|
16
30
|
/** @type {Selection} */
|
|
@@ -20,6 +34,12 @@ export class MosaicClient {
|
|
|
20
34
|
this._coordinator = null;
|
|
21
35
|
/** @type {Promise<any>} */
|
|
22
36
|
this._pending = Promise.resolve();
|
|
37
|
+
/** @type {boolean} */
|
|
38
|
+
this._enabled = true;
|
|
39
|
+
/** @type {boolean} */
|
|
40
|
+
this._initialized = false;
|
|
41
|
+
/** @type {Query | boolean} */
|
|
42
|
+
this._request = null;
|
|
23
43
|
}
|
|
24
44
|
|
|
25
45
|
/**
|
|
@@ -36,6 +56,33 @@ export class MosaicClient {
|
|
|
36
56
|
this._coordinator = coordinator;
|
|
37
57
|
}
|
|
38
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Return this client's enabled state.
|
|
61
|
+
*/
|
|
62
|
+
get enabled() {
|
|
63
|
+
return this._enabled;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Set this client's enabled state;
|
|
68
|
+
*/
|
|
69
|
+
set enabled(state) {
|
|
70
|
+
state = !!state; // ensure boolean
|
|
71
|
+
if (this._enabled !== state) {
|
|
72
|
+
this._enabled = state;
|
|
73
|
+
if (state) {
|
|
74
|
+
if (!this._initialized) {
|
|
75
|
+
// initialization includes a query request
|
|
76
|
+
this.initialize();
|
|
77
|
+
} else if (this._request) {
|
|
78
|
+
// request query now if requested while disabled
|
|
79
|
+
this.requestQuery(this._request === true ? undefined : this._request);
|
|
80
|
+
}
|
|
81
|
+
this._request = null;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
39
86
|
/**
|
|
40
87
|
* Return a Promise that resolves once the client has updated.
|
|
41
88
|
*/
|
|
@@ -52,8 +99,8 @@ export class MosaicClient {
|
|
|
52
99
|
|
|
53
100
|
/**
|
|
54
101
|
* Return a boolean indicating if the client query can be sped up with
|
|
55
|
-
* materialized views of pre-aggregated data. Should return true if changes
|
|
56
|
-
* the filterBy selection
|
|
102
|
+
* materialized views of pre-aggregated data. Should return true if changes
|
|
103
|
+
* to the filterBy selection do not change the groupby domain of the client
|
|
57
104
|
* query.
|
|
58
105
|
*/
|
|
59
106
|
get filterStable() {
|
|
@@ -61,25 +108,9 @@ export class MosaicClient {
|
|
|
61
108
|
}
|
|
62
109
|
|
|
63
110
|
/**
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*/
|
|
68
|
-
fields() {
|
|
69
|
-
return null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Called by the coordinator to set the field info for this client.
|
|
74
|
-
* @param {import('./types.js').FieldInfo[]} info The field info result.
|
|
75
|
-
* @returns {this}
|
|
76
|
-
*/
|
|
77
|
-
fieldInfo(info) { // eslint-disable-line no-unused-vars
|
|
78
|
-
return this;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Prepare the client before the query() method is called.
|
|
111
|
+
* Prepare the client before the `query()` method is called. Subclasses
|
|
112
|
+
* should override this method as needed, potentially issuing one or more
|
|
113
|
+
* queries to gather data or metadata needed prior to `query` calls.
|
|
83
114
|
*/
|
|
84
115
|
async prepare() {
|
|
85
116
|
}
|
|
@@ -122,34 +153,55 @@ export class MosaicClient {
|
|
|
122
153
|
|
|
123
154
|
/**
|
|
124
155
|
* Request the coordinator to execute a query for this client.
|
|
125
|
-
* If an explicit query is not provided, the client query method will
|
|
126
|
-
* be called, filtered by the current filterBy selection. This method
|
|
127
|
-
*
|
|
156
|
+
* If an explicit query is not provided, the client `query` method will
|
|
157
|
+
* be called, filtered by the current `filterBy` selection. This method has
|
|
158
|
+
* no effect if the client is not connected to a coordinator. If the client
|
|
159
|
+
* is connected by currently disabled, the request will be serviced if the
|
|
160
|
+
* client is later enabled.
|
|
161
|
+
* @param {Query} [query] The query to request. If unspecified, the query
|
|
162
|
+
* will be determind by the client's `query` method and the current
|
|
163
|
+
* `filterBy` selection state.
|
|
128
164
|
* @returns {Promise}
|
|
129
165
|
*/
|
|
130
166
|
requestQuery(query) {
|
|
131
|
-
|
|
132
|
-
|
|
167
|
+
if (this._enabled) {
|
|
168
|
+
const q = query || this.query(this.filterBy?.predicate(this));
|
|
169
|
+
return this._coordinator?.requestQuery(this, q);
|
|
170
|
+
} else {
|
|
171
|
+
this._request = query ?? true;
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
133
174
|
}
|
|
134
175
|
|
|
135
176
|
/**
|
|
136
177
|
* Request that the coordinator perform a throttled update of this client
|
|
137
|
-
* using the default query. Unlike requestQuery, for which every call
|
|
138
|
-
*
|
|
139
|
-
*
|
|
178
|
+
* using the default query. Unlike requestQuery, for which every call results
|
|
179
|
+
* in an executed query, multiple calls to requestUpdate may be consolidated
|
|
180
|
+
* into a single update. This method has no effect if the client is not
|
|
181
|
+
* connected to a coordinator. If the client is connected but currently
|
|
182
|
+
* disabled, the request will be serviced if the client is later enabled.
|
|
140
183
|
*/
|
|
141
184
|
requestUpdate() {
|
|
142
|
-
this.
|
|
185
|
+
if (this._enabled) {
|
|
186
|
+
this._requestUpdate();
|
|
187
|
+
} else {
|
|
188
|
+
this.requestQuery();
|
|
189
|
+
}
|
|
143
190
|
}
|
|
144
191
|
|
|
145
192
|
/**
|
|
146
|
-
* Reset this client,
|
|
147
|
-
*
|
|
148
|
-
* registered with a coordinator.
|
|
149
|
-
* @returns {Promise}
|
|
193
|
+
* Reset this client, calling the prepare method and query requests. This
|
|
194
|
+
* method has no effect if the client is not registered with a coordinator.
|
|
150
195
|
*/
|
|
151
196
|
initialize() {
|
|
152
|
-
|
|
197
|
+
if (!this._enabled) {
|
|
198
|
+
// clear flag so we initialize when enabled again
|
|
199
|
+
this._initialized = false;
|
|
200
|
+
} else if (this._coordinator) {
|
|
201
|
+
// if connected, let's initialize
|
|
202
|
+
this._initialized = true;
|
|
203
|
+
this._pending = this.prepare().then(() => this.requestQuery());
|
|
204
|
+
}
|
|
153
205
|
}
|
|
154
206
|
|
|
155
207
|
/**
|
package/src/make-client.js
CHANGED
|
@@ -1,64 +1,105 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
} from
|
|
1
|
+
/** @import { Coordinator } from './Coordinator.js' */
|
|
2
|
+
/** @import { Selection } from './Selection.js' */
|
|
3
|
+
import { MosaicClient } from './MosaicClient.js';
|
|
4
|
+
import { coordinator as defaultCoordinator } from './Coordinator.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* @typedef {Object} MakeClientOptions
|
|
8
|
-
* @property {
|
|
9
|
-
*
|
|
10
|
-
* @property {
|
|
11
|
-
*
|
|
12
|
-
* @property {
|
|
13
|
-
*
|
|
14
|
-
* @property {
|
|
8
|
+
* @property {Coordinator} [coordinator] Mosaic coordinator.
|
|
9
|
+
* Defaults to the global coordinator.
|
|
10
|
+
* @property {Selection|null} [selection] A selection whose predicates are
|
|
11
|
+
* fed into the query function to produce the SQL query.
|
|
12
|
+
* @property {boolean} [enabled] A flag (default `true`) indicating if the
|
|
13
|
+
* client should initially be enabled or not.
|
|
14
|
+
* @property {boolean} [filterStable] A flag (default `true`) indicating if the
|
|
15
|
+
* if client queries can be sped up using pre-aggregated data. Should be set
|
|
16
|
+
* to `false` if filtering changes the groupby domain of the query.
|
|
17
|
+
* @property {function(): Promise<void>} [prepare]
|
|
18
|
+
* An async function to prepare the client before running queries.
|
|
19
|
+
* @property {function(any): any} [query]
|
|
20
|
+
* A function that returns a query from a list of selection predicates.
|
|
21
|
+
* @property {function(any): void} [queryResult]
|
|
22
|
+
* Called by the coordinator to return a query result.
|
|
23
|
+
* @property {function(): void} [queryPending]
|
|
24
|
+
* Called by the coordinator to report a query execution error.
|
|
25
|
+
* @property {function(any): void} [queryError]
|
|
26
|
+
* Called by the coordinator to inform the client that a query is pending.
|
|
15
27
|
*/
|
|
16
28
|
|
|
17
|
-
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
29
|
+
/**
|
|
30
|
+
* Make a new client with the given options, and connect the client to the
|
|
31
|
+
* provided coordinator.
|
|
32
|
+
* @param {MakeClientOptions} options The options for making the client.
|
|
33
|
+
* @returns {MosaicClient & { destroy: () => void }} The resulting client,
|
|
34
|
+
* along with a method to destroy the client when no longer needed.
|
|
20
35
|
*/
|
|
21
36
|
export function makeClient(options) {
|
|
22
|
-
const
|
|
23
|
-
|
|
37
|
+
const {
|
|
38
|
+
coordinator = defaultCoordinator(),
|
|
39
|
+
...clientOptions
|
|
40
|
+
} = options;
|
|
41
|
+
const client = new ProxyClient(clientOptions);
|
|
24
42
|
coordinator.connect(client);
|
|
25
43
|
return client;
|
|
26
44
|
}
|
|
27
45
|
|
|
28
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* An internal class used to implement the makeClient API.
|
|
48
|
+
*/
|
|
29
49
|
class ProxyClient extends MosaicClient {
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
|
|
50
|
+
/**
|
|
51
|
+
* @param {MakeClientOptions} options The options for making the client.
|
|
52
|
+
*/
|
|
53
|
+
constructor({
|
|
54
|
+
selection = undefined,
|
|
55
|
+
enabled = true,
|
|
56
|
+
filterStable = true,
|
|
57
|
+
...methods
|
|
58
|
+
}) {
|
|
59
|
+
super(selection);
|
|
60
|
+
this.enabled = enabled;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @type {MakeClientOptions}
|
|
64
|
+
* @readonly
|
|
65
|
+
*/
|
|
66
|
+
this._methods = methods;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @type {boolean}
|
|
70
|
+
* @readonly
|
|
71
|
+
*/
|
|
72
|
+
this._filterStable = filterStable;
|
|
73
|
+
}
|
|
33
74
|
|
|
34
|
-
|
|
35
|
-
this.
|
|
75
|
+
get filterStable() {
|
|
76
|
+
return this._filterStable;
|
|
36
77
|
}
|
|
37
78
|
|
|
38
79
|
async prepare() {
|
|
39
|
-
await this.
|
|
80
|
+
await this._methods.prepare?.();
|
|
40
81
|
}
|
|
41
82
|
|
|
42
83
|
query(filter) {
|
|
43
|
-
return this.
|
|
84
|
+
return this._methods.query?.(filter) ?? null;
|
|
44
85
|
}
|
|
45
86
|
|
|
46
87
|
queryResult(data) {
|
|
47
|
-
this.
|
|
88
|
+
this._methods.queryResult?.(data);
|
|
48
89
|
return this;
|
|
49
90
|
}
|
|
50
91
|
|
|
51
92
|
queryPending() {
|
|
52
|
-
this.
|
|
93
|
+
this._methods.queryPending?.();
|
|
53
94
|
return this;
|
|
54
95
|
}
|
|
55
96
|
|
|
56
97
|
queryError(error) {
|
|
57
|
-
this.
|
|
98
|
+
this._methods.queryError?.(error);
|
|
58
99
|
return this;
|
|
59
100
|
}
|
|
60
101
|
|
|
61
102
|
destroy() {
|
|
62
|
-
this.
|
|
103
|
+
this.coordinator.disconnect(this);
|
|
63
104
|
}
|
|
64
105
|
}
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
/** @import { ExprNode } from '@uwdata/mosaic-sql' */
|
|
2
|
+
/** @import { Coordinator } from '../Coordinator.js' */
|
|
3
|
+
/** @import { MosaicClient } from '../MosaicClient.js' */
|
|
4
|
+
/** @import { Selection } from '../Selection.js' */
|
|
5
|
+
/** @import { BinMethod, Scale, SelectionClause } from '../util/selection-types.js' */
|
|
6
|
+
import { Query, and, asNode, ceil, collectColumns, createTable, float64, floor, isBetween, int32, mul, round, scaleTransform, sub, isSelectQuery, SelectQuery, isAggregateExpression, ColumnNameRefNode } from '@uwdata/mosaic-sql';
|
|
2
7
|
import { preaggColumns } from './preagg-columns.js';
|
|
3
8
|
import { fnv_hash } from '../util/hash.js';
|
|
4
9
|
|
|
@@ -34,14 +39,14 @@ const Skip = { skip: true, result: null };
|
|
|
34
39
|
export class PreAggregator {
|
|
35
40
|
/**
|
|
36
41
|
* Create a new manager of materialized views of pre-aggregated data.
|
|
37
|
-
* @param {
|
|
42
|
+
* @param {Coordinator} coordinator A Mosaic coordinator.
|
|
38
43
|
* @param {PreAggregateOptions} [options] Pre-aggregation options.
|
|
39
44
|
*/
|
|
40
45
|
constructor(coordinator, {
|
|
41
46
|
schema = 'mosaic',
|
|
42
47
|
enabled = true
|
|
43
48
|
} = {}) {
|
|
44
|
-
/** @type {Map<
|
|
49
|
+
/** @type {Map<MosaicClient, PreAggregateInfo | Skip | null>} */
|
|
45
50
|
this.entries = new Map();
|
|
46
51
|
this.active = null;
|
|
47
52
|
this.mc = coordinator;
|
|
@@ -123,12 +128,10 @@ export class PreAggregator {
|
|
|
123
128
|
* client-selection pair, or null if the client has unstable filters.
|
|
124
129
|
* This method has multiple possible side effects, including materialized
|
|
125
130
|
* view creation and updating internal caches.
|
|
126
|
-
* @param {
|
|
127
|
-
* @param {
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
* A representative active selection clause for which to (possibly) generate
|
|
131
|
-
* materialized views of pre-aggregates.
|
|
131
|
+
* @param {MosaicClient} client A Mosaic client.
|
|
132
|
+
* @param {Selection} selection A Mosaic selection to filter the client by.
|
|
133
|
+
* @param {SelectionClause} activeClause A representative active selection
|
|
134
|
+
* clause for which to generate materialized views of pre-aggregates.
|
|
132
135
|
* @returns {PreAggregateInfo | Skip | null} Information and query generator
|
|
133
136
|
* for pre-aggregated tables, or null if the client has unstable filters.
|
|
134
137
|
*/
|
|
@@ -205,8 +208,7 @@ export class PreAggregator {
|
|
|
205
208
|
* function for the active dimensions of a pre-aggregated materialized view.
|
|
206
209
|
* If the active clause is not indexable or is missing metadata, this method
|
|
207
210
|
* returns an object with a null source property.
|
|
208
|
-
* @param {
|
|
209
|
-
* The active selection clause to analyze.
|
|
211
|
+
* @param {SelectionClause} clause The active selection clause to analyze.
|
|
210
212
|
*/
|
|
211
213
|
function activeColumns(clause) {
|
|
212
214
|
const { source, meta } = clause;
|
|
@@ -261,12 +263,12 @@ const BIN = { ceil, round };
|
|
|
261
263
|
|
|
262
264
|
/**
|
|
263
265
|
* Returns a bin function generator to discretize a selection interval domain.
|
|
264
|
-
* @param {
|
|
265
|
-
*
|
|
266
|
+
* @param {Scale} scale A scale that maps domain values to the output range
|
|
267
|
+
* (typically pixels).
|
|
266
268
|
* @param {number} pixelSize The interactive pixel size. This value indicates
|
|
267
269
|
* the bin step size and may be greater than an actual screen pixel.
|
|
268
|
-
* @param {
|
|
269
|
-
*
|
|
270
|
+
* @param {BinMethod} bin The binning method to apply, one of `floor`,
|
|
271
|
+
* `ceil', or `round`.
|
|
270
272
|
* @returns {(value: any) => ExprNode} A bin function generator.
|
|
271
273
|
*/
|
|
272
274
|
function binInterval(scale, pixelSize, bin) {
|
|
@@ -426,8 +428,7 @@ export class PreAggregateInfo {
|
|
|
426
428
|
|
|
427
429
|
/**
|
|
428
430
|
* Generate a materialized view query for the given predicate.
|
|
429
|
-
* @param {
|
|
430
|
-
* active clause predicate.
|
|
431
|
+
* @param {ExprNode} predicate The current active clause predicate.
|
|
431
432
|
* @returns {SelectQuery} A materialized view query.
|
|
432
433
|
*/
|
|
433
434
|
query(predicate) {
|