@uwdata/mosaic-core 0.1.0 → 0.3.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/mosaic-core.js +1895 -11407
- package/dist/mosaic-core.min.js +4 -13
- package/package.json +4 -4
- package/src/Catalog.js +37 -19
- package/src/Coordinator.js +72 -51
- package/src/DataTileIndexer.js +49 -50
- package/src/FilterGroup.js +3 -6
- package/src/MosaicClient.js +5 -2
- package/src/Param.js +67 -21
- package/src/QueryConsolidator.js +238 -0
- package/src/QueryManager.js +133 -0
- package/src/Selection.js +236 -33
- package/src/{clients → connectors}/rest.js +1 -1
- package/src/{clients → connectors}/socket.js +1 -1
- package/src/{clients → connectors}/wasm.js +1 -1
- package/src/index.js +7 -4
- package/src/util/AsyncDispatch.js +180 -0
- package/src/util/cache.js +58 -0
- package/src/util/priority-queue.js +85 -0
- package/src/util/query-result.js +8 -0
- package/src/util/synchronizer.js +47 -0
- package/src/QueryCache.js +0 -65
- package/src/util/skip-client.js +0 -3
- package/src/util/sql-from.js +0 -22
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a new synchronizer instance to aid synchronization
|
|
3
|
+
* of updates on multiple pending operations.
|
|
4
|
+
*/
|
|
5
|
+
export function synchronizer() {
|
|
6
|
+
const set = new Set;
|
|
7
|
+
let done;
|
|
8
|
+
let promise = new Promise(resolve => done = resolve);
|
|
9
|
+
|
|
10
|
+
return {
|
|
11
|
+
/**
|
|
12
|
+
* Mark an item as pending.
|
|
13
|
+
* @param {*} item An item to synchronize on.
|
|
14
|
+
*/
|
|
15
|
+
pending(item) {
|
|
16
|
+
set.add(item);
|
|
17
|
+
},
|
|
18
|
+
/**
|
|
19
|
+
* Mark a pending item as ready, indicating it is
|
|
20
|
+
* ready for a synchronized update.
|
|
21
|
+
* @param {*} item An item to synchronize on.
|
|
22
|
+
* @returns {boolean} True if the synchronizer is ready to
|
|
23
|
+
* resolve, false otherwise.
|
|
24
|
+
*/
|
|
25
|
+
ready(item) {
|
|
26
|
+
set.delete(item);
|
|
27
|
+
return set.size === 0;
|
|
28
|
+
},
|
|
29
|
+
/**
|
|
30
|
+
* Resolve the current synchronization cycle, causing the synchronize
|
|
31
|
+
* promise to resolve and thereby trigger downstream updates.
|
|
32
|
+
*/
|
|
33
|
+
resolve() {
|
|
34
|
+
promise = new Promise(resolve => {
|
|
35
|
+
done();
|
|
36
|
+
done = resolve;
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
/**
|
|
40
|
+
* The promise for the current synchronization cycle.
|
|
41
|
+
* @return {Promise} The synchronization promise.
|
|
42
|
+
*/
|
|
43
|
+
get promise() {
|
|
44
|
+
return promise;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/src/QueryCache.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
const requestIdle = typeof requestIdleCallback !== 'undefined'
|
|
2
|
-
? requestIdleCallback
|
|
3
|
-
: setTimeout;
|
|
4
|
-
|
|
5
|
-
export const voidCache = () => ({
|
|
6
|
-
get: () => undefined,
|
|
7
|
-
set: (key, result) => result,
|
|
8
|
-
clear: () => {}
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
export class QueryCache {
|
|
12
|
-
constructor({
|
|
13
|
-
max = 1000, // max entries
|
|
14
|
-
ttl = 3 * 60 * 60 * 1000 // time-to-live, default 3 hours
|
|
15
|
-
} = {}) {
|
|
16
|
-
this.max = max;
|
|
17
|
-
this.ttl = ttl;
|
|
18
|
-
this.clear();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
clear() {
|
|
22
|
-
this.cache = new Map();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get(key) {
|
|
26
|
-
const entry = this.cache.get(key);
|
|
27
|
-
if (entry) {
|
|
28
|
-
entry.last = performance.now();
|
|
29
|
-
return entry.promise;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
set(key, promise) {
|
|
34
|
-
const { cache, max } = this;
|
|
35
|
-
cache.set(key, { last: performance.now(), promise });
|
|
36
|
-
if (cache.size > max) requestIdle(() => this.evict());
|
|
37
|
-
return promise;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
evict() {
|
|
41
|
-
const expire = performance.now() - this.ttl;
|
|
42
|
-
let lruKey = null;
|
|
43
|
-
let lruLast = Infinity;
|
|
44
|
-
|
|
45
|
-
for (const [key, value] of this.cache) {
|
|
46
|
-
const { last } = value;
|
|
47
|
-
|
|
48
|
-
// least recently used entry seen so far
|
|
49
|
-
if (last < lruLast) {
|
|
50
|
-
lruKey = key;
|
|
51
|
-
lruLast = last;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// remove if time since last access exceeds ttl
|
|
55
|
-
if (expire > last) {
|
|
56
|
-
this.cache.delete(key);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// remove lru entry
|
|
61
|
-
if (lruKey) {
|
|
62
|
-
this.cache.delete(lruKey);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
package/src/util/skip-client.js
DELETED
package/src/util/sql-from.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { literalToSQL } from '@uwdata/mosaic-sql';
|
|
2
|
-
|
|
3
|
-
export function sqlFrom(data, {
|
|
4
|
-
columns = Object.keys(data?.[0] || {})
|
|
5
|
-
} = {}) {
|
|
6
|
-
let keys = [];
|
|
7
|
-
if (Array.isArray(columns)) {
|
|
8
|
-
keys = columns;
|
|
9
|
-
columns = keys.reduce((m, k) => (m[k] = k, m), {});
|
|
10
|
-
} else if (columns) {
|
|
11
|
-
keys = Object.keys(columns);
|
|
12
|
-
}
|
|
13
|
-
if (!keys.length) {
|
|
14
|
-
throw new Error('Can not create table from empty column set.');
|
|
15
|
-
}
|
|
16
|
-
const subq = [];
|
|
17
|
-
for (const datum of data) {
|
|
18
|
-
const sel = keys.map(k => `${literalToSQL(datum[k])} AS "${columns[k]}"`);
|
|
19
|
-
subq.push(`(SELECT ${sel.join(', ')})`);
|
|
20
|
-
}
|
|
21
|
-
return subq.join(' UNION ALL ');
|
|
22
|
-
}
|