@omegup/msync 0.1.31 → 0.1.33
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/index.d.ts +6 -1
- package/index.esm.js +64 -41
- package/index.js +65 -40
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -600,6 +600,11 @@ declare const dateDiff: <D, C>({ end, unit, start, }: {
|
|
|
600
600
|
end: Expr<Date, D, C>;
|
|
601
601
|
unit: Expr<"week" | "day" | "month" | "year", D, C>;
|
|
602
602
|
}) => Expr<number, D, C>;
|
|
603
|
+
declare const mapFromPlainDateTime: <D, C>({ plainDate, timezone, }: {
|
|
604
|
+
plainDate: Expr<Date, D, C>;
|
|
605
|
+
timezone: Expr<string, D, C>;
|
|
606
|
+
}) => Expr<Date, D, C>;
|
|
607
|
+
declare const mapToPlainDateTime: <D, C>(date: Expr<Date, D, C>, timezone: Expr<string, D, C>) => Expr<Date, D, C>;
|
|
603
608
|
|
|
604
609
|
declare const ite: {
|
|
605
610
|
<T, D, C = unknown>(cond: Expr<unknown, D, C>, then: Expr<T, D, C>, orelse: Expr<T, D, C>): Expr<T, D, C>;
|
|
@@ -680,5 +685,5 @@ declare const enablePreAndPostImages: <T extends doc>(coll: Collection<T>) => Pr
|
|
|
680
685
|
declare const prepare: (testName?: string) => Promise<MongoClient$1>;
|
|
681
686
|
declare const makeCol: <T extends ID>(docs: readonly OptionalUnlessRequiredId<T>[], database: Db, name?: string) => Promise<Collection<T>>;
|
|
682
687
|
|
|
683
|
-
export { $accumulator, $and, $countDict, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $group_, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertPart, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map0, $map1, $match, $matchDelta, $merge, $merge2, $mergeId, $mergePart, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $reduce, $replaceWith, $set, $simpleInsert, $simpleMerge, $simpleMergePart, $sum, $type, $unwind, $unwindDelta, Expr, Field, Machine, Type, add, and, anyElementTrue, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
|
|
688
|
+
export { $accumulator, $and, $countDict, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $group_, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertPart, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map0, $map1, $match, $matchDelta, $merge, $merge2, $mergeId, $mergePart, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $reduce, $replaceWith, $set, $simpleInsert, $simpleMerge, $simpleMergePart, $sum, $type, $unwind, $unwindDelta, Expr, Field, Machine, Type, add, and, anyElementTrue, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapFromPlainDateTime, mapToPlainDateTime, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
|
|
684
689
|
export type { Accumulators, Arr, AsLiteral, Delta, DeltaAccumulator, DeltaAccumulators, ExactKeys, ExprHKT, Exprs, ExprsExact, ExprsExactHKT, ExprsPart, ID, Loose, Merge, MergeArgs, MergeInto, MergeMapOArgs, Model, MongoTypeNames, N, NoRaw, NullToOBJ, O, OPick, OPickD, Patch, RONoRaw, RORec, RawStages, Rec, Replace, SnapshotStreamExecutionResult, StrKey, Strict, TS, WriteonlyCollection, doc, jsonPrim, notArr };
|
package/index.esm.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { UUID, Timestamp, MongoClient } from 'mongodb';
|
|
2
2
|
import crypto$1 from 'crypto';
|
|
3
3
|
import { canonicalize } from 'json-canonicalize';
|
|
4
|
-
import { SynchronousPromise } from 'synchronous-promise';
|
|
5
4
|
import { writeFile } from 'fs/promises';
|
|
6
5
|
|
|
7
6
|
const asExprRaw = (raw) => ({ get: () => raw });
|
|
@@ -764,6 +763,26 @@ const dateDiff = ({ end, unit, start, }) => asExpr({
|
|
|
764
763
|
},
|
|
765
764
|
}),
|
|
766
765
|
});
|
|
766
|
+
const mapFromPlainDateTime = ({ plainDate, timezone, }) => asExpr({
|
|
767
|
+
raw: f => asExprRaw({
|
|
768
|
+
$dateFromString: {
|
|
769
|
+
dateString: {
|
|
770
|
+
$dateToString: { date: plainDate.raw(f).get(), timezone: 'GMT' },
|
|
771
|
+
},
|
|
772
|
+
timezone: timezone.raw(f).get(),
|
|
773
|
+
},
|
|
774
|
+
}),
|
|
775
|
+
});
|
|
776
|
+
const mapToPlainDateTime = (date, timezone) => asExpr({
|
|
777
|
+
raw: f => asExprRaw({
|
|
778
|
+
$dateFromString: {
|
|
779
|
+
$dateToString: {
|
|
780
|
+
date: date.raw(f).get(),
|
|
781
|
+
timezone: timezone.raw(f).get(),
|
|
782
|
+
},
|
|
783
|
+
},
|
|
784
|
+
}),
|
|
785
|
+
});
|
|
767
786
|
|
|
768
787
|
const range = (start, end, step) => asExpr({
|
|
769
788
|
raw: f => asExprRaw({ $range: [start.raw(f).get(), end.raw(f).get(), step?.raw(f).get() ?? 1] }),
|
|
@@ -1312,7 +1331,7 @@ const restart = (sources) => {
|
|
|
1312
1331
|
};
|
|
1313
1332
|
const race = (sources) => {
|
|
1314
1333
|
const promises = Object.values(map(sources, ({ next }, key) => next.then(frame => ({ key, frame }), error => new Error(error))));
|
|
1315
|
-
return
|
|
1334
|
+
return Promise.any(promises).then((result) => {
|
|
1316
1335
|
if (result instanceof Error) {
|
|
1317
1336
|
throw result;
|
|
1318
1337
|
}
|
|
@@ -1335,28 +1354,31 @@ const nextWinner = (previousWinner, previousWinnerNextFrame, sources, interrupt)
|
|
|
1335
1354
|
return race(sources);
|
|
1336
1355
|
};
|
|
1337
1356
|
|
|
1357
|
+
const makeSelect = (winner, nextFrame, interrupt) => sources => nextWinner(winner, nextFrame, sources, interrupt);
|
|
1358
|
+
const makeContinuation = (sources, winner, interrupt, hooks) => () => {
|
|
1359
|
+
const { frame, key } = winner;
|
|
1360
|
+
const result = frame.cont();
|
|
1361
|
+
hooks?.start?.(frame, result);
|
|
1362
|
+
return mergeIterators({
|
|
1363
|
+
sources: patch(sources, key, result),
|
|
1364
|
+
interrupt,
|
|
1365
|
+
select: makeSelect(winner, result.next, interrupt),
|
|
1366
|
+
hooks,
|
|
1367
|
+
});
|
|
1368
|
+
};
|
|
1369
|
+
const makeReiterate = (sources, interrupt, hooks) => (winner) => {
|
|
1370
|
+
const { frame, key } = winner;
|
|
1371
|
+
return {
|
|
1372
|
+
cont: makeContinuation(sources, winner, interrupt, hooks),
|
|
1373
|
+
data: frame.data,
|
|
1374
|
+
info: { key, value: frame.info, job: frame.info.job },
|
|
1375
|
+
};
|
|
1376
|
+
};
|
|
1338
1377
|
const mergeIterators = (params) => {
|
|
1339
1378
|
const { sources, interrupt, select = race, hooks } = params;
|
|
1340
|
-
const reiterate = (winner) => {
|
|
1341
|
-
const { frame, key } = winner;
|
|
1342
|
-
return {
|
|
1343
|
-
cont: () => {
|
|
1344
|
-
const result = frame.cont();
|
|
1345
|
-
hooks?.start?.(frame, result);
|
|
1346
|
-
return mergeIterators({
|
|
1347
|
-
sources: patch(sources, key, result),
|
|
1348
|
-
interrupt,
|
|
1349
|
-
select: sources => nextWinner(winner, result.next, sources, interrupt),
|
|
1350
|
-
hooks,
|
|
1351
|
-
});
|
|
1352
|
-
},
|
|
1353
|
-
data: frame.data,
|
|
1354
|
-
info: { key, value: frame.info, job: frame.info.job },
|
|
1355
|
-
};
|
|
1356
|
-
};
|
|
1357
1379
|
return {
|
|
1358
1380
|
stop: () => mergeIterators({ sources: restart(sources), interrupt, select, hooks }),
|
|
1359
|
-
next: select(sources).then(
|
|
1381
|
+
next: select(sources).then(makeReiterate(sources, interrupt, hooks)),
|
|
1360
1382
|
clear: async () => {
|
|
1361
1383
|
for (const key in sources) {
|
|
1362
1384
|
await sources[key].clear();
|
|
@@ -1660,6 +1682,7 @@ async function* tailOplog(db) {
|
|
|
1660
1682
|
try {
|
|
1661
1683
|
for await (const docs of cursor) {
|
|
1662
1684
|
for (const doc of docs.op === 'c' ? docs.o['applyOps'] : [docs]) {
|
|
1685
|
+
doc.ts = docs.ts;
|
|
1663
1686
|
if (doc.op === 'i' || '_id' in doc.o) {
|
|
1664
1687
|
const fields = new Set(Object.keys(doc.o));
|
|
1665
1688
|
fields.delete('_id');
|
|
@@ -1730,7 +1753,7 @@ const loop = async (db) => {
|
|
|
1730
1753
|
if (!events) {
|
|
1731
1754
|
log('notifying watchers of oplog loop restart');
|
|
1732
1755
|
for (const m of watchers.values()) {
|
|
1733
|
-
for (const { cb } of m.values()) {
|
|
1756
|
+
for (const { cb } of [...m.values()]) {
|
|
1734
1757
|
cb(null);
|
|
1735
1758
|
}
|
|
1736
1759
|
}
|
|
@@ -1740,9 +1763,10 @@ const loop = async (db) => {
|
|
|
1740
1763
|
const m = watchers.get(doc.ns);
|
|
1741
1764
|
if (!m)
|
|
1742
1765
|
continue;
|
|
1743
|
-
for (const { cb, keys } of m.values()) {
|
|
1766
|
+
for (const { cb, keys, rem } of [...m.values()]) {
|
|
1744
1767
|
if (!keys || keys.some(k => fields.has(k))) {
|
|
1745
1768
|
cb(doc);
|
|
1769
|
+
rem();
|
|
1746
1770
|
}
|
|
1747
1771
|
}
|
|
1748
1772
|
}
|
|
@@ -1754,16 +1778,17 @@ const register = (coll, keys, cb) => {
|
|
|
1754
1778
|
if (!m)
|
|
1755
1779
|
watchers.set(ns, (m = new Map()));
|
|
1756
1780
|
const id = crypto.randomUUID();
|
|
1757
|
-
|
|
1758
|
-
if (!running) {
|
|
1759
|
-
running = true;
|
|
1760
|
-
loop(coll.s.db);
|
|
1761
|
-
}
|
|
1762
|
-
return () => {
|
|
1781
|
+
const rem = () => {
|
|
1763
1782
|
m.delete(id);
|
|
1764
1783
|
if (m.size === 0)
|
|
1765
1784
|
watchers.delete(ns);
|
|
1766
1785
|
};
|
|
1786
|
+
m.set(id, { cb, keys, rem });
|
|
1787
|
+
if (!running) {
|
|
1788
|
+
running = true;
|
|
1789
|
+
loop(coll.s.db);
|
|
1790
|
+
}
|
|
1791
|
+
return rem;
|
|
1767
1792
|
};
|
|
1768
1793
|
let maxKeysRemoved = null;
|
|
1769
1794
|
const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, streamName) => {
|
|
@@ -1772,23 +1797,21 @@ const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, stre
|
|
|
1772
1797
|
.collection(x.name)
|
|
1773
1798
|
.updateMany({ touchedAt: maxTimestamp }, [{ $set: { touchedAt: '$$CLUSTER_TIME' } }]))).then(() => { }));
|
|
1774
1799
|
const projection = { ...(p ? mapExactToObject(p, v => v) : {}), deletedAt: 1 };
|
|
1775
|
-
let
|
|
1776
|
-
|
|
1777
|
-
const close = register(collection, p ? Object.keys(projection) : null, doc => {
|
|
1800
|
+
let notify = makePromise();
|
|
1801
|
+
register(collection, p ? Object.keys(projection) : null, doc => {
|
|
1778
1802
|
log(streamName, 'change detected', doc);
|
|
1779
|
-
resolve(doc);
|
|
1780
|
-
close();
|
|
1803
|
+
notify.resolve(doc);
|
|
1781
1804
|
});
|
|
1782
1805
|
return {
|
|
1783
1806
|
tryNext: async () => {
|
|
1784
|
-
const doc = await promise;
|
|
1807
|
+
const doc = await notify.promise;
|
|
1785
1808
|
const start = Date.now();
|
|
1786
1809
|
if (doc)
|
|
1787
1810
|
await waitUntilStablePast(collection.s.db, doc.ts);
|
|
1788
1811
|
log(streamName, 'stable past took', Date.now() - start);
|
|
1789
1812
|
return doc ?? {};
|
|
1790
1813
|
},
|
|
1791
|
-
close: async () =>
|
|
1814
|
+
close: async () => { },
|
|
1792
1815
|
};
|
|
1793
1816
|
};
|
|
1794
1817
|
|
|
@@ -1913,7 +1936,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
1913
1936
|
params: x.params,
|
|
1914
1937
|
})),
|
|
1915
1938
|
};
|
|
1916
|
-
const step0 = () =>
|
|
1939
|
+
const step0 = () => Promise.resolve(next(step1, 'empty new collection'));
|
|
1917
1940
|
const stop = withStop(step0);
|
|
1918
1941
|
const step1 = async () => {
|
|
1919
1942
|
log('reset collection', streamName, `db['${snapshotCollection.collectionName}'].updateMany( updated: true }, { $set: { updated: false, after: null } })`);
|
|
@@ -2012,7 +2035,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
2012
2035
|
const start = Date.now();
|
|
2013
2036
|
const res = await snapshotCollection.deleteMany({ updated: true, after: null, before: null });
|
|
2014
2037
|
log('deleting from cloned into new collection', Date.now() - start, res, `db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null, before: null })`);
|
|
2015
|
-
return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation');
|
|
2038
|
+
return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation', () => stream.close());
|
|
2016
2039
|
};
|
|
2017
2040
|
const makeStream = () => makeWatchStream(view, streamName);
|
|
2018
2041
|
const step4 = ({ result, ts, stream }) => async () => {
|
|
@@ -2036,7 +2059,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
2036
2059
|
.with(stages).stages,
|
|
2037
2060
|
}), false, start);
|
|
2038
2061
|
stages.at(-1).$merge.into.coll;
|
|
2039
|
-
return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated'
|
|
2062
|
+
return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated');
|
|
2040
2063
|
};
|
|
2041
2064
|
const step5 = (l) => async () => {
|
|
2042
2065
|
log(streamName, `remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
|
|
@@ -2079,7 +2102,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
2079
2102
|
: step8({ ...l, nextRes: l.stream.tryNext() })), 'wait for change');
|
|
2080
2103
|
};
|
|
2081
2104
|
return skip
|
|
2082
|
-
? withStop(() =>
|
|
2105
|
+
? withStop(() => Promise.resolve(next(step3(null), 'clone into new collection')))
|
|
2083
2106
|
: stop;
|
|
2084
2107
|
};
|
|
2085
2108
|
const hasBefore = root().of('before').has($ne(null));
|
|
@@ -2147,7 +2170,7 @@ const executes$1 = (view, input, streamName, needs) => {
|
|
|
2147
2170
|
params: x.params,
|
|
2148
2171
|
})),
|
|
2149
2172
|
};
|
|
2150
|
-
const step0 = () =>
|
|
2173
|
+
const step0 = () => Promise.resolve(next(step1, 'get last update'));
|
|
2151
2174
|
const stop = withStop(step0);
|
|
2152
2175
|
const step1 = async () => {
|
|
2153
2176
|
log('creating indexes');
|
|
@@ -2242,4 +2265,4 @@ const executes = (view, input, needs) => {
|
|
|
2242
2265
|
};
|
|
2243
2266
|
const single = (view, needs = {}) => pipe(input => executes(view, input, needs), emptyDelta(), concatDelta, emptyDelta);
|
|
2244
2267
|
|
|
2245
|
-
export { $accumulator, $and, $countDict, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $group_, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertPart, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map0, $map1, $match, $matchDelta, $merge, $merge2, $mergeId, $mergePart, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $reduce, $replaceWith, $set, $simpleInsert, $simpleMerge, $simpleMergePart, $sum, $type, $unwind, $unwindDelta, Field, Machine, add, and, anyElementTrue, array, ceil, comp, concat$1 as concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first$1 as first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
|
|
2268
|
+
export { $accumulator, $and, $countDict, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $group_, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertPart, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map0, $map1, $match, $matchDelta, $merge, $merge2, $mergeId, $mergePart, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $reduce, $replaceWith, $set, $simpleInsert, $simpleMerge, $simpleMergePart, $sum, $type, $unwind, $unwindDelta, Field, Machine, add, and, anyElementTrue, array, ceil, comp, concat$1 as concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first$1 as first, firstSure, floor, from, func, getWhenMatched, getWhenMatchedForMerge, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapFromPlainDateTime, mapToPlainDateTime, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, not, notNull, now, or, pair, prepare, rand, range, regex, root, set, setField, single, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
|
package/index.js
CHANGED
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
var mongodb = require('mongodb');
|
|
4
4
|
var crypto$1 = require('crypto');
|
|
5
5
|
var jsonCanonicalize = require('json-canonicalize');
|
|
6
|
-
var synchronousPromise = require('synchronous-promise');
|
|
7
6
|
var promises = require('fs/promises');
|
|
8
7
|
|
|
9
8
|
const asExprRaw = (raw) => ({ get: () => raw });
|
|
@@ -766,6 +765,26 @@ const dateDiff = ({ end, unit, start, }) => asExpr({
|
|
|
766
765
|
},
|
|
767
766
|
}),
|
|
768
767
|
});
|
|
768
|
+
const mapFromPlainDateTime = ({ plainDate, timezone, }) => asExpr({
|
|
769
|
+
raw: f => asExprRaw({
|
|
770
|
+
$dateFromString: {
|
|
771
|
+
dateString: {
|
|
772
|
+
$dateToString: { date: plainDate.raw(f).get(), timezone: 'GMT' },
|
|
773
|
+
},
|
|
774
|
+
timezone: timezone.raw(f).get(),
|
|
775
|
+
},
|
|
776
|
+
}),
|
|
777
|
+
});
|
|
778
|
+
const mapToPlainDateTime = (date, timezone) => asExpr({
|
|
779
|
+
raw: f => asExprRaw({
|
|
780
|
+
$dateFromString: {
|
|
781
|
+
$dateToString: {
|
|
782
|
+
date: date.raw(f).get(),
|
|
783
|
+
timezone: timezone.raw(f).get(),
|
|
784
|
+
},
|
|
785
|
+
},
|
|
786
|
+
}),
|
|
787
|
+
});
|
|
769
788
|
|
|
770
789
|
const range = (start, end, step) => asExpr({
|
|
771
790
|
raw: f => asExprRaw({ $range: [start.raw(f).get(), end.raw(f).get(), step?.raw(f).get() ?? 1] }),
|
|
@@ -1314,7 +1333,7 @@ const restart = (sources) => {
|
|
|
1314
1333
|
};
|
|
1315
1334
|
const race = (sources) => {
|
|
1316
1335
|
const promises = Object.values(map(sources, ({ next }, key) => next.then(frame => ({ key, frame }), error => new Error(error))));
|
|
1317
|
-
return
|
|
1336
|
+
return Promise.any(promises).then((result) => {
|
|
1318
1337
|
if (result instanceof Error) {
|
|
1319
1338
|
throw result;
|
|
1320
1339
|
}
|
|
@@ -1337,28 +1356,31 @@ const nextWinner = (previousWinner, previousWinnerNextFrame, sources, interrupt)
|
|
|
1337
1356
|
return race(sources);
|
|
1338
1357
|
};
|
|
1339
1358
|
|
|
1359
|
+
const makeSelect = (winner, nextFrame, interrupt) => sources => nextWinner(winner, nextFrame, sources, interrupt);
|
|
1360
|
+
const makeContinuation = (sources, winner, interrupt, hooks) => () => {
|
|
1361
|
+
const { frame, key } = winner;
|
|
1362
|
+
const result = frame.cont();
|
|
1363
|
+
hooks?.start?.(frame, result);
|
|
1364
|
+
return mergeIterators({
|
|
1365
|
+
sources: patch(sources, key, result),
|
|
1366
|
+
interrupt,
|
|
1367
|
+
select: makeSelect(winner, result.next, interrupt),
|
|
1368
|
+
hooks,
|
|
1369
|
+
});
|
|
1370
|
+
};
|
|
1371
|
+
const makeReiterate = (sources, interrupt, hooks) => (winner) => {
|
|
1372
|
+
const { frame, key } = winner;
|
|
1373
|
+
return {
|
|
1374
|
+
cont: makeContinuation(sources, winner, interrupt, hooks),
|
|
1375
|
+
data: frame.data,
|
|
1376
|
+
info: { key, value: frame.info, job: frame.info.job },
|
|
1377
|
+
};
|
|
1378
|
+
};
|
|
1340
1379
|
const mergeIterators = (params) => {
|
|
1341
1380
|
const { sources, interrupt, select = race, hooks } = params;
|
|
1342
|
-
const reiterate = (winner) => {
|
|
1343
|
-
const { frame, key } = winner;
|
|
1344
|
-
return {
|
|
1345
|
-
cont: () => {
|
|
1346
|
-
const result = frame.cont();
|
|
1347
|
-
hooks?.start?.(frame, result);
|
|
1348
|
-
return mergeIterators({
|
|
1349
|
-
sources: patch(sources, key, result),
|
|
1350
|
-
interrupt,
|
|
1351
|
-
select: sources => nextWinner(winner, result.next, sources, interrupt),
|
|
1352
|
-
hooks,
|
|
1353
|
-
});
|
|
1354
|
-
},
|
|
1355
|
-
data: frame.data,
|
|
1356
|
-
info: { key, value: frame.info, job: frame.info.job },
|
|
1357
|
-
};
|
|
1358
|
-
};
|
|
1359
1381
|
return {
|
|
1360
1382
|
stop: () => mergeIterators({ sources: restart(sources), interrupt, select, hooks }),
|
|
1361
|
-
next: select(sources).then(
|
|
1383
|
+
next: select(sources).then(makeReiterate(sources, interrupt, hooks)),
|
|
1362
1384
|
clear: async () => {
|
|
1363
1385
|
for (const key in sources) {
|
|
1364
1386
|
await sources[key].clear();
|
|
@@ -1662,6 +1684,7 @@ async function* tailOplog(db) {
|
|
|
1662
1684
|
try {
|
|
1663
1685
|
for await (const docs of cursor) {
|
|
1664
1686
|
for (const doc of docs.op === 'c' ? docs.o['applyOps'] : [docs]) {
|
|
1687
|
+
doc.ts = docs.ts;
|
|
1665
1688
|
if (doc.op === 'i' || '_id' in doc.o) {
|
|
1666
1689
|
const fields = new Set(Object.keys(doc.o));
|
|
1667
1690
|
fields.delete('_id');
|
|
@@ -1732,7 +1755,7 @@ const loop = async (db) => {
|
|
|
1732
1755
|
if (!events) {
|
|
1733
1756
|
log('notifying watchers of oplog loop restart');
|
|
1734
1757
|
for (const m of watchers.values()) {
|
|
1735
|
-
for (const { cb } of m.values()) {
|
|
1758
|
+
for (const { cb } of [...m.values()]) {
|
|
1736
1759
|
cb(null);
|
|
1737
1760
|
}
|
|
1738
1761
|
}
|
|
@@ -1742,9 +1765,10 @@ const loop = async (db) => {
|
|
|
1742
1765
|
const m = watchers.get(doc.ns);
|
|
1743
1766
|
if (!m)
|
|
1744
1767
|
continue;
|
|
1745
|
-
for (const { cb, keys } of m.values()) {
|
|
1768
|
+
for (const { cb, keys, rem } of [...m.values()]) {
|
|
1746
1769
|
if (!keys || keys.some(k => fields.has(k))) {
|
|
1747
1770
|
cb(doc);
|
|
1771
|
+
rem();
|
|
1748
1772
|
}
|
|
1749
1773
|
}
|
|
1750
1774
|
}
|
|
@@ -1756,16 +1780,17 @@ const register = (coll, keys, cb) => {
|
|
|
1756
1780
|
if (!m)
|
|
1757
1781
|
watchers.set(ns, (m = new Map()));
|
|
1758
1782
|
const id = crypto.randomUUID();
|
|
1759
|
-
|
|
1760
|
-
if (!running) {
|
|
1761
|
-
running = true;
|
|
1762
|
-
loop(coll.s.db);
|
|
1763
|
-
}
|
|
1764
|
-
return () => {
|
|
1783
|
+
const rem = () => {
|
|
1765
1784
|
m.delete(id);
|
|
1766
1785
|
if (m.size === 0)
|
|
1767
1786
|
watchers.delete(ns);
|
|
1768
1787
|
};
|
|
1788
|
+
m.set(id, { cb, keys, rem });
|
|
1789
|
+
if (!running) {
|
|
1790
|
+
running = true;
|
|
1791
|
+
loop(coll.s.db);
|
|
1792
|
+
}
|
|
1793
|
+
return rem;
|
|
1769
1794
|
};
|
|
1770
1795
|
let maxKeysRemoved = null;
|
|
1771
1796
|
const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, streamName) => {
|
|
@@ -1774,23 +1799,21 @@ const makeWatchStream = async ({ collection, projection: p, hardMatch: m }, stre
|
|
|
1774
1799
|
.collection(x.name)
|
|
1775
1800
|
.updateMany({ touchedAt: maxTimestamp }, [{ $set: { touchedAt: '$$CLUSTER_TIME' } }]))).then(() => { }));
|
|
1776
1801
|
const projection = { ...(p ? mapExactToObject(p, v => v) : {}), deletedAt: 1 };
|
|
1777
|
-
let
|
|
1778
|
-
|
|
1779
|
-
const close = register(collection, p ? Object.keys(projection) : null, doc => {
|
|
1802
|
+
let notify = makePromise();
|
|
1803
|
+
register(collection, p ? Object.keys(projection) : null, doc => {
|
|
1780
1804
|
log(streamName, 'change detected', doc);
|
|
1781
|
-
resolve(doc);
|
|
1782
|
-
close();
|
|
1805
|
+
notify.resolve(doc);
|
|
1783
1806
|
});
|
|
1784
1807
|
return {
|
|
1785
1808
|
tryNext: async () => {
|
|
1786
|
-
const doc = await promise;
|
|
1809
|
+
const doc = await notify.promise;
|
|
1787
1810
|
const start = Date.now();
|
|
1788
1811
|
if (doc)
|
|
1789
1812
|
await waitUntilStablePast(collection.s.db, doc.ts);
|
|
1790
1813
|
log(streamName, 'stable past took', Date.now() - start);
|
|
1791
1814
|
return doc ?? {};
|
|
1792
1815
|
},
|
|
1793
|
-
close: async () =>
|
|
1816
|
+
close: async () => { },
|
|
1794
1817
|
};
|
|
1795
1818
|
};
|
|
1796
1819
|
|
|
@@ -1915,7 +1938,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
1915
1938
|
params: x.params,
|
|
1916
1939
|
})),
|
|
1917
1940
|
};
|
|
1918
|
-
const step0 = () =>
|
|
1941
|
+
const step0 = () => Promise.resolve(next(step1, 'empty new collection'));
|
|
1919
1942
|
const stop = withStop(step0);
|
|
1920
1943
|
const step1 = async () => {
|
|
1921
1944
|
log('reset collection', streamName, `db['${snapshotCollection.collectionName}'].updateMany( updated: true }, { $set: { updated: false, after: null } })`);
|
|
@@ -2014,7 +2037,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
2014
2037
|
const start = Date.now();
|
|
2015
2038
|
const res = await snapshotCollection.deleteMany({ updated: true, after: null, before: null });
|
|
2016
2039
|
log('deleting from cloned into new collection', Date.now() - start, res, `db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null, before: null })`);
|
|
2017
|
-
return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation');
|
|
2040
|
+
return next(step4({ result: r, ts: lastTS?.ts, stream }), 'run the aggregation', () => stream.close());
|
|
2018
2041
|
};
|
|
2019
2042
|
const makeStream = () => makeWatchStream(view, streamName);
|
|
2020
2043
|
const step4 = ({ result, ts, stream }) => async () => {
|
|
@@ -2038,7 +2061,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
2038
2061
|
.with(stages).stages,
|
|
2039
2062
|
}), false, start);
|
|
2040
2063
|
stages.at(-1).$merge.into.coll;
|
|
2041
|
-
return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated'
|
|
2064
|
+
return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream, nextRes, first }), 'remove handled deleted updated');
|
|
2042
2065
|
};
|
|
2043
2066
|
const step5 = (l) => async () => {
|
|
2044
2067
|
log(streamName, `remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
|
|
@@ -2081,7 +2104,7 @@ const executes$2 = (view, input, streamName, skip = false, after, needs = {}) =>
|
|
|
2081
2104
|
: step8({ ...l, nextRes: l.stream.tryNext() })), 'wait for change');
|
|
2082
2105
|
};
|
|
2083
2106
|
return skip
|
|
2084
|
-
? withStop(() =>
|
|
2107
|
+
? withStop(() => Promise.resolve(next(step3(null), 'clone into new collection')))
|
|
2085
2108
|
: stop;
|
|
2086
2109
|
};
|
|
2087
2110
|
const hasBefore = root().of('before').has($ne(null));
|
|
@@ -2149,7 +2172,7 @@ const executes$1 = (view, input, streamName, needs) => {
|
|
|
2149
2172
|
params: x.params,
|
|
2150
2173
|
})),
|
|
2151
2174
|
};
|
|
2152
|
-
const step0 = () =>
|
|
2175
|
+
const step0 = () => Promise.resolve(next(step1, 'get last update'));
|
|
2153
2176
|
const stop = withStop(step0);
|
|
2154
2177
|
const step1 = async () => {
|
|
2155
2178
|
log('creating indexes');
|
|
@@ -2344,6 +2367,8 @@ exports.lt = lt;
|
|
|
2344
2367
|
exports.lte = lte;
|
|
2345
2368
|
exports.makeCol = makeCol;
|
|
2346
2369
|
exports.map1 = map1;
|
|
2370
|
+
exports.mapFromPlainDateTime = mapFromPlainDateTime;
|
|
2371
|
+
exports.mapToPlainDateTime = mapToPlainDateTime;
|
|
2347
2372
|
exports.mapVal = mapVal;
|
|
2348
2373
|
exports.max = max;
|
|
2349
2374
|
exports.maxDate = maxDate;
|