@omegup/msync 0.0.47 → 0.0.49
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 +19 -10
- package/index.esm.js +45 -28
- package/index.js +46 -27
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -27,7 +27,6 @@ declare const Predicate: unique symbol;
|
|
|
27
27
|
interface Predicate<in V> {
|
|
28
28
|
[Type]?(x: typeof Predicate, _: V): void;
|
|
29
29
|
raw: PredicateRaw;
|
|
30
|
-
expr: <D extends O, C>(field: Field<D, V, C>) => Expr<boolean, D, C>;
|
|
31
30
|
}
|
|
32
31
|
|
|
33
32
|
declare class Field<in R, out V, in C = unknown> {
|
|
@@ -629,14 +628,24 @@ declare const wrap: <Result>(root: Machine<Result>) => Machine<Result>;
|
|
|
629
628
|
declare const $eq: <T extends unknown>(operand: rawItem & T) => Predicate<T>;
|
|
630
629
|
declare const $ne: <T extends unknown>(operand: rawItem & T) => Predicate<T>;
|
|
631
630
|
type Numeric = number | Timestamp | Date;
|
|
632
|
-
declare const comp: <D2 extends Numeric =
|
|
633
|
-
declare const $gt: <T extends
|
|
634
|
-
declare const $gtTs: <T extends
|
|
635
|
-
declare const $gteTs: <T extends
|
|
636
|
-
declare const $lt: <T extends
|
|
637
|
-
declare const dateLt: <T extends
|
|
638
|
-
declare const $gte: <T extends
|
|
639
|
-
declare const $lte: <T extends
|
|
631
|
+
declare const comp: <D2 extends Numeric = Numeric>(op: "$lte" | "$gte" | "$lt" | "$gt") => <T extends Numeric>(operand: rawItem & D2) => Predicate<D2>;
|
|
632
|
+
declare const $gt: <T extends Numeric>(operand: rawItem & Numeric) => Predicate<Numeric>;
|
|
633
|
+
declare const $gtTs: <T extends Numeric>(operand: rawItem & Timestamp) => Predicate<Timestamp>;
|
|
634
|
+
declare const $gteTs: <T extends Numeric>(operand: rawItem & Timestamp) => Predicate<Timestamp>;
|
|
635
|
+
declare const $lt: <T extends Numeric>(operand: rawItem & number) => Predicate<number>;
|
|
636
|
+
declare const dateLt: <T extends Numeric>(operand: rawItem & Date) => Predicate<Date>;
|
|
637
|
+
declare const $gte: <T extends Numeric>(operand: rawItem & number) => Predicate<number>;
|
|
638
|
+
declare const $lte: <T extends Numeric>(operand: rawItem & number) => Predicate<number>;
|
|
639
|
+
type MongoTypes = {
|
|
640
|
+
number: number;
|
|
641
|
+
array: readonly rawItem[];
|
|
642
|
+
string: string;
|
|
643
|
+
object: RawObj;
|
|
644
|
+
[i: number]: unknown;
|
|
645
|
+
};
|
|
646
|
+
type MongoTypeNames = keyof MongoTypes;
|
|
647
|
+
declare const $type: <T extends keyof MongoTypes>(operand: rawItem & readonly T[]) => Predicate<N | MongoTypes[T]>;
|
|
648
|
+
declare const $exists: <T extends keyof MongoTypes>(operand: rawItem & boolean) => Predicate<unknown>;
|
|
640
649
|
|
|
641
650
|
declare const $expr: <D extends O, C>(expr: Expr<boolean, D, C>) => Query<D, C>;
|
|
642
651
|
|
|
@@ -667,4 +676,4 @@ declare const enablePreAndPostImages: <T extends doc>(coll: Collection<T>) => Pr
|
|
|
667
676
|
declare const prepare: (testName?: string) => Promise<MongoClient$1>;
|
|
668
677
|
declare const makeCol: <T extends ID>(docs: readonly OptionalUnlessRequiredId<T>[], database: Db, name?: string) => Promise<Collection<T>>;
|
|
669
678
|
|
|
670
|
-
export { $accumulator, $and, $countDict, $entries, $eq, $expr, $getField, $group, $groupId, $groupMerge, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map1, $match, $matchDelta, $merge, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $replaceWith, $set, $simpleInsert, $simpleMerge, $sum, $unwind, $unwindDelta, type Accumulators, type Arr, type AsLiteral, type Delta, type DeltaAccumulator, type DeltaAccumulators, Expr, type ExprHKT, type Exprs, type ExprsExact, type ExprsExactHKT, type ExprsPart, Field, type ID, type Loose, Machine, type Merge, type MergeArgs, type MergeInto, type MergeMapOArgs, type Model, type N, type NoRaw, type NullToOBJ, type O, type OPick, type OPickD, type RONoRaw, type RORec, type RawStages, type Rec, type Replace, type SnapshotStreamExecutionResult, type StrKey, type Strict, type TS, Type, type WriteonlyCollection, add, and, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, type doc, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first, firstSure, floor, from, func, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, type notArr, notNull, now, or, pair, prepare, rand, range, root, set, setField, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
|
|
679
|
+
export { $accumulator, $and, $countDict, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map1, $match, $matchDelta, $merge, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $replaceWith, $set, $simpleInsert, $simpleMerge, $sum, $type, $unwind, $unwindDelta, type Accumulators, type Arr, type AsLiteral, type Delta, type DeltaAccumulator, type DeltaAccumulators, Expr, type ExprHKT, type Exprs, type ExprsExact, type ExprsExactHKT, type ExprsPart, Field, type ID, type Loose, Machine, type Merge, type MergeArgs, type MergeInto, type MergeMapOArgs, type Model, type MongoTypeNames, type N, type NoRaw, type NullToOBJ, type O, type OPick, type OPickD, type RONoRaw, type RORec, type RawStages, type Rec, type Replace, type SnapshotStreamExecutionResult, type StrKey, type Strict, type TS, Type, type WriteonlyCollection, add, and, array, ceil, comp, concat, concatArray, createIndex, ctx, current, dateAdd, dateDiff, dateLt, datePart, dayAndMonthPart, divide, type doc, enablePreAndPostImages, eq, eqTyped, except, exprMapVal, field, fieldF, fieldM, filter, filterDefined, first, firstSure, floor, from, func, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, type notArr, notNull, now, or, pair, prepare, rand, range, root, set, setField, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
|
package/index.esm.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { UUID, MongoClient } from 'mongodb';
|
|
2
2
|
import { SynchronousPromise } from 'synchronous-promise';
|
|
3
3
|
import crypto$1 from 'crypto';
|
|
4
|
-
import { log as log$1 } from 'console';
|
|
5
4
|
import { writeFile } from 'fs/promises';
|
|
6
5
|
|
|
7
6
|
const asExprRaw = (raw) => ({ get: () => raw });
|
|
@@ -885,9 +884,6 @@ const $map = (ex, map) => $map1(ex, i => map(i.expr()));
|
|
|
885
884
|
const operator = () => (op) => (operand) => {
|
|
886
885
|
return {
|
|
887
886
|
raw: { [op]: operand },
|
|
888
|
-
expr: (field) => asExpr({
|
|
889
|
-
raw: f => asExprRaw({ [op]: [$ifNull(field.expr(), nil).raw(f).get(), operand] }),
|
|
890
|
-
}),
|
|
891
887
|
};
|
|
892
888
|
};
|
|
893
889
|
|
|
@@ -902,6 +898,8 @@ const $lt = comp('$lt');
|
|
|
902
898
|
const dateLt = comp('$lt');
|
|
903
899
|
const $gte = comp('$gte');
|
|
904
900
|
const $lte = comp('$lte');
|
|
901
|
+
const $type = operator()('$type');
|
|
902
|
+
const $exists = operator()('$exists');
|
|
905
903
|
|
|
906
904
|
const $expr = (expr) => ({
|
|
907
905
|
raw: f => ({ $expr: expr.raw(f).get() }),
|
|
@@ -1384,16 +1382,16 @@ const replace = (s) => s.replace(/\{"\$timestamp":"(\d+)"\}/g, (_, d) => T(d));
|
|
|
1384
1382
|
const json = (a) => replace(JSON.stringify(a));
|
|
1385
1383
|
const log = (...args) => console.log(new Date(), ...args.map(a => (typeof a === 'function' ? a(replace) : a && typeof a === 'object' ? json(a) : a)));
|
|
1386
1384
|
|
|
1387
|
-
const aggregate = (input, snapshot = true, start = Date.now()) => input(({ coll, input }) => {
|
|
1385
|
+
const aggregate = (streamName, input, snapshot = true, start = Date.now()) => input(({ coll, input }) => {
|
|
1388
1386
|
const req = {
|
|
1389
1387
|
aggregate: coll.collectionName,
|
|
1390
1388
|
pipeline: input,
|
|
1391
1389
|
cursor: {},
|
|
1392
1390
|
...(snapshot && { readConcern: { level: 'snapshot' } }),
|
|
1393
1391
|
};
|
|
1394
|
-
log('exec', req);
|
|
1392
|
+
log('exec', streamName, req);
|
|
1395
1393
|
return coll.s.db.command(req).then(result => {
|
|
1396
|
-
log('execed', req, result, 'took', Date.now() - start);
|
|
1394
|
+
log('execed', streamName, req, result, 'took', Date.now() - start);
|
|
1397
1395
|
return result;
|
|
1398
1396
|
}, err => {
|
|
1399
1397
|
log('err', req, err);
|
|
@@ -1445,11 +1443,19 @@ const makeWatchStream = (db, { collection, projection: p, hardMatch: m }, startA
|
|
|
1445
1443
|
},
|
|
1446
1444
|
});
|
|
1447
1445
|
pipeline.push({
|
|
1448
|
-
$
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1446
|
+
$replaceWith: {
|
|
1447
|
+
ts: {
|
|
1448
|
+
$cond: {
|
|
1449
|
+
if: {
|
|
1450
|
+
$or: [
|
|
1451
|
+
{ $ne: ['$fullDocument', '$fullDocumentBeforeChange'] },
|
|
1452
|
+
{ $and: changeKeys.map(k => ({ $eq: [k, null] })) },
|
|
1453
|
+
],
|
|
1454
|
+
},
|
|
1455
|
+
then: '$clusterTime',
|
|
1456
|
+
else: null,
|
|
1457
|
+
},
|
|
1458
|
+
},
|
|
1453
1459
|
},
|
|
1454
1460
|
});
|
|
1455
1461
|
const stream = db.collection(collection.collectionName).watch(pipeline, {
|
|
@@ -1462,7 +1468,7 @@ const makeWatchStream = (db, { collection, projection: p, hardMatch: m }, startA
|
|
|
1462
1468
|
if (doc)
|
|
1463
1469
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
1464
1470
|
if (doc)
|
|
1465
|
-
log
|
|
1471
|
+
log('detected', streamName, collection.collectionName, doc);
|
|
1466
1472
|
return doc;
|
|
1467
1473
|
};
|
|
1468
1474
|
return { tryNext, close: () => stream.close() };
|
|
@@ -1484,8 +1490,9 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1484
1490
|
streamNames[streamName] = hash;
|
|
1485
1491
|
else if (streamNames[streamName] != hash)
|
|
1486
1492
|
throw new Error(`streamName ${streamName} already used`);
|
|
1487
|
-
const { collection, projection, hardMatch, match } = view;
|
|
1488
|
-
const removeNotYetSynchronizedFields = Object.values(mapExactToObject(projection, (_, k) => k.startsWith('_') ? root().of(k).has($
|
|
1493
|
+
const { collection, projection, hardMatch: pre, match } = view;
|
|
1494
|
+
const removeNotYetSynchronizedFields = Object.values(mapExactToObject(projection, (_, k) => k.startsWith('_') ? root().of(k).has($exists(true)) : null));
|
|
1495
|
+
const hardMatch = $and(pre, ...removeNotYetSynchronizedFields);
|
|
1489
1496
|
const job = {};
|
|
1490
1497
|
const db = collection.s.db, coll = collection.collectionName;
|
|
1491
1498
|
db.command({
|
|
@@ -1569,7 +1576,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1569
1576
|
const step3 = (lastTS) => async () => {
|
|
1570
1577
|
const hardQuery = $and(lastTS
|
|
1571
1578
|
? root().of('touchedAt').has($gteTs(lastTS.ts))
|
|
1572
|
-
: root().of('deletedAt').has($eq(null)), lastTS ? null : match && $expr(match), hardMatch
|
|
1579
|
+
: root().of('deletedAt').has($eq(null)), lastTS ? null : match && $expr(match), hardMatch);
|
|
1573
1580
|
const notDeleted = eq($ifNull(root().of('deletedAt').expr(), nil))(nil);
|
|
1574
1581
|
const query = match ? and(notDeleted, match) : notDeleted;
|
|
1575
1582
|
const replaceRaw = $replaceWith_(field({
|
|
@@ -1587,7 +1594,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1587
1594
|
whenMatched: 'merge',
|
|
1588
1595
|
whenNotMatched: 'insert',
|
|
1589
1596
|
})).stages;
|
|
1590
|
-
const r = await aggregate(c => c({ coll: collection, input: cloneIntoNew }));
|
|
1597
|
+
const r = await aggregate(streamName, c => c({ coll: collection, input: cloneIntoNew }));
|
|
1591
1598
|
await snapshotCollection.deleteMany({ updated: true, after: null, before: null });
|
|
1592
1599
|
return next(step4({ result: r, ts: lastTS?.ts }), 'run the aggregation');
|
|
1593
1600
|
};
|
|
@@ -1595,7 +1602,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1595
1602
|
const step4 = ({ result, ts }) => async () => {
|
|
1596
1603
|
const start = Date.now();
|
|
1597
1604
|
await snapshotCollection.updateMany({ before: null }, { $set: { before: null } });
|
|
1598
|
-
const aggResult = await aggregate(c => c({
|
|
1605
|
+
const aggResult = await aggregate(streamName, c => c({
|
|
1599
1606
|
coll: snapshotCollection,
|
|
1600
1607
|
input: link()
|
|
1601
1608
|
.with($match_(root().of('updated').has($eq(true))))
|
|
@@ -1604,7 +1611,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1604
1611
|
.with(finalInput.raw(ts === undefined)).stages,
|
|
1605
1612
|
}), false, start);
|
|
1606
1613
|
const stream = makeStream(result.cursor.atClusterTime);
|
|
1607
|
-
return next(step5({ result, aggResult, stream }), 'remove handled deleted updated', () => stream.close());
|
|
1614
|
+
return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream }), 'remove handled deleted updated', () => stream.close());
|
|
1608
1615
|
};
|
|
1609
1616
|
const step5 = (l) => async () => {
|
|
1610
1617
|
log(`remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
|
|
@@ -1629,7 +1636,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1629
1636
|
const step7 = (l) => async () => {
|
|
1630
1637
|
await last.updateOne({ _id: streamName }, {
|
|
1631
1638
|
$set: {
|
|
1632
|
-
ts: l.
|
|
1639
|
+
ts: l.ts,
|
|
1633
1640
|
data,
|
|
1634
1641
|
},
|
|
1635
1642
|
}, { upsert: true });
|
|
@@ -1638,11 +1645,15 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1638
1645
|
const step8 = (l) => {
|
|
1639
1646
|
return nextData(l.aggResult.cursor.firstBatch)(() => l.stream
|
|
1640
1647
|
.tryNext()
|
|
1641
|
-
.catch(err => {
|
|
1648
|
+
.catch((err) => {
|
|
1642
1649
|
log('restarting', err);
|
|
1643
|
-
return
|
|
1650
|
+
return { ts: null };
|
|
1644
1651
|
})
|
|
1645
|
-
.then(doc =>
|
|
1652
|
+
.then(doc => doc
|
|
1653
|
+
? doc.ts
|
|
1654
|
+
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1655
|
+
: next(step2, 'restart')
|
|
1656
|
+
: step8(l)), 'wait for change');
|
|
1646
1657
|
};
|
|
1647
1658
|
return stop;
|
|
1648
1659
|
};
|
|
@@ -1732,7 +1743,7 @@ const executes = (view, input, streamName) => {
|
|
|
1732
1743
|
const makeStream = (startAt) => makeWatchStream(db, view, startAt, streamName);
|
|
1733
1744
|
const step4 = (lastTS) => async () => {
|
|
1734
1745
|
const hardQuery = $and(lastTS && root().of('touchedAt').has($gteTs(lastTS.ts)), hardMatch, notDeleted, match && $expr(match));
|
|
1735
|
-
const aggResult = await aggregate(c => c({
|
|
1746
|
+
const aggResult = await aggregate(streamName, c => c({
|
|
1736
1747
|
coll: collection,
|
|
1737
1748
|
input: link()
|
|
1738
1749
|
.with($match_(hardQuery))
|
|
@@ -1741,17 +1752,23 @@ const executes = (view, input, streamName) => {
|
|
|
1741
1752
|
.with(finalInput.raw(lastTS === null)).stages,
|
|
1742
1753
|
}));
|
|
1743
1754
|
const stream = makeStream(aggResult.cursor.atClusterTime);
|
|
1744
|
-
return next(step7({ aggResult,
|
|
1755
|
+
return next(step7({ aggResult, ts: aggResult.cursor.atClusterTime, stream }), 'update __last', () => stream.close());
|
|
1745
1756
|
};
|
|
1746
1757
|
const step7 = (l) => async () => {
|
|
1747
|
-
await last.updateOne({ _id: streamName }, { $set: { ts: l.
|
|
1758
|
+
await last.updateOne({ _id: streamName }, { $set: { ts: l.ts, data } }, { upsert: true });
|
|
1748
1759
|
return step8(l);
|
|
1749
1760
|
};
|
|
1750
1761
|
const step8 = (l) => {
|
|
1751
1762
|
return {
|
|
1752
1763
|
data: l.aggResult.cursor.firstBatch,
|
|
1753
1764
|
info: { job: undefined, debug: 'wait for change' },
|
|
1754
|
-
cont: withStop(() => l.stream
|
|
1765
|
+
cont: withStop(() => l.stream
|
|
1766
|
+
.tryNext()
|
|
1767
|
+
.then(doc => doc
|
|
1768
|
+
? doc.ts
|
|
1769
|
+
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1770
|
+
: next(step1, 'restart')
|
|
1771
|
+
: step8(l))),
|
|
1755
1772
|
};
|
|
1756
1773
|
};
|
|
1757
1774
|
return stop;
|
|
@@ -1806,4 +1823,4 @@ const makeCol = async (docs, database, name) => {
|
|
|
1806
1823
|
}
|
|
1807
1824
|
};
|
|
1808
1825
|
|
|
1809
|
-
export { $accumulator, $and, $countDict, $entries, $eq, $expr, $getField, $group, $groupId, $groupMerge, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map1, $match, $matchDelta, $merge, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $replaceWith, $set, $simpleInsert, $simpleMerge, $sum, $unwind, $unwindDelta, Field, Machine, add, and, 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, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, notNull, now, or, pair, prepare, rand, range, root, set, setField, size, slice, sortArray, staging, startOf, str, sub, subtract, to, toInt, val, weekPart, wrap, year };
|
|
1826
|
+
export { $accumulator, $and, $countDict, $entries, $eq, $exists, $expr, $getField, $group, $groupId, $groupMerge, $gt, $gtTs, $gte, $gteTs, $ifNull, $in, $insert, $insertX, $keys, $let, $lookup, $lt, $lte, $map, $map1, $match, $matchDelta, $merge, $merge_, $ne, $nin, $nor, $or, $outerLookup, $pushDict, $rand, $replaceWith, $set, $simpleInsert, $simpleMerge, $sum, $type, $unwind, $unwindDelta, Field, Machine, add, and, 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, gt, gte, inArray, isArray, ite, last, log, lt, lte, makeCol, map1, mapVal, max, maxDate, mergeExact, mergeExact0, mergeExpr, mergeObjects, minDate, monthPart, multiply, ne, nil, noop, notNull, now, or, pair, prepare, rand, range, root, set, setField, 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 synchronousPromise = require('synchronous-promise');
|
|
5
5
|
var crypto$1 = require('crypto');
|
|
6
|
-
var console$1 = require('console');
|
|
7
6
|
var promises = require('fs/promises');
|
|
8
7
|
|
|
9
8
|
const asExprRaw = (raw) => ({ get: () => raw });
|
|
@@ -887,9 +886,6 @@ const $map = (ex, map) => $map1(ex, i => map(i.expr()));
|
|
|
887
886
|
const operator = () => (op) => (operand) => {
|
|
888
887
|
return {
|
|
889
888
|
raw: { [op]: operand },
|
|
890
|
-
expr: (field) => asExpr({
|
|
891
|
-
raw: f => asExprRaw({ [op]: [$ifNull(field.expr(), nil).raw(f).get(), operand] }),
|
|
892
|
-
}),
|
|
893
889
|
};
|
|
894
890
|
};
|
|
895
891
|
|
|
@@ -904,6 +900,8 @@ const $lt = comp('$lt');
|
|
|
904
900
|
const dateLt = comp('$lt');
|
|
905
901
|
const $gte = comp('$gte');
|
|
906
902
|
const $lte = comp('$lte');
|
|
903
|
+
const $type = operator()('$type');
|
|
904
|
+
const $exists = operator()('$exists');
|
|
907
905
|
|
|
908
906
|
const $expr = (expr) => ({
|
|
909
907
|
raw: f => ({ $expr: expr.raw(f).get() }),
|
|
@@ -1386,16 +1384,16 @@ const replace = (s) => s.replace(/\{"\$timestamp":"(\d+)"\}/g, (_, d) => T(d));
|
|
|
1386
1384
|
const json = (a) => replace(JSON.stringify(a));
|
|
1387
1385
|
const log = (...args) => console.log(new Date(), ...args.map(a => (typeof a === 'function' ? a(replace) : a && typeof a === 'object' ? json(a) : a)));
|
|
1388
1386
|
|
|
1389
|
-
const aggregate = (input, snapshot = true, start = Date.now()) => input(({ coll, input }) => {
|
|
1387
|
+
const aggregate = (streamName, input, snapshot = true, start = Date.now()) => input(({ coll, input }) => {
|
|
1390
1388
|
const req = {
|
|
1391
1389
|
aggregate: coll.collectionName,
|
|
1392
1390
|
pipeline: input,
|
|
1393
1391
|
cursor: {},
|
|
1394
1392
|
...(snapshot && { readConcern: { level: 'snapshot' } }),
|
|
1395
1393
|
};
|
|
1396
|
-
log('exec', req);
|
|
1394
|
+
log('exec', streamName, req);
|
|
1397
1395
|
return coll.s.db.command(req).then(result => {
|
|
1398
|
-
log('execed', req, result, 'took', Date.now() - start);
|
|
1396
|
+
log('execed', streamName, req, result, 'took', Date.now() - start);
|
|
1399
1397
|
return result;
|
|
1400
1398
|
}, err => {
|
|
1401
1399
|
log('err', req, err);
|
|
@@ -1447,11 +1445,19 @@ const makeWatchStream = (db, { collection, projection: p, hardMatch: m }, startA
|
|
|
1447
1445
|
},
|
|
1448
1446
|
});
|
|
1449
1447
|
pipeline.push({
|
|
1450
|
-
$
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1448
|
+
$replaceWith: {
|
|
1449
|
+
ts: {
|
|
1450
|
+
$cond: {
|
|
1451
|
+
if: {
|
|
1452
|
+
$or: [
|
|
1453
|
+
{ $ne: ['$fullDocument', '$fullDocumentBeforeChange'] },
|
|
1454
|
+
{ $and: changeKeys.map(k => ({ $eq: [k, null] })) },
|
|
1455
|
+
],
|
|
1456
|
+
},
|
|
1457
|
+
then: '$clusterTime',
|
|
1458
|
+
else: null,
|
|
1459
|
+
},
|
|
1460
|
+
},
|
|
1455
1461
|
},
|
|
1456
1462
|
});
|
|
1457
1463
|
const stream = db.collection(collection.collectionName).watch(pipeline, {
|
|
@@ -1464,7 +1470,7 @@ const makeWatchStream = (db, { collection, projection: p, hardMatch: m }, startA
|
|
|
1464
1470
|
if (doc)
|
|
1465
1471
|
await new Promise(resolve => setTimeout(resolve, 100));
|
|
1466
1472
|
if (doc)
|
|
1467
|
-
|
|
1473
|
+
log('detected', streamName, collection.collectionName, doc);
|
|
1468
1474
|
return doc;
|
|
1469
1475
|
};
|
|
1470
1476
|
return { tryNext, close: () => stream.close() };
|
|
@@ -1486,8 +1492,9 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1486
1492
|
streamNames[streamName] = hash;
|
|
1487
1493
|
else if (streamNames[streamName] != hash)
|
|
1488
1494
|
throw new Error(`streamName ${streamName} already used`);
|
|
1489
|
-
const { collection, projection, hardMatch, match } = view;
|
|
1490
|
-
const removeNotYetSynchronizedFields = Object.values(mapExactToObject(projection, (_, k) => k.startsWith('_') ? root().of(k).has($
|
|
1495
|
+
const { collection, projection, hardMatch: pre, match } = view;
|
|
1496
|
+
const removeNotYetSynchronizedFields = Object.values(mapExactToObject(projection, (_, k) => k.startsWith('_') ? root().of(k).has($exists(true)) : null));
|
|
1497
|
+
const hardMatch = $and(pre, ...removeNotYetSynchronizedFields);
|
|
1491
1498
|
const job = {};
|
|
1492
1499
|
const db = collection.s.db, coll = collection.collectionName;
|
|
1493
1500
|
db.command({
|
|
@@ -1571,7 +1578,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1571
1578
|
const step3 = (lastTS) => async () => {
|
|
1572
1579
|
const hardQuery = $and(lastTS
|
|
1573
1580
|
? root().of('touchedAt').has($gteTs(lastTS.ts))
|
|
1574
|
-
: root().of('deletedAt').has($eq(null)), lastTS ? null : match && $expr(match), hardMatch
|
|
1581
|
+
: root().of('deletedAt').has($eq(null)), lastTS ? null : match && $expr(match), hardMatch);
|
|
1575
1582
|
const notDeleted = eq($ifNull(root().of('deletedAt').expr(), nil))(nil);
|
|
1576
1583
|
const query = match ? and(notDeleted, match) : notDeleted;
|
|
1577
1584
|
const replaceRaw = $replaceWith_(field({
|
|
@@ -1589,7 +1596,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1589
1596
|
whenMatched: 'merge',
|
|
1590
1597
|
whenNotMatched: 'insert',
|
|
1591
1598
|
})).stages;
|
|
1592
|
-
const r = await aggregate(c => c({ coll: collection, input: cloneIntoNew }));
|
|
1599
|
+
const r = await aggregate(streamName, c => c({ coll: collection, input: cloneIntoNew }));
|
|
1593
1600
|
await snapshotCollection.deleteMany({ updated: true, after: null, before: null });
|
|
1594
1601
|
return next(step4({ result: r, ts: lastTS?.ts }), 'run the aggregation');
|
|
1595
1602
|
};
|
|
@@ -1597,7 +1604,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1597
1604
|
const step4 = ({ result, ts }) => async () => {
|
|
1598
1605
|
const start = Date.now();
|
|
1599
1606
|
await snapshotCollection.updateMany({ before: null }, { $set: { before: null } });
|
|
1600
|
-
const aggResult = await aggregate(c => c({
|
|
1607
|
+
const aggResult = await aggregate(streamName, c => c({
|
|
1601
1608
|
coll: snapshotCollection,
|
|
1602
1609
|
input: link()
|
|
1603
1610
|
.with($match_(root().of('updated').has($eq(true))))
|
|
@@ -1606,7 +1613,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1606
1613
|
.with(finalInput.raw(ts === undefined)).stages,
|
|
1607
1614
|
}), false, start);
|
|
1608
1615
|
const stream = makeStream(result.cursor.atClusterTime);
|
|
1609
|
-
return next(step5({ result, aggResult, stream }), 'remove handled deleted updated', () => stream.close());
|
|
1616
|
+
return next(step5({ ts: result.cursor.atClusterTime, aggResult, stream }), 'remove handled deleted updated', () => stream.close());
|
|
1610
1617
|
};
|
|
1611
1618
|
const step5 = (l) => async () => {
|
|
1612
1619
|
log(`remove handled deleted updated db['${snapshotCollection.collectionName}'].deleteMany({ updated: true, after: null })`);
|
|
@@ -1631,7 +1638,7 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1631
1638
|
const step7 = (l) => async () => {
|
|
1632
1639
|
await last.updateOne({ _id: streamName }, {
|
|
1633
1640
|
$set: {
|
|
1634
|
-
ts: l.
|
|
1641
|
+
ts: l.ts,
|
|
1635
1642
|
data,
|
|
1636
1643
|
},
|
|
1637
1644
|
}, { upsert: true });
|
|
@@ -1640,11 +1647,15 @@ const executes$1 = (view, input, streamName) => {
|
|
|
1640
1647
|
const step8 = (l) => {
|
|
1641
1648
|
return nextData(l.aggResult.cursor.firstBatch)(() => l.stream
|
|
1642
1649
|
.tryNext()
|
|
1643
|
-
.catch(err => {
|
|
1650
|
+
.catch((err) => {
|
|
1644
1651
|
log('restarting', err);
|
|
1645
|
-
return
|
|
1652
|
+
return { ts: null };
|
|
1646
1653
|
})
|
|
1647
|
-
.then(doc =>
|
|
1654
|
+
.then(doc => doc
|
|
1655
|
+
? doc.ts
|
|
1656
|
+
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1657
|
+
: next(step2, 'restart')
|
|
1658
|
+
: step8(l)), 'wait for change');
|
|
1648
1659
|
};
|
|
1649
1660
|
return stop;
|
|
1650
1661
|
};
|
|
@@ -1734,7 +1745,7 @@ const executes = (view, input, streamName) => {
|
|
|
1734
1745
|
const makeStream = (startAt) => makeWatchStream(db, view, startAt, streamName);
|
|
1735
1746
|
const step4 = (lastTS) => async () => {
|
|
1736
1747
|
const hardQuery = $and(lastTS && root().of('touchedAt').has($gteTs(lastTS.ts)), hardMatch, notDeleted, match && $expr(match));
|
|
1737
|
-
const aggResult = await aggregate(c => c({
|
|
1748
|
+
const aggResult = await aggregate(streamName, c => c({
|
|
1738
1749
|
coll: collection,
|
|
1739
1750
|
input: link()
|
|
1740
1751
|
.with($match_(hardQuery))
|
|
@@ -1743,17 +1754,23 @@ const executes = (view, input, streamName) => {
|
|
|
1743
1754
|
.with(finalInput.raw(lastTS === null)).stages,
|
|
1744
1755
|
}));
|
|
1745
1756
|
const stream = makeStream(aggResult.cursor.atClusterTime);
|
|
1746
|
-
return next(step7({ aggResult,
|
|
1757
|
+
return next(step7({ aggResult, ts: aggResult.cursor.atClusterTime, stream }), 'update __last', () => stream.close());
|
|
1747
1758
|
};
|
|
1748
1759
|
const step7 = (l) => async () => {
|
|
1749
|
-
await last.updateOne({ _id: streamName }, { $set: { ts: l.
|
|
1760
|
+
await last.updateOne({ _id: streamName }, { $set: { ts: l.ts, data } }, { upsert: true });
|
|
1750
1761
|
return step8(l);
|
|
1751
1762
|
};
|
|
1752
1763
|
const step8 = (l) => {
|
|
1753
1764
|
return {
|
|
1754
1765
|
data: l.aggResult.cursor.firstBatch,
|
|
1755
1766
|
info: { job: undefined, debug: 'wait for change' },
|
|
1756
|
-
cont: withStop(() => l.stream
|
|
1767
|
+
cont: withStop(() => l.stream
|
|
1768
|
+
.tryNext()
|
|
1769
|
+
.then(doc => doc
|
|
1770
|
+
? doc.ts
|
|
1771
|
+
? next(step7({ ...l, ts: doc.ts }), 'nothing changed')
|
|
1772
|
+
: next(step1, 'restart')
|
|
1773
|
+
: step8(l))),
|
|
1757
1774
|
};
|
|
1758
1775
|
};
|
|
1759
1776
|
return stop;
|
|
@@ -1813,6 +1830,7 @@ exports.$and = $and;
|
|
|
1813
1830
|
exports.$countDict = $countDict;
|
|
1814
1831
|
exports.$entries = $entries;
|
|
1815
1832
|
exports.$eq = $eq;
|
|
1833
|
+
exports.$exists = $exists;
|
|
1816
1834
|
exports.$expr = $expr;
|
|
1817
1835
|
exports.$getField = $getField;
|
|
1818
1836
|
exports.$group = $group;
|
|
@@ -1849,6 +1867,7 @@ exports.$set = $set;
|
|
|
1849
1867
|
exports.$simpleInsert = $simpleInsert;
|
|
1850
1868
|
exports.$simpleMerge = $simpleMerge;
|
|
1851
1869
|
exports.$sum = $sum;
|
|
1870
|
+
exports.$type = $type;
|
|
1852
1871
|
exports.$unwind = $unwind;
|
|
1853
1872
|
exports.$unwindDelta = $unwindDelta;
|
|
1854
1873
|
exports.Field = Field;
|