@absolutejs/sync 1.18.0 → 1.18.2
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/adapters/tanstack-db/index.js +9 -2
- package/dist/adapters/tanstack-db/index.js.map +3 -3
- package/dist/angular/index.js +9 -2
- package/dist/angular/index.js.map +3 -3
- package/dist/client/index.js +29 -4
- package/dist/client/index.js.map +5 -5
- package/dist/engine/cluster.d.ts +17 -3
- package/dist/engine/connection.d.ts +18 -3
- package/dist/engine/index.js +128 -26
- package/dist/engine/index.js.map +5 -5
- package/dist/engine/syncEngine.d.ts +58 -8
- package/dist/index.js +128 -26
- package/dist/index.js.map +4 -4
- package/dist/react/index.js +9 -2
- package/dist/react/index.js.map +3 -3
- package/dist/svelte/index.js +9 -2
- package/dist/svelte/index.js.map +3 -3
- package/dist/testing.js +111 -18
- package/dist/testing.js.map +3 -3
- package/dist/vue/index.js +9 -2
- package/dist/vue/index.js.map +3 -3
- package/package.json +1 -1
package/dist/engine/index.js
CHANGED
|
@@ -1565,11 +1565,11 @@ var createSyncEngine = (options = {}) => {
|
|
|
1565
1565
|
};
|
|
1566
1566
|
const streamSubscribers = new Set;
|
|
1567
1567
|
const runInTransaction = options.transaction;
|
|
1568
|
-
const instanceId = globalThis.crypto?.randomUUID?.() ?? `i${Math.random()}`;
|
|
1568
|
+
const instanceId = options.instanceId ?? globalThis.crypto?.randomUUID?.() ?? `i${Math.random()}`;
|
|
1569
1569
|
let clusterBus;
|
|
1570
|
-
const broadcast = (changes) => {
|
|
1570
|
+
const broadcast = (changes, originVersion) => {
|
|
1571
1571
|
if (clusterBus !== undefined && changes.length > 0) {
|
|
1572
|
-
clusterBus.publish({ changes, origin: instanceId });
|
|
1572
|
+
clusterBus.publish({ changes, origin: instanceId, originVersion });
|
|
1573
1573
|
}
|
|
1574
1574
|
};
|
|
1575
1575
|
const subsFor = (collection) => {
|
|
@@ -1946,11 +1946,44 @@ var createSyncEngine = (options = {}) => {
|
|
|
1946
1946
|
subscriber(entry);
|
|
1947
1947
|
}
|
|
1948
1948
|
};
|
|
1949
|
+
const encodeCursor = (versions) => JSON.stringify(versions);
|
|
1950
|
+
const decodeCursor = (cursor) => {
|
|
1951
|
+
try {
|
|
1952
|
+
const parsed = JSON.parse(cursor);
|
|
1953
|
+
if (typeof parsed !== "object" || parsed === null)
|
|
1954
|
+
return null;
|
|
1955
|
+
const out = {};
|
|
1956
|
+
for (const [k, v] of Object.entries(parsed)) {
|
|
1957
|
+
if (typeof v === "number")
|
|
1958
|
+
out[k] = v;
|
|
1959
|
+
}
|
|
1960
|
+
return out;
|
|
1961
|
+
} catch {
|
|
1962
|
+
return null;
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
const currentCursor = () => {
|
|
1966
|
+
const versions = { [instanceId]: version };
|
|
1967
|
+
for (let i = changeLog.length - 1;i >= 0; i--) {
|
|
1968
|
+
const entry = changeLog[i];
|
|
1969
|
+
if (versions[entry.origin] === undefined) {
|
|
1970
|
+
versions[entry.origin] = entry.originVersion;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
return encodeCursor(versions);
|
|
1974
|
+
};
|
|
1949
1975
|
const applyChange = async (table, change, shouldBroadcast = true) => {
|
|
1950
1976
|
version += 1;
|
|
1951
1977
|
const changeVersion = version;
|
|
1952
1978
|
const at = Date.now();
|
|
1953
|
-
logChange(changeVersion, {
|
|
1979
|
+
logChange(changeVersion, {
|
|
1980
|
+
version: changeVersion,
|
|
1981
|
+
table,
|
|
1982
|
+
change,
|
|
1983
|
+
at,
|
|
1984
|
+
origin: instanceId,
|
|
1985
|
+
originVersion: changeVersion
|
|
1986
|
+
});
|
|
1954
1987
|
emitActivity({
|
|
1955
1988
|
type: "change",
|
|
1956
1989
|
at,
|
|
@@ -1969,14 +2002,15 @@ var createSyncEngine = (options = {}) => {
|
|
|
1969
2002
|
{ table, key: changedKeyFor(table, change), row: change.row }
|
|
1970
2003
|
]));
|
|
1971
2004
|
emissions.push(...searchPairs([{ table, change }]));
|
|
2005
|
+
const cursorForBatch = currentCursor();
|
|
1972
2006
|
for (const [subscription, diff] of emissions) {
|
|
1973
|
-
subscription.onDiff(diff, changeVersion);
|
|
2007
|
+
subscription.onDiff(diff, changeVersion, cursorForBatch);
|
|
1974
2008
|
}
|
|
1975
2009
|
if (shouldBroadcast) {
|
|
1976
|
-
broadcast([{ table, change }]);
|
|
2010
|
+
broadcast([{ table, change }], changeVersion);
|
|
1977
2011
|
}
|
|
1978
2012
|
};
|
|
1979
|
-
const applyChangeBatch = async (changes, shouldBroadcast = true) => {
|
|
2013
|
+
const applyChangeBatch = async (changes, shouldBroadcast = true, peerOrigin) => {
|
|
1980
2014
|
if (changes.length === 0) {
|
|
1981
2015
|
return;
|
|
1982
2016
|
}
|
|
@@ -1985,8 +2019,17 @@ var createSyncEngine = (options = {}) => {
|
|
|
1985
2019
|
const perSubscription = new Map;
|
|
1986
2020
|
const reactiveChanges = [];
|
|
1987
2021
|
const batchAt = Date.now();
|
|
2022
|
+
const batchOrigin = peerOrigin?.origin ?? instanceId;
|
|
2023
|
+
const batchOriginVersion = peerOrigin?.originVersion ?? batchVersion;
|
|
1988
2024
|
for (const { table, change } of changes) {
|
|
1989
|
-
logChange(batchVersion, {
|
|
2025
|
+
logChange(batchVersion, {
|
|
2026
|
+
version: batchVersion,
|
|
2027
|
+
table,
|
|
2028
|
+
change,
|
|
2029
|
+
at: batchAt,
|
|
2030
|
+
origin: batchOrigin,
|
|
2031
|
+
originVersion: batchOriginVersion
|
|
2032
|
+
});
|
|
1990
2033
|
emitActivity({
|
|
1991
2034
|
type: "change",
|
|
1992
2035
|
at: batchAt,
|
|
@@ -2018,29 +2061,70 @@ var createSyncEngine = (options = {}) => {
|
|
|
2018
2061
|
}
|
|
2019
2062
|
emissions.push(...await reactivePairs(reactiveChanges));
|
|
2020
2063
|
emissions.push(...searchPairs(changes));
|
|
2064
|
+
const cursorForBatch = currentCursor();
|
|
2021
2065
|
for (const [subscription, diff] of emissions) {
|
|
2022
|
-
subscription.onDiff(diff, batchVersion);
|
|
2066
|
+
subscription.onDiff(diff, batchVersion, cursorForBatch);
|
|
2023
2067
|
}
|
|
2024
2068
|
if (shouldBroadcast) {
|
|
2025
|
-
broadcast(changes);
|
|
2069
|
+
broadcast(changes, batchVersion);
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
const normalizeSince = (since) => {
|
|
2073
|
+
if (typeof since === "number") {
|
|
2074
|
+
return { [instanceId]: since };
|
|
2026
2075
|
}
|
|
2076
|
+
return decodeCursor(since);
|
|
2027
2077
|
};
|
|
2028
2078
|
const canResume = (since, incremental) => {
|
|
2029
2079
|
if (!incremental) {
|
|
2030
2080
|
return false;
|
|
2031
2081
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
2082
|
+
const sinceVec = normalizeSince(since);
|
|
2083
|
+
if (sinceVec === null) {
|
|
2084
|
+
return false;
|
|
2085
|
+
}
|
|
2086
|
+
const oldestPerOrigin = new Map;
|
|
2087
|
+
for (const entry of changeLog) {
|
|
2088
|
+
const current = oldestPerOrigin.get(entry.origin);
|
|
2089
|
+
if (current === undefined || entry.originVersion < current) {
|
|
2090
|
+
oldestPerOrigin.set(entry.origin, entry.originVersion);
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
const oldestLogVersion = changeLog[0]?.version;
|
|
2094
|
+
for (const [origin, lastSeen] of Object.entries(sinceVec)) {
|
|
2095
|
+
if (origin === instanceId) {
|
|
2096
|
+
if (lastSeen >= version)
|
|
2097
|
+
continue;
|
|
2098
|
+
const oldestLocal = oldestPerOrigin.get(instanceId);
|
|
2099
|
+
if (oldestLocal !== undefined) {
|
|
2100
|
+
if (oldestLocal > lastSeen + 1)
|
|
2101
|
+
return false;
|
|
2102
|
+
continue;
|
|
2103
|
+
}
|
|
2104
|
+
if (oldestLogVersion !== undefined && oldestLogVersion > lastSeen + 1) {
|
|
2105
|
+
return false;
|
|
2106
|
+
}
|
|
2107
|
+
} else {
|
|
2108
|
+
const oldestPeer = oldestPerOrigin.get(origin);
|
|
2109
|
+
if (oldestPeer === undefined) {
|
|
2110
|
+
if (lastSeen > 0)
|
|
2111
|
+
return false;
|
|
2112
|
+
} else if (oldestPeer > lastSeen + 1) {
|
|
2113
|
+
return false;
|
|
2114
|
+
}
|
|
2115
|
+
}
|
|
2034
2116
|
}
|
|
2035
|
-
|
|
2036
|
-
return oldest !== undefined && oldest.version <= since + 1;
|
|
2117
|
+
return true;
|
|
2037
2118
|
};
|
|
2038
2119
|
const buildCatchup = (since, tables, key, match) => {
|
|
2120
|
+
const sinceVec = normalizeSince(since) ?? {};
|
|
2039
2121
|
const latest = new Map;
|
|
2040
2122
|
for (const entry of changeLog) {
|
|
2041
|
-
if (
|
|
2123
|
+
if (!tables.includes(entry.table))
|
|
2124
|
+
continue;
|
|
2125
|
+
const lastSeen = sinceVec[entry.origin];
|
|
2126
|
+
if (lastSeen !== undefined && entry.originVersion <= lastSeen)
|
|
2042
2127
|
continue;
|
|
2043
|
-
}
|
|
2044
2128
|
const row = entry.change.row;
|
|
2045
2129
|
const present = entry.change.op !== "delete" && match(row) ? "upsert" : "remove";
|
|
2046
2130
|
latest.set(key(row), { op: present, row });
|
|
@@ -2085,6 +2169,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2085
2169
|
set.add(subscription);
|
|
2086
2170
|
return {
|
|
2087
2171
|
initial: op.rows(),
|
|
2172
|
+
cursor: currentCursor(),
|
|
2088
2173
|
version: atVersion,
|
|
2089
2174
|
unsubscribe: () => {
|
|
2090
2175
|
set.delete(subscription);
|
|
@@ -2111,6 +2196,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2111
2196
|
set.add(subscription);
|
|
2112
2197
|
return {
|
|
2113
2198
|
initial,
|
|
2199
|
+
cursor: currentCursor(),
|
|
2114
2200
|
version: atVersion,
|
|
2115
2201
|
unsubscribe: () => {
|
|
2116
2202
|
set.delete(subscription);
|
|
@@ -2172,6 +2258,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2172
2258
|
reactiveSubs.add(subscription);
|
|
2173
2259
|
return {
|
|
2174
2260
|
initial: first.rows,
|
|
2261
|
+
cursor: currentCursor(),
|
|
2175
2262
|
version: atVersion,
|
|
2176
2263
|
unsubscribe: () => {
|
|
2177
2264
|
set.delete(subscription);
|
|
@@ -2216,6 +2303,7 @@ var createSyncEngine = (options = {}) => {
|
|
|
2216
2303
|
searchSubs.add(subscription);
|
|
2217
2304
|
return {
|
|
2218
2305
|
initial,
|
|
2306
|
+
cursor: currentCursor(),
|
|
2219
2307
|
version: atVersion,
|
|
2220
2308
|
unsubscribe: () => {
|
|
2221
2309
|
set.delete(subscription);
|
|
@@ -2317,12 +2405,14 @@ var createSyncEngine = (options = {}) => {
|
|
|
2317
2405
|
return wrapReturn({
|
|
2318
2406
|
initial: [],
|
|
2319
2407
|
catchup: buildCatchup(since, tables, key, boundMatch),
|
|
2408
|
+
cursor: currentCursor(),
|
|
2320
2409
|
version: atVersion,
|
|
2321
2410
|
unsubscribe
|
|
2322
2411
|
});
|
|
2323
2412
|
}
|
|
2324
2413
|
return wrapReturn({
|
|
2325
2414
|
initial: view.rows(),
|
|
2415
|
+
cursor: currentCursor(),
|
|
2326
2416
|
version: atVersion,
|
|
2327
2417
|
unsubscribe
|
|
2328
2418
|
});
|
|
@@ -2361,7 +2451,10 @@ var createSyncEngine = (options = {}) => {
|
|
|
2361
2451
|
if (message.origin === instanceId) {
|
|
2362
2452
|
return;
|
|
2363
2453
|
}
|
|
2364
|
-
applyChangeBatch(message.changes, false
|
|
2454
|
+
applyChangeBatch(message.changes, false, {
|
|
2455
|
+
origin: message.origin,
|
|
2456
|
+
originVersion: message.originVersion ?? 0
|
|
2457
|
+
});
|
|
2365
2458
|
});
|
|
2366
2459
|
clusterBus = bus;
|
|
2367
2460
|
return async () => {
|
|
@@ -3032,12 +3125,13 @@ var parseFrame = (raw, serializer) => {
|
|
|
3032
3125
|
}
|
|
3033
3126
|
const frame = value;
|
|
3034
3127
|
if (frame.type === "subscribe") {
|
|
3128
|
+
const since = typeof frame.since === "number" || typeof frame.since === "string" ? frame.since : undefined;
|
|
3035
3129
|
return typeof frame.id === "string" && typeof frame.collection === "string" ? {
|
|
3036
3130
|
type: "subscribe",
|
|
3037
3131
|
id: frame.id,
|
|
3038
3132
|
collection: frame.collection,
|
|
3039
3133
|
params: frame.params,
|
|
3040
|
-
since
|
|
3134
|
+
since
|
|
3041
3135
|
} : undefined;
|
|
3042
3136
|
}
|
|
3043
3137
|
if (frame.type === "unsubscribe") {
|
|
@@ -3089,6 +3183,7 @@ var createSyncConnection = ({
|
|
|
3089
3183
|
};
|
|
3090
3184
|
let pending = [];
|
|
3091
3185
|
let pendingVersion;
|
|
3186
|
+
let pendingCursor;
|
|
3092
3187
|
let flushScheduled = false;
|
|
3093
3188
|
const flush = () => {
|
|
3094
3189
|
if (pending.length === 0) {
|
|
@@ -3096,8 +3191,10 @@ var createSyncConnection = ({
|
|
|
3096
3191
|
}
|
|
3097
3192
|
const diffs = pending;
|
|
3098
3193
|
const version = pendingVersion;
|
|
3194
|
+
const cursor = pendingCursor;
|
|
3099
3195
|
pending = [];
|
|
3100
3196
|
pendingVersion = undefined;
|
|
3197
|
+
pendingCursor = undefined;
|
|
3101
3198
|
if (diffs.length === 1) {
|
|
3102
3199
|
const only = diffs[0];
|
|
3103
3200
|
send({
|
|
@@ -3106,10 +3203,11 @@ var createSyncConnection = ({
|
|
|
3106
3203
|
added: only.added,
|
|
3107
3204
|
removed: only.removed,
|
|
3108
3205
|
changed: only.changed,
|
|
3109
|
-
version
|
|
3206
|
+
version,
|
|
3207
|
+
cursor
|
|
3110
3208
|
});
|
|
3111
3209
|
} else {
|
|
3112
|
-
send({ type: "frame", diffs, version });
|
|
3210
|
+
send({ type: "frame", diffs, version, cursor });
|
|
3113
3211
|
}
|
|
3114
3212
|
};
|
|
3115
3213
|
const scheduleFlush = () => {
|
|
@@ -3122,12 +3220,14 @@ var createSyncConnection = ({
|
|
|
3122
3220
|
flush();
|
|
3123
3221
|
});
|
|
3124
3222
|
};
|
|
3125
|
-
const bufferDiff = (diff, diffVersion) => {
|
|
3223
|
+
const bufferDiff = (diff, diffVersion, cursor) => {
|
|
3126
3224
|
if (pending.length > 0 && pendingVersion !== diffVersion) {
|
|
3127
3225
|
flush();
|
|
3128
3226
|
}
|
|
3129
3227
|
pending.push(diff);
|
|
3130
3228
|
pendingVersion = diffVersion;
|
|
3229
|
+
if (cursor !== undefined)
|
|
3230
|
+
pendingCursor = cursor;
|
|
3131
3231
|
scheduleFlush();
|
|
3132
3232
|
};
|
|
3133
3233
|
const handle = async (raw) => {
|
|
@@ -3203,13 +3303,13 @@ var createSyncConnection = ({
|
|
|
3203
3303
|
params: frame.params,
|
|
3204
3304
|
ctx,
|
|
3205
3305
|
since: frame.since,
|
|
3206
|
-
onDiff: (diff, diffVersion) => {
|
|
3306
|
+
onDiff: (diff, diffVersion, cursor) => {
|
|
3207
3307
|
bufferDiff({
|
|
3208
3308
|
id: frame.id,
|
|
3209
3309
|
added: diff.added,
|
|
3210
3310
|
removed: diff.removed,
|
|
3211
3311
|
changed: diff.changed
|
|
3212
|
-
}, diffVersion);
|
|
3312
|
+
}, diffVersion, cursor);
|
|
3213
3313
|
}
|
|
3214
3314
|
});
|
|
3215
3315
|
subscriptions.set(frame.id, subscription);
|
|
@@ -3220,14 +3320,16 @@ var createSyncConnection = ({
|
|
|
3220
3320
|
added: subscription.catchup.added,
|
|
3221
3321
|
removed: subscription.catchup.removed,
|
|
3222
3322
|
changed: subscription.catchup.changed,
|
|
3223
|
-
version: subscription.version
|
|
3323
|
+
version: subscription.version,
|
|
3324
|
+
cursor: subscription.cursor
|
|
3224
3325
|
});
|
|
3225
3326
|
} else {
|
|
3226
3327
|
send({
|
|
3227
3328
|
type: "snapshot",
|
|
3228
3329
|
id: frame.id,
|
|
3229
3330
|
rows: subscription.initial,
|
|
3230
|
-
version: subscription.version
|
|
3331
|
+
version: subscription.version,
|
|
3332
|
+
cursor: subscription.cursor
|
|
3231
3333
|
});
|
|
3232
3334
|
}
|
|
3233
3335
|
} catch (error) {
|
|
@@ -3304,5 +3406,5 @@ export {
|
|
|
3304
3406
|
CdcConsumerSlowError
|
|
3305
3407
|
};
|
|
3306
3408
|
|
|
3307
|
-
//# debugId=
|
|
3409
|
+
//# debugId=83816548811B9BFD64756E2164756E21
|
|
3308
3410
|
//# sourceMappingURL=index.js.map
|