@absolutejs/sync 2.0.1 → 2.2.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/engine/collection.d.ts +14 -1
- package/dist/engine/devtools.d.ts +15 -0
- package/dist/engine/index.js +26 -2
- package/dist/engine/index.js.map +4 -4
- package/dist/index.js +26 -2
- package/dist/index.js.map +3 -3
- package/dist/testing.js +26 -2
- package/dist/testing.js.map +3 -3
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RowKey } from './types';
|
|
1
|
+
import type { RowChange, RowKey } from './types';
|
|
2
2
|
/**
|
|
3
3
|
* App-provided context for a subscription — typically the authenticated session
|
|
4
4
|
* (user id, roles). Passed to `authorize`, `hydrate`, and `match` so a
|
|
@@ -32,6 +32,19 @@ export type CollectionDefinition<T, P = void, Ctx = CollectionContext> = {
|
|
|
32
32
|
* two in lockstep — the planned adapter convenience.)
|
|
33
33
|
*/
|
|
34
34
|
match?: (row: T, params: P, ctx: Ctx) => boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Refetch-fallback gate (multi-table / shape-mismatched collections that can't
|
|
37
|
+
* use `match`). Without it, ANY change to a read table re-hydrates EVERY
|
|
38
|
+
* subscription — even ones the change can't touch. Given the RAW change (the
|
|
39
|
+
* source row, which may differ from `T` and be partial), return `false` ONLY
|
|
40
|
+
* when the change provably can't affect this subscription's result, to skip
|
|
41
|
+
* its re-hydrate; the fan-out drops from O(all subscribers) to O(affected).
|
|
42
|
+
*
|
|
43
|
+
* Conservative: a `false` that should have been `true` DROPS an update, so
|
|
44
|
+
* default to `true` when unsure (e.g. a delete whose row lacks your scope
|
|
45
|
+
* field). Ignored when `match` is set (incremental routing is already exact).
|
|
46
|
+
*/
|
|
47
|
+
affects?: (change: RowChange<unknown>, params: P, ctx: Ctx) => boolean;
|
|
35
48
|
/**
|
|
36
49
|
* Access control: return `false` (or throw) to deny the subscription. Runs
|
|
37
50
|
* before `hydrate`. Without it a collection is world-readable, so treat it as
|
|
@@ -113,6 +113,21 @@ export type EngineMetrics = {
|
|
|
113
113
|
schedules: {
|
|
114
114
|
registered: number;
|
|
115
115
|
};
|
|
116
|
+
/**
|
|
117
|
+
* Change-source liveness, aggregated across every `connectSource` (e.g. a
|
|
118
|
+
* CDC adapter). Lets a health check distinguish a healthy-but-quiet feed
|
|
119
|
+
* from a wired-but-silent or disconnected one. Added in 2.1.0.
|
|
120
|
+
*/
|
|
121
|
+
source: {
|
|
122
|
+
/** Currently-connected change sources (0 once all have disconnected). */
|
|
123
|
+
connected: number;
|
|
124
|
+
/** Total changes delivered by connected sources since engine start. */
|
|
125
|
+
changesReceived: number;
|
|
126
|
+
/** `Date.now()` of the most recent source change, or `null` if none yet. */
|
|
127
|
+
lastChangeAt: number | null;
|
|
128
|
+
/** Wall-clock age of the most recent source change in ms, or `null`. */
|
|
129
|
+
lastChangeAgeMs: number | null;
|
|
130
|
+
};
|
|
116
131
|
};
|
|
117
132
|
/**
|
|
118
133
|
* A live engine event (see {@link SyncEngine.onActivity}): a committed change or
|
package/dist/engine/index.js
CHANGED
|
@@ -1611,6 +1611,9 @@ var createSyncEngine = (options = {}) => {
|
|
|
1611
1611
|
let mutationsFailed = 0;
|
|
1612
1612
|
let mutationsRetried = 0;
|
|
1613
1613
|
let mutationsInFlight = 0;
|
|
1614
|
+
let connectedSources = 0;
|
|
1615
|
+
let sourceChangesReceived = 0;
|
|
1616
|
+
let sourceLastChangeAt = null;
|
|
1614
1617
|
const mutationWaiters = [];
|
|
1615
1618
|
let mutationsQueued = 0;
|
|
1616
1619
|
const activeFences = new Set;
|
|
@@ -1796,6 +1799,9 @@ var createSyncEngine = (options = {}) => {
|
|
|
1796
1799
|
return subscription.view.reset(await subscription.rehydrate());
|
|
1797
1800
|
}
|
|
1798
1801
|
}
|
|
1802
|
+
if (subscription.affects && !subscription.affects(change)) {
|
|
1803
|
+
return EMPTY_DIFF;
|
|
1804
|
+
}
|
|
1799
1805
|
return subscription.view.reset(await subscription.rehydrate());
|
|
1800
1806
|
};
|
|
1801
1807
|
const subscriptionsForTable = function* (table) {
|
|
@@ -2588,6 +2594,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2588
2594
|
return readRule ? rows.filter((row) => readRule(ctx, row)) : rows;
|
|
2589
2595
|
};
|
|
2590
2596
|
const incremental = match !== undefined && tables.length === 1;
|
|
2597
|
+
const boundAffects = !incremental && definition.affects ? (change) => definition.affects(change, params, ctx) : undefined;
|
|
2591
2598
|
const boundMatch = incremental ? (row) => match(row, params, ctx) && (readRule ? readRule(ctx, row) : true) : () => true;
|
|
2592
2599
|
const view = createMaterializedView({
|
|
2593
2600
|
key,
|
|
@@ -2602,6 +2609,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2602
2609
|
view,
|
|
2603
2610
|
incremental,
|
|
2604
2611
|
rehydrate,
|
|
2612
|
+
...boundAffects ? { affects: boundAffects } : {},
|
|
2605
2613
|
key,
|
|
2606
2614
|
onDiff: typedOnDiff
|
|
2607
2615
|
};
|
|
@@ -2664,8 +2672,18 @@ var createSyncEngine = (options = {}) => {
|
|
|
2664
2672
|
},
|
|
2665
2673
|
applyChange: (table, change) => applyChange(table, change),
|
|
2666
2674
|
connectSource: async (source) => {
|
|
2667
|
-
await source.start((table, change) =>
|
|
2675
|
+
await source.start((table, change) => {
|
|
2676
|
+
sourceChangesReceived += 1;
|
|
2677
|
+
sourceLastChangeAt = Date.now();
|
|
2678
|
+
return applyChange(table, change);
|
|
2679
|
+
});
|
|
2680
|
+
connectedSources += 1;
|
|
2681
|
+
let stopped = false;
|
|
2668
2682
|
return async () => {
|
|
2683
|
+
if (!stopped) {
|
|
2684
|
+
stopped = true;
|
|
2685
|
+
connectedSources -= 1;
|
|
2686
|
+
}
|
|
2669
2687
|
await source.stop();
|
|
2670
2688
|
};
|
|
2671
2689
|
},
|
|
@@ -3226,6 +3244,12 @@ var createSyncEngine = (options = {}) => {
|
|
|
3226
3244
|
schedules: {
|
|
3227
3245
|
registered: schedules.size
|
|
3228
3246
|
},
|
|
3247
|
+
source: {
|
|
3248
|
+
changesReceived: sourceChangesReceived,
|
|
3249
|
+
connected: connectedSources,
|
|
3250
|
+
lastChangeAgeMs: sourceLastChangeAt === null ? null : now - sourceLastChangeAt,
|
|
3251
|
+
lastChangeAt: sourceLastChangeAt
|
|
3252
|
+
},
|
|
3229
3253
|
subscriptions: {
|
|
3230
3254
|
byCollection,
|
|
3231
3255
|
byTenant: Object.fromEntries(subscriptionsByTenant),
|
|
@@ -3769,5 +3793,5 @@ export {
|
|
|
3769
3793
|
CdcConsumerSlowError
|
|
3770
3794
|
};
|
|
3771
3795
|
|
|
3772
|
-
//# debugId=
|
|
3796
|
+
//# debugId=40999B3553DAC88C64756E2164756E21
|
|
3773
3797
|
//# sourceMappingURL=index.js.map
|