mongodb-livedata-server 0.0.1

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.
Files changed (94) hide show
  1. package/README.md +63 -0
  2. package/dist/livedata_server.js +9 -0
  3. package/dist/meteor/binary-heap/max_heap.js +186 -0
  4. package/dist/meteor/binary-heap/min_heap.js +17 -0
  5. package/dist/meteor/binary-heap/min_max_heap.js +48 -0
  6. package/dist/meteor/callback-hook/hook.js +78 -0
  7. package/dist/meteor/ddp/crossbar.js +136 -0
  8. package/dist/meteor/ddp/heartbeat.js +77 -0
  9. package/dist/meteor/ddp/livedata_server.js +403 -0
  10. package/dist/meteor/ddp/method-invocation.js +72 -0
  11. package/dist/meteor/ddp/random-stream.js +100 -0
  12. package/dist/meteor/ddp/session-collection-view.js +106 -0
  13. package/dist/meteor/ddp/session-document-view.js +82 -0
  14. package/dist/meteor/ddp/session.js +570 -0
  15. package/dist/meteor/ddp/stream_server.js +181 -0
  16. package/dist/meteor/ddp/subscription.js +347 -0
  17. package/dist/meteor/ddp/utils.js +104 -0
  18. package/dist/meteor/ddp/writefence.js +111 -0
  19. package/dist/meteor/diff-sequence/diff.js +257 -0
  20. package/dist/meteor/ejson/ejson.js +569 -0
  21. package/dist/meteor/ejson/stringify.js +119 -0
  22. package/dist/meteor/ejson/utils.js +42 -0
  23. package/dist/meteor/id-map/id_map.js +92 -0
  24. package/dist/meteor/mongo/caching_change_observer.js +94 -0
  25. package/dist/meteor/mongo/doc_fetcher.js +53 -0
  26. package/dist/meteor/mongo/geojson_utils.js +41 -0
  27. package/dist/meteor/mongo/live_connection.js +264 -0
  28. package/dist/meteor/mongo/live_cursor.js +57 -0
  29. package/dist/meteor/mongo/minimongo_common.js +2002 -0
  30. package/dist/meteor/mongo/minimongo_matcher.js +217 -0
  31. package/dist/meteor/mongo/minimongo_sorter.js +268 -0
  32. package/dist/meteor/mongo/observe_driver_utils.js +73 -0
  33. package/dist/meteor/mongo/observe_multiplexer.js +228 -0
  34. package/dist/meteor/mongo/oplog-observe-driver.js +919 -0
  35. package/dist/meteor/mongo/oplog_tailing.js +352 -0
  36. package/dist/meteor/mongo/oplog_v2_converter.js +126 -0
  37. package/dist/meteor/mongo/polling_observe_driver.js +195 -0
  38. package/dist/meteor/mongo/synchronous-cursor.js +261 -0
  39. package/dist/meteor/mongo/synchronous-queue.js +110 -0
  40. package/dist/meteor/ordered-dict/ordered_dict.js +198 -0
  41. package/dist/meteor/random/AbstractRandomGenerator.js +92 -0
  42. package/dist/meteor/random/AleaRandomGenerator.js +90 -0
  43. package/dist/meteor/random/NodeRandomGenerator.js +42 -0
  44. package/dist/meteor/random/createAleaGenerator.js +32 -0
  45. package/dist/meteor/random/createRandom.js +22 -0
  46. package/dist/meteor/random/main.js +12 -0
  47. package/livedata_server.ts +3 -0
  48. package/meteor/LICENSE +28 -0
  49. package/meteor/binary-heap/max_heap.ts +225 -0
  50. package/meteor/binary-heap/min_heap.ts +15 -0
  51. package/meteor/binary-heap/min_max_heap.ts +53 -0
  52. package/meteor/callback-hook/hook.ts +85 -0
  53. package/meteor/ddp/crossbar.ts +148 -0
  54. package/meteor/ddp/heartbeat.ts +97 -0
  55. package/meteor/ddp/livedata_server.ts +473 -0
  56. package/meteor/ddp/method-invocation.ts +86 -0
  57. package/meteor/ddp/random-stream.ts +102 -0
  58. package/meteor/ddp/session-collection-view.ts +119 -0
  59. package/meteor/ddp/session-document-view.ts +92 -0
  60. package/meteor/ddp/session.ts +708 -0
  61. package/meteor/ddp/stream_server.ts +204 -0
  62. package/meteor/ddp/subscription.ts +392 -0
  63. package/meteor/ddp/utils.ts +119 -0
  64. package/meteor/ddp/writefence.ts +130 -0
  65. package/meteor/diff-sequence/diff.ts +295 -0
  66. package/meteor/ejson/ejson.ts +601 -0
  67. package/meteor/ejson/stringify.ts +122 -0
  68. package/meteor/ejson/utils.ts +38 -0
  69. package/meteor/id-map/id_map.ts +84 -0
  70. package/meteor/mongo/caching_change_observer.ts +120 -0
  71. package/meteor/mongo/doc_fetcher.ts +52 -0
  72. package/meteor/mongo/geojson_utils.ts +42 -0
  73. package/meteor/mongo/live_connection.ts +302 -0
  74. package/meteor/mongo/live_cursor.ts +79 -0
  75. package/meteor/mongo/minimongo_common.ts +2440 -0
  76. package/meteor/mongo/minimongo_matcher.ts +275 -0
  77. package/meteor/mongo/minimongo_sorter.ts +331 -0
  78. package/meteor/mongo/observe_driver_utils.ts +79 -0
  79. package/meteor/mongo/observe_multiplexer.ts +256 -0
  80. package/meteor/mongo/oplog-observe-driver.ts +1049 -0
  81. package/meteor/mongo/oplog_tailing.ts +414 -0
  82. package/meteor/mongo/oplog_v2_converter.ts +124 -0
  83. package/meteor/mongo/polling_observe_driver.ts +247 -0
  84. package/meteor/mongo/synchronous-cursor.ts +293 -0
  85. package/meteor/mongo/synchronous-queue.ts +119 -0
  86. package/meteor/ordered-dict/ordered_dict.ts +229 -0
  87. package/meteor/random/AbstractRandomGenerator.ts +99 -0
  88. package/meteor/random/AleaRandomGenerator.ts +96 -0
  89. package/meteor/random/NodeRandomGenerator.ts +37 -0
  90. package/meteor/random/createAleaGenerator.ts +31 -0
  91. package/meteor/random/createRandom.ts +19 -0
  92. package/meteor/random/main.ts +8 -0
  93. package/package.json +30 -0
  94. package/tsconfig.json +10 -0
@@ -0,0 +1,111 @@
1
+ "use strict";
2
+ // A write fence collects a group of writes, and provides a callback
3
+ // when all of the writes are fully committed and propagated (all
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports._WriteFence = void 0;
6
+ // observers have been notified of the write and acknowledged it.)
7
+ class _WriteFence {
8
+ constructor() {
9
+ this.armed = false;
10
+ this.fired = false;
11
+ this.retired = false;
12
+ this.outstanding_writes = 0;
13
+ this.before_fire_callbacks = [];
14
+ this.completion_callbacks = [];
15
+ }
16
+ ;
17
+ // Start tracking a write, and return an object to represent it. The
18
+ // object has a single method, committed(). This method should be
19
+ // called when the write is fully committed and propagated. You can
20
+ // continue to add writes to the WriteFence up until it is triggered
21
+ // (calls its callbacks because all writes have committed.)
22
+ beginWrite() {
23
+ var self = this;
24
+ if (self.retired)
25
+ return { committed: function () { } };
26
+ if (self.fired)
27
+ throw new Error("fence has already activated -- too late to add writes");
28
+ self.outstanding_writes++;
29
+ var committed = false;
30
+ return {
31
+ committed: function () {
32
+ if (committed)
33
+ throw new Error("committed called twice on the same write");
34
+ committed = true;
35
+ self.outstanding_writes--;
36
+ self._maybeFire();
37
+ }
38
+ };
39
+ }
40
+ // Arm the fence. Once the fence is armed, and there are no more
41
+ // uncommitted writes, it will activate.
42
+ arm() {
43
+ var self = this;
44
+ if (self === _WriteFence._CurrentWriteFence)
45
+ throw Error("Can't arm the current fence");
46
+ self.armed = true;
47
+ self._maybeFire();
48
+ }
49
+ // Register a function to be called once before firing the fence.
50
+ // Callback function can add new writes to the fence, in which case
51
+ // it won't fire until those writes are done as well.
52
+ onBeforeFire(func) {
53
+ var self = this;
54
+ if (self.fired)
55
+ throw new Error("fence has already activated -- too late to " +
56
+ "add a callback");
57
+ self.before_fire_callbacks.push(func);
58
+ }
59
+ // Register a function to be called when the fence fires.
60
+ onAllCommitted(func) {
61
+ var self = this;
62
+ if (self.fired)
63
+ throw new Error("fence has already activated -- too late to " +
64
+ "add a callback");
65
+ self.completion_callbacks.push(func);
66
+ }
67
+ _maybeFire() {
68
+ var self = this;
69
+ if (self.fired)
70
+ throw new Error("write fence already activated?");
71
+ if (self.armed && !self.outstanding_writes) {
72
+ self.outstanding_writes++;
73
+ while (self.before_fire_callbacks.length > 0) {
74
+ var callbacks = self.before_fire_callbacks;
75
+ self.before_fire_callbacks = [];
76
+ for (const callback of callbacks)
77
+ invokeCallback(callback, self);
78
+ }
79
+ self.outstanding_writes--;
80
+ if (!self.outstanding_writes) {
81
+ self.fired = true;
82
+ var callbacks = self.completion_callbacks;
83
+ self.completion_callbacks = [];
84
+ for (const callback of callbacks)
85
+ invokeCallback(callback, self);
86
+ }
87
+ }
88
+ }
89
+ // Deactivate this fence so that adding more writes has no effect.
90
+ // The fence must have already fired.
91
+ retire() {
92
+ var self = this;
93
+ if (!self.fired)
94
+ throw new Error("Can't retire a fence that hasn't fired.");
95
+ self.retired = true;
96
+ }
97
+ }
98
+ exports._WriteFence = _WriteFence;
99
+ // The current write fence. When there is a current write fence, code
100
+ // that writes to databases should register their writes with it using
101
+ // beginWrite().
102
+ //
103
+ _WriteFence._CurrentWriteFence = new _WriteFence();
104
+ function invokeCallback(func, self) {
105
+ try {
106
+ func(self);
107
+ }
108
+ catch (err) {
109
+ console.error("exception in write fence callback", err);
110
+ }
111
+ }
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DiffSequence = void 0;
4
+ const ejson_1 = require("../ejson/ejson");
5
+ exports.DiffSequence = {};
6
+ const hasOwn = Object.prototype.hasOwnProperty;
7
+ function isObjEmpty(obj) {
8
+ for (let key in Object(obj)) {
9
+ if (hasOwn.call(obj, key)) {
10
+ return false;
11
+ }
12
+ }
13
+ return true;
14
+ }
15
+ // ordered: bool.
16
+ // old_results and new_results: collections of documents.
17
+ // if ordered, they are arrays.
18
+ // if unordered, they are IdMaps
19
+ exports.DiffSequence.diffQueryChanges = function (ordered, oldResults, newResults, observer, options) {
20
+ if (ordered)
21
+ exports.DiffSequence.diffQueryOrderedChanges(oldResults, newResults, observer, options);
22
+ else
23
+ exports.DiffSequence.diffQueryUnorderedChanges(oldResults, newResults, observer, options);
24
+ };
25
+ exports.DiffSequence.diffQueryUnorderedChanges = function (oldResults, newResults, observer, options) {
26
+ options = options || {};
27
+ var projectionFn = options.projectionFn || ejson_1.clone;
28
+ if (observer.movedBefore) {
29
+ throw new Error("_diffQueryUnordered called with a movedBefore observer!");
30
+ }
31
+ newResults.forEach(function (newDoc, id) {
32
+ var oldDoc = oldResults.get(id);
33
+ if (oldDoc) {
34
+ if (observer.changed && !(0, ejson_1.equals)(oldDoc, newDoc)) {
35
+ var projectedNew = projectionFn(newDoc);
36
+ var projectedOld = projectionFn(oldDoc);
37
+ var changedFields = exports.DiffSequence.makeChangedFields(projectedNew, projectedOld);
38
+ if (!isObjEmpty(changedFields)) {
39
+ observer.changed(id, changedFields);
40
+ }
41
+ }
42
+ }
43
+ else if (observer.added) {
44
+ var fields = projectionFn(newDoc);
45
+ delete fields._id;
46
+ observer.added(newDoc._id, fields);
47
+ }
48
+ });
49
+ if (observer.removed) {
50
+ oldResults.forEach(function (oldDoc, id) {
51
+ if (!newResults.has(id))
52
+ observer.removed(id);
53
+ });
54
+ }
55
+ };
56
+ exports.DiffSequence.diffQueryOrderedChanges = function (old_results, new_results, observer, options) {
57
+ options = options || {};
58
+ var projectionFn = options.projectionFn || ejson_1.clone;
59
+ var new_presence_of_id = {};
60
+ new_results.forEach(function (doc) {
61
+ if (new_presence_of_id[doc._id])
62
+ console.log("Duplicate _id in new_results");
63
+ new_presence_of_id[doc._id] = true;
64
+ });
65
+ var old_index_of_id = {};
66
+ old_results.forEach(function (doc, i) {
67
+ if (doc._id in old_index_of_id)
68
+ console.log("Duplicate _id in old_results");
69
+ old_index_of_id[doc._id] = i;
70
+ });
71
+ // ALGORITHM:
72
+ //
73
+ // To determine which docs should be considered "moved" (and which
74
+ // merely change position because of other docs moving) we run
75
+ // a "longest common subsequence" (LCS) algorithm. The LCS of the
76
+ // old doc IDs and the new doc IDs gives the docs that should NOT be
77
+ // considered moved.
78
+ // To actually call the appropriate callbacks to get from the old state to the
79
+ // new state:
80
+ // First, we call removed() on all the items that only appear in the old
81
+ // state.
82
+ // Then, once we have the items that should not move, we walk through the new
83
+ // results array group-by-group, where a "group" is a set of items that have
84
+ // moved, anchored on the end by an item that should not move. One by one, we
85
+ // move each of those elements into place "before" the anchoring end-of-group
86
+ // item, and fire changed events on them if necessary. Then we fire a changed
87
+ // event on the anchor, and move on to the next group. There is always at
88
+ // least one group; the last group is anchored by a virtual "null" id at the
89
+ // end.
90
+ // Asymptotically: O(N k) where k is number of ops, or potentially
91
+ // O(N log N) if inner loop of LCS were made to be binary search.
92
+ //////// LCS (longest common sequence, with respect to _id)
93
+ // (see Wikipedia article on Longest Increasing Subsequence,
94
+ // where the LIS is taken of the sequence of old indices of the
95
+ // docs in new_results)
96
+ //
97
+ // unmoved: the output of the algorithm; members of the LCS,
98
+ // in the form of indices into new_results
99
+ var unmoved = [];
100
+ // max_seq_len: length of LCS found so far
101
+ var max_seq_len = 0;
102
+ // seq_ends[i]: the index into new_results of the last doc in a
103
+ // common subsequence of length of i+1 <= max_seq_len
104
+ var N = new_results.length;
105
+ var seq_ends = new Array(N);
106
+ // ptrs: the common subsequence ending with new_results[n] extends
107
+ // a common subsequence ending with new_results[ptr[n]], unless
108
+ // ptr[n] is -1.
109
+ var ptrs = new Array(N);
110
+ // virtual sequence of old indices of new results
111
+ var old_idx_seq = function (i_new) {
112
+ return old_index_of_id[new_results[i_new]._id];
113
+ };
114
+ // for each item in new_results, use it to extend a common subsequence
115
+ // of length j <= max_seq_len
116
+ for (var i = 0; i < N; i++) {
117
+ if (old_index_of_id[new_results[i]._id] !== undefined) {
118
+ var j = max_seq_len;
119
+ // this inner loop would traditionally be a binary search,
120
+ // but scanning backwards we will likely find a subseq to extend
121
+ // pretty soon, bounded for example by the total number of ops.
122
+ // If this were to be changed to a binary search, we'd still want
123
+ // to scan backwards a bit as an optimization.
124
+ while (j > 0) {
125
+ if (old_idx_seq(seq_ends[j - 1]) < old_idx_seq(i))
126
+ break;
127
+ j--;
128
+ }
129
+ ptrs[i] = (j === 0 ? -1 : seq_ends[j - 1]);
130
+ seq_ends[j] = i;
131
+ if (j + 1 > max_seq_len)
132
+ max_seq_len = j + 1;
133
+ }
134
+ }
135
+ // pull out the LCS/LIS into unmoved
136
+ var idx = (max_seq_len === 0 ? -1 : seq_ends[max_seq_len - 1]);
137
+ while (idx >= 0) {
138
+ unmoved.push(idx);
139
+ idx = ptrs[idx];
140
+ }
141
+ // the unmoved item list is built backwards, so fix that
142
+ unmoved.reverse();
143
+ // the last group is always anchored by the end of the result list, which is
144
+ // an id of "null"
145
+ unmoved.push(new_results.length);
146
+ old_results.forEach(function (doc) {
147
+ if (!new_presence_of_id[doc._id])
148
+ observer.removed && observer.removed(doc._id);
149
+ });
150
+ // for each group of things in the new_results that is anchored by an unmoved
151
+ // element, iterate through the things before it.
152
+ var startOfGroup = 0;
153
+ unmoved.forEach(function (endOfGroup) {
154
+ var groupId = new_results[endOfGroup] ? new_results[endOfGroup]._id : null;
155
+ var oldDoc, newDoc, fields, projectedNew, projectedOld;
156
+ for (var i = startOfGroup; i < endOfGroup; i++) {
157
+ newDoc = new_results[i];
158
+ if (!hasOwn.call(old_index_of_id, newDoc._id)) {
159
+ fields = projectionFn(newDoc);
160
+ delete fields._id;
161
+ observer.addedBefore && observer.addedBefore(newDoc._id, fields, groupId);
162
+ observer.added && observer.added(newDoc._id, fields);
163
+ }
164
+ else {
165
+ // moved
166
+ oldDoc = old_results[old_index_of_id[newDoc._id]];
167
+ projectedNew = projectionFn(newDoc);
168
+ projectedOld = projectionFn(oldDoc);
169
+ fields = exports.DiffSequence.makeChangedFields(projectedNew, projectedOld);
170
+ if (!isObjEmpty(fields)) {
171
+ observer.changed && observer.changed(newDoc._id, fields);
172
+ }
173
+ observer.movedBefore && observer.movedBefore(newDoc._id, groupId);
174
+ }
175
+ }
176
+ if (groupId) {
177
+ newDoc = new_results[endOfGroup];
178
+ oldDoc = old_results[old_index_of_id[newDoc._id]];
179
+ projectedNew = projectionFn(newDoc);
180
+ projectedOld = projectionFn(oldDoc);
181
+ fields = exports.DiffSequence.makeChangedFields(projectedNew, projectedOld);
182
+ if (!isObjEmpty(fields)) {
183
+ observer.changed && observer.changed(newDoc._id, fields);
184
+ }
185
+ }
186
+ startOfGroup = endOfGroup + 1;
187
+ });
188
+ };
189
+ // General helper for diff-ing two objects.
190
+ // callbacks is an object like so:
191
+ // { leftOnly: function (key, leftValue) {...},
192
+ // rightOnly: function (key, rightValue) {...},
193
+ // both: function (key, leftValue, rightValue) {...},
194
+ // }
195
+ exports.DiffSequence.diffObjects = function (left, right, callbacks) {
196
+ Object.keys(left).forEach(key => {
197
+ const leftValue = left[key];
198
+ if (hasOwn.call(right, key)) {
199
+ callbacks.both && callbacks.both(key, leftValue, right[key]);
200
+ }
201
+ else {
202
+ callbacks.leftOnly && callbacks.leftOnly(key, leftValue);
203
+ }
204
+ });
205
+ if (callbacks.rightOnly) {
206
+ Object.keys(right).forEach(key => {
207
+ const rightValue = right[key];
208
+ if (!hasOwn.call(left, key)) {
209
+ callbacks.rightOnly(key, rightValue);
210
+ }
211
+ });
212
+ }
213
+ };
214
+ exports.DiffSequence.diffMaps = function (left, right, callbacks) {
215
+ left.forEach(function (leftValue, key) {
216
+ if (right.has(key)) {
217
+ callbacks.both && callbacks.both(key, leftValue, right.get(key));
218
+ }
219
+ else {
220
+ callbacks.leftOnly && callbacks.leftOnly(key, leftValue);
221
+ }
222
+ });
223
+ if (callbacks.rightOnly) {
224
+ right.forEach(function (rightValue, key) {
225
+ if (!left.has(key)) {
226
+ callbacks.rightOnly(key, rightValue);
227
+ }
228
+ });
229
+ }
230
+ };
231
+ exports.DiffSequence.makeChangedFields = function (newDoc, oldDoc) {
232
+ var fields = {};
233
+ exports.DiffSequence.diffObjects(oldDoc, newDoc, {
234
+ leftOnly: function (key, value) {
235
+ fields[key] = undefined;
236
+ },
237
+ rightOnly: function (key, value) {
238
+ fields[key] = value;
239
+ },
240
+ both: function (key, leftValue, rightValue) {
241
+ if (!(0, ejson_1.equals)(leftValue, rightValue))
242
+ fields[key] = rightValue;
243
+ }
244
+ });
245
+ return fields;
246
+ };
247
+ exports.DiffSequence.applyChanges = function (doc, changeFields) {
248
+ Object.keys(changeFields).forEach(key => {
249
+ const value = changeFields[key];
250
+ if (typeof value === "undefined") {
251
+ delete doc[key];
252
+ }
253
+ else {
254
+ doc[key] = value;
255
+ }
256
+ });
257
+ };