mongodb-livedata-server 0.1.3 → 0.1.5

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 (92) hide show
  1. package/README.md +2 -2
  2. package/dist/livedata_server.d.ts +4 -4
  3. package/dist/livedata_server.js +11 -11
  4. package/dist/meteor/binary-heap/max_heap.d.ts +31 -31
  5. package/dist/meteor/binary-heap/max_heap.js +186 -186
  6. package/dist/meteor/binary-heap/min_heap.d.ts +6 -6
  7. package/dist/meteor/binary-heap/min_heap.js +17 -17
  8. package/dist/meteor/binary-heap/min_max_heap.d.ts +11 -11
  9. package/dist/meteor/binary-heap/min_max_heap.js +48 -48
  10. package/dist/meteor/callback-hook/hook.d.ts +11 -11
  11. package/dist/meteor/callback-hook/hook.js +78 -78
  12. package/dist/meteor/ddp/crossbar.d.ts +15 -15
  13. package/dist/meteor/ddp/crossbar.js +136 -136
  14. package/dist/meteor/ddp/heartbeat.d.ts +19 -19
  15. package/dist/meteor/ddp/heartbeat.js +77 -77
  16. package/dist/meteor/ddp/livedata_server.d.ts +141 -142
  17. package/dist/meteor/ddp/livedata_server.js +403 -403
  18. package/dist/meteor/ddp/method-invocation.d.ts +35 -35
  19. package/dist/meteor/ddp/method-invocation.js +72 -72
  20. package/dist/meteor/ddp/random-stream.d.ts +8 -8
  21. package/dist/meteor/ddp/random-stream.js +100 -100
  22. package/dist/meteor/ddp/session-collection-view.d.ts +20 -20
  23. package/dist/meteor/ddp/session-collection-view.js +106 -106
  24. package/dist/meteor/ddp/session-document-view.d.ts +8 -8
  25. package/dist/meteor/ddp/session-document-view.js +82 -82
  26. package/dist/meteor/ddp/session.d.ts +75 -75
  27. package/dist/meteor/ddp/session.js +590 -590
  28. package/dist/meteor/ddp/stream_server.d.ts +20 -21
  29. package/dist/meteor/ddp/stream_server.js +181 -181
  30. package/dist/meteor/ddp/subscription.d.ts +94 -94
  31. package/dist/meteor/ddp/subscription.js +370 -370
  32. package/dist/meteor/ddp/utils.d.ts +8 -8
  33. package/dist/meteor/ddp/utils.js +104 -104
  34. package/dist/meteor/ddp/writefence.d.ts +20 -20
  35. package/dist/meteor/ddp/writefence.js +111 -111
  36. package/dist/meteor/diff-sequence/diff.d.ts +17 -17
  37. package/dist/meteor/diff-sequence/diff.js +257 -257
  38. package/dist/meteor/ejson/ejson.d.ts +82 -82
  39. package/dist/meteor/ejson/ejson.js +568 -569
  40. package/dist/meteor/ejson/stringify.d.ts +2 -2
  41. package/dist/meteor/ejson/stringify.js +119 -119
  42. package/dist/meteor/ejson/utils.d.ts +12 -12
  43. package/dist/meteor/ejson/utils.js +42 -42
  44. package/dist/meteor/mongo/caching_change_observer.d.ts +16 -16
  45. package/dist/meteor/mongo/caching_change_observer.js +63 -63
  46. package/dist/meteor/mongo/doc_fetcher.d.ts +7 -7
  47. package/dist/meteor/mongo/doc_fetcher.js +53 -53
  48. package/dist/meteor/mongo/geojson_utils.d.ts +3 -3
  49. package/dist/meteor/mongo/geojson_utils.js +40 -41
  50. package/dist/meteor/mongo/live_connection.d.ts +28 -28
  51. package/dist/meteor/mongo/live_connection.js +264 -264
  52. package/dist/meteor/mongo/live_cursor.d.ts +25 -25
  53. package/dist/meteor/mongo/live_cursor.js +60 -60
  54. package/dist/meteor/mongo/minimongo_common.d.ts +84 -84
  55. package/dist/meteor/mongo/minimongo_common.js +1998 -1998
  56. package/dist/meteor/mongo/minimongo_matcher.d.ts +23 -23
  57. package/dist/meteor/mongo/minimongo_matcher.js +283 -283
  58. package/dist/meteor/mongo/minimongo_sorter.d.ts +16 -16
  59. package/dist/meteor/mongo/minimongo_sorter.js +268 -268
  60. package/dist/meteor/mongo/observe_driver_utils.d.ts +9 -9
  61. package/dist/meteor/mongo/observe_driver_utils.js +72 -73
  62. package/dist/meteor/mongo/observe_multiplexer.d.ts +46 -46
  63. package/dist/meteor/mongo/observe_multiplexer.js +203 -203
  64. package/dist/meteor/mongo/oplog-observe-driver.d.ts +68 -68
  65. package/dist/meteor/mongo/oplog-observe-driver.js +918 -918
  66. package/dist/meteor/mongo/oplog_tailing.d.ts +35 -35
  67. package/dist/meteor/mongo/oplog_tailing.js +352 -352
  68. package/dist/meteor/mongo/oplog_v2_converter.d.ts +1 -1
  69. package/dist/meteor/mongo/oplog_v2_converter.js +125 -126
  70. package/dist/meteor/mongo/polling_observe_driver.d.ts +30 -30
  71. package/dist/meteor/mongo/polling_observe_driver.js +216 -221
  72. package/dist/meteor/mongo/synchronous-cursor.d.ts +17 -17
  73. package/dist/meteor/mongo/synchronous-cursor.js +261 -261
  74. package/dist/meteor/mongo/synchronous-queue.d.ts +13 -13
  75. package/dist/meteor/mongo/synchronous-queue.js +110 -110
  76. package/dist/meteor/ordered-dict/ordered_dict.d.ts +31 -31
  77. package/dist/meteor/ordered-dict/ordered_dict.js +198 -198
  78. package/dist/meteor/random/AbstractRandomGenerator.d.ts +42 -42
  79. package/dist/meteor/random/AbstractRandomGenerator.js +92 -92
  80. package/dist/meteor/random/AleaRandomGenerator.d.ts +13 -13
  81. package/dist/meteor/random/AleaRandomGenerator.js +90 -90
  82. package/dist/meteor/random/NodeRandomGenerator.d.ts +16 -16
  83. package/dist/meteor/random/NodeRandomGenerator.js +42 -42
  84. package/dist/meteor/random/createAleaGenerator.d.ts +2 -2
  85. package/dist/meteor/random/createAleaGenerator.js +32 -32
  86. package/dist/meteor/random/createRandom.d.ts +1 -1
  87. package/dist/meteor/random/createRandom.js +22 -22
  88. package/dist/meteor/random/main.d.ts +1 -1
  89. package/dist/meteor/random/main.js +12 -12
  90. package/dist/meteor/types.d.ts +1 -1
  91. package/dist/meteor/types.js +2 -2
  92. package/package.json +5 -5
@@ -1,73 +1,72 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports._idsMatchedBySelector = exports.forEachTrigger = exports.listenAll = void 0;
4
- const crossbar_1 = require("../ddp/crossbar");
5
- // Listen for the invalidation messages that will trigger us to poll the
6
- // database for changes. If this selector specifies specific IDs, specify them
7
- // here, so that updates to different specific IDs don't cause us to poll.
8
- // listenCallback is the same kind of (notification, complete) callback passed
9
- // to InvalidationCrossbar.listen.
10
- function listenAll(cursorDescription, listenCallback) {
11
- var listeners = [];
12
- forEachTrigger(cursorDescription, function (trigger) {
13
- listeners.push(crossbar_1._InvalidationCrossbar.listen(trigger, listenCallback));
14
- });
15
- return {
16
- stop: function () {
17
- for (const listener of listeners) {
18
- listener.stop();
19
- }
20
- }
21
- };
22
- }
23
- exports.listenAll = listenAll;
24
- function forEachTrigger(cursorDescription, triggerCallback) {
25
- var key = { collection: cursorDescription.collectionName };
26
- var specificIds = _idsMatchedBySelector(cursorDescription.selector);
27
- if (specificIds) {
28
- for (const id of specificIds) {
29
- triggerCallback(Object.assign({ id: id }, key));
30
- }
31
- triggerCallback(Object.assign({ dropCollection: true, id: null }, key));
32
- }
33
- else {
34
- triggerCallback(key);
35
- }
36
- // Everyone cares about the database being dropped.
37
- triggerCallback({ dropDatabase: true });
38
- }
39
- exports.forEachTrigger = forEachTrigger;
40
- function _idsMatchedBySelector(selector) {
41
- if (!selector) {
42
- return null;
43
- }
44
- // Do we have an _id clause?
45
- if (selector.hasOwnProperty('_id')) {
46
- // Is the _id clause just an ID?
47
- if (typeof selector._id === "string") {
48
- return [selector._id];
49
- }
50
- // Is the _id clause {_id: {$in: ["x", "y", "z"]}}?
51
- if (selector._id
52
- && "$in" in selector._id
53
- && Array.isArray(selector._id.$in)
54
- && selector._id.$in.length
55
- && selector._id.$in.every(id => typeof id === "string")) {
56
- return selector._id.$in;
57
- }
58
- return null;
59
- }
60
- // If this is a top-level $and, and any of the clauses constrain their
61
- // documents, then the whole selector is constrained by any one clause's
62
- // constraint. (Well, by their intersection, but that seems unlikely.)
63
- if ("$and" in selector && Array.isArray(selector.$and)) {
64
- for (let i = 0; i < selector.$and.length; ++i) {
65
- const subIds = _idsMatchedBySelector(selector.$and[i]);
66
- if (subIds) {
67
- return subIds;
68
- }
69
- }
70
- }
71
- return null;
72
- }
73
- exports._idsMatchedBySelector = _idsMatchedBySelector;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listenAll = listenAll;
4
+ exports.forEachTrigger = forEachTrigger;
5
+ exports._idsMatchedBySelector = _idsMatchedBySelector;
6
+ const crossbar_1 = require("../ddp/crossbar");
7
+ // Listen for the invalidation messages that will trigger us to poll the
8
+ // database for changes. If this selector specifies specific IDs, specify them
9
+ // here, so that updates to different specific IDs don't cause us to poll.
10
+ // listenCallback is the same kind of (notification, complete) callback passed
11
+ // to InvalidationCrossbar.listen.
12
+ function listenAll(cursorDescription, listenCallback) {
13
+ var listeners = [];
14
+ forEachTrigger(cursorDescription, function (trigger) {
15
+ listeners.push(crossbar_1._InvalidationCrossbar.listen(trigger, listenCallback));
16
+ });
17
+ return {
18
+ stop: function () {
19
+ for (const listener of listeners) {
20
+ listener.stop();
21
+ }
22
+ }
23
+ };
24
+ }
25
+ function forEachTrigger(cursorDescription, triggerCallback) {
26
+ var key = { collection: cursorDescription.collectionName };
27
+ var specificIds = _idsMatchedBySelector(cursorDescription.selector);
28
+ if (specificIds) {
29
+ for (const id of specificIds) {
30
+ triggerCallback(Object.assign({ id: id }, key));
31
+ }
32
+ triggerCallback(Object.assign({ dropCollection: true, id: null }, key));
33
+ }
34
+ else {
35
+ triggerCallback(key);
36
+ }
37
+ // Everyone cares about the database being dropped.
38
+ triggerCallback({ dropDatabase: true });
39
+ }
40
+ function _idsMatchedBySelector(selector) {
41
+ if (!selector) {
42
+ return null;
43
+ }
44
+ // Do we have an _id clause?
45
+ if (selector.hasOwnProperty('_id')) {
46
+ // Is the _id clause just an ID?
47
+ if (typeof selector._id === "string") {
48
+ return [selector._id];
49
+ }
50
+ // Is the _id clause {_id: {$in: ["x", "y", "z"]}}?
51
+ if (selector._id
52
+ && "$in" in selector._id
53
+ && Array.isArray(selector._id.$in)
54
+ && selector._id.$in.length
55
+ && selector._id.$in.every(id => typeof id === "string")) {
56
+ return selector._id.$in;
57
+ }
58
+ return null;
59
+ }
60
+ // If this is a top-level $and, and any of the clauses constrain their
61
+ // documents, then the whole selector is constrained by any one clause's
62
+ // constraint. (Well, by their intersection, but that seems unlikely.)
63
+ if ("$and" in selector && Array.isArray(selector.$and)) {
64
+ for (let i = 0; i < selector.$and.length; ++i) {
65
+ const subIds = _idsMatchedBySelector(selector.$and[i]);
66
+ if (subIds) {
67
+ return subIds;
68
+ }
69
+ }
70
+ }
71
+ return null;
72
+ }
@@ -1,46 +1,46 @@
1
- import { OrderedDict } from "../ordered-dict/ordered_dict";
2
- export interface ObserveCallbacks {
3
- added: (id: string, fields: Record<string, any>) => void;
4
- changed: (id: string, fields: Record<string, any>) => void;
5
- removed: (id: string) => void;
6
- addedBefore?: (id: string, fields: Record<string, any>, before?: any) => void;
7
- movedBefore?: (id: string, fields: Record<string, any>, before?: any) => void;
8
- initialAdds: (docs: Map<string, any> | OrderedDict) => void;
9
- _testOnlyPollCallback?: any;
10
- }
11
- export declare class ObserveMultiplexer {
12
- private _ordered;
13
- private _onStop;
14
- private _queue;
15
- private _handles;
16
- private _readyFuture;
17
- private _cache;
18
- private _addHandleTasksScheduledButNotPerformed;
19
- added: ObserveCallbacks["added"];
20
- changed: ObserveCallbacks["changed"];
21
- removed: ObserveCallbacks["removed"];
22
- constructor(options: any);
23
- addHandleAndSendInitialAdds(handle: ObserveHandle): Promise<void>;
24
- removeHandle(id: number): void;
25
- _stop(options?: any): void;
26
- ready(): void;
27
- queryError(err: Error): void;
28
- onFlush(cb: any): void;
29
- callbackNames(): string[];
30
- _ready(): boolean;
31
- _applyCallback(callbackName: string, args: any): Promise<void>;
32
- }
33
- export declare class ObserveHandle {
34
- private _multiplexer;
35
- nonMutatingCallbacks: boolean;
36
- _id: number;
37
- _initialAdds: ObserveCallbacks["initialAdds"];
38
- _addedBefore: ObserveCallbacks["addedBefore"];
39
- _movedBefore: ObserveCallbacks["movedBefore"];
40
- _added: ObserveCallbacks["added"];
41
- _changed: ObserveCallbacks["changed"];
42
- _removed: ObserveCallbacks["removed"];
43
- private _stopped;
44
- constructor(_multiplexer: ObserveMultiplexer, callbacks: ObserveCallbacks, nonMutatingCallbacks?: boolean);
45
- stop(): void;
46
- }
1
+ import { OrderedDict } from "../ordered-dict/ordered_dict";
2
+ export interface ObserveCallbacks {
3
+ added: (id: string, fields: Record<string, any>) => void;
4
+ changed: (id: string, fields: Record<string, any>) => void;
5
+ removed: (id: string) => void;
6
+ addedBefore?: (id: string, fields: Record<string, any>, before?: any) => void;
7
+ movedBefore?: (id: string, fields: Record<string, any>, before?: any) => void;
8
+ initialAdds: (docs: Map<string, any> | OrderedDict) => void;
9
+ _testOnlyPollCallback?: any;
10
+ }
11
+ export declare class ObserveMultiplexer {
12
+ private _ordered;
13
+ private _onStop;
14
+ private _queue;
15
+ private _handles;
16
+ private _readyFuture;
17
+ private _cache;
18
+ private _addHandleTasksScheduledButNotPerformed;
19
+ added: ObserveCallbacks["added"];
20
+ changed: ObserveCallbacks["changed"];
21
+ removed: ObserveCallbacks["removed"];
22
+ constructor(options: any);
23
+ addHandleAndSendInitialAdds(handle: ObserveHandle): Promise<void>;
24
+ removeHandle(id: number): void;
25
+ _stop(options?: any): void;
26
+ ready(): void;
27
+ queryError(err: Error): void;
28
+ onFlush(cb: any): void;
29
+ callbackNames(): string[];
30
+ _ready(): boolean;
31
+ _applyCallback(callbackName: string, args: any): Promise<void>;
32
+ }
33
+ export declare class ObserveHandle {
34
+ private _multiplexer;
35
+ nonMutatingCallbacks: boolean;
36
+ _id: number;
37
+ _initialAdds: ObserveCallbacks["initialAdds"];
38
+ _addedBefore: ObserveCallbacks["addedBefore"];
39
+ _movedBefore: ObserveCallbacks["movedBefore"];
40
+ _added: ObserveCallbacks["added"];
41
+ _changed: ObserveCallbacks["changed"];
42
+ _removed: ObserveCallbacks["removed"];
43
+ private _stopped;
44
+ constructor(_multiplexer: ObserveMultiplexer, callbacks: ObserveCallbacks, nonMutatingCallbacks?: boolean);
45
+ stop(): void;
46
+ }
@@ -1,203 +1,203 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ObserveHandle = exports.ObserveMultiplexer = void 0;
4
- const ejson_1 = require("../ejson/ejson");
5
- const caching_change_observer_1 = require("./caching_change_observer");
6
- const synchronous_queue_1 = require("./synchronous-queue");
7
- class ObserveMultiplexer {
8
- constructor(options) {
9
- this._readyFuture = { isResolved: false };
10
- var self = this;
11
- if (!options || !options.hasOwnProperty('ordered'))
12
- throw Error("must specify ordered");
13
- self._ordered = options.ordered;
14
- self._onStop = options.onStop || function () { };
15
- self._queue = new synchronous_queue_1._SynchronousQueue();
16
- self._handles = {};
17
- self._readyFuture.promise = new Promise((resolve, reject) => {
18
- self._readyFuture.resolve = resolve;
19
- self._readyFuture.reject = reject;
20
- });
21
- self._cache = new caching_change_observer_1._CachingChangeObserver({ ordered: options.ordered });
22
- // Number of addHandleAndSendInitialAdds tasks scheduled but not yet
23
- // running. removeHandle uses this to know if it's time to call the onStop
24
- // callback.
25
- self._addHandleTasksScheduledButNotPerformed = 0;
26
- for (const callbackName of self.callbackNames()) {
27
- self[callbackName] = async function ( /* ... */) {
28
- await self._applyCallback(callbackName, Array.from(arguments));
29
- };
30
- }
31
- }
32
- async addHandleAndSendInitialAdds(handle) {
33
- var self = this;
34
- // Check this before calling runTask (even though runTask does the same
35
- // check) so that we don't leak an ObserveMultiplexer on error by
36
- // incrementing _addHandleTasksScheduledButNotPerformed and never
37
- // decrementing it.
38
- //if (!self._queue.safeToRunTask())
39
- // throw new Error("Can't call observeChanges from an observe callback on the same query");
40
- ++self._addHandleTasksScheduledButNotPerformed;
41
- await self._queue.runTask(async () => {
42
- self._handles[handle._id] = handle;
43
- if (this._ready() && this._cache.docs.size > 0)
44
- handle._initialAdds(this._cache.docs);
45
- --self._addHandleTasksScheduledButNotPerformed;
46
- });
47
- // *outside* the task, since otherwise we'd deadlock
48
- await self._readyFuture.promise;
49
- }
50
- // Remove an observe handle. If it was the last observe handle, call the
51
- // onStop callback; you cannot add any more observe handles after this.
52
- //
53
- // This is not synchronized with polls and handle additions: this means that
54
- // you can safely call it from within an observe callback, but it also means
55
- // that we have to be careful when we iterate over _handles.
56
- removeHandle(id) {
57
- var self = this;
58
- // This should not be possible: you can only call removeHandle by having
59
- // access to the ObserveHandle, which isn't returned to user code until the
60
- // multiplex is ready.
61
- if (!self._ready())
62
- throw new Error("Can't remove handles until the multiplex is ready");
63
- delete self._handles[id];
64
- if (Object.keys(self._handles).length === 0 && self._addHandleTasksScheduledButNotPerformed === 0) {
65
- self._stop();
66
- }
67
- }
68
- _stop(options) {
69
- const self = this;
70
- options = options || {};
71
- // It shouldn't be possible for us to stop when all our handles still
72
- // haven't been returned from observeChanges!
73
- if (!self._ready() && !options.fromQueryError)
74
- throw Error("surprising _stop: not ready");
75
- // Call stop callback (which kills the underlying process which sends us
76
- // callbacks and removes us from the connection's dictionary).
77
- self._onStop();
78
- // Cause future addHandleAndSendInitialAdds calls to throw (but the onStop
79
- // callback should make our connection forget about us).
80
- self._handles = null;
81
- }
82
- // Allows all addHandleAndSendInitialAdds calls to return, once all preceding
83
- // adds have been processed. Does not block.
84
- ready() {
85
- this._queue.queueTask(async () => {
86
- if (this._ready())
87
- throw Error("can't make ObserveMultiplex ready twice!");
88
- if (this._cache.docs.size > 0) {
89
- for (const handleId of Object.keys(this._handles)) {
90
- var handle = this._handles && this._handles[handleId];
91
- if (handle)
92
- handle._initialAdds(this._cache.docs);
93
- }
94
- }
95
- this._readyFuture.resolve();
96
- this._readyFuture.isResolved = true;
97
- });
98
- }
99
- // If trying to execute the query results in an error, call this. This is
100
- // intended for permanent errors, not transient network errors that could be
101
- // fixed. It should only be called before ready(), because if you called ready
102
- // that meant that you managed to run the query once. It will stop this
103
- // ObserveMultiplex and cause addHandleAndSendInitialAdds calls (and thus
104
- // observeChanges calls) to throw the error.
105
- queryError(err) {
106
- var self = this;
107
- self._queue.runTask(async () => {
108
- if (self._ready())
109
- throw Error("can't claim query has an error after it worked!");
110
- self._stop({ fromQueryError: true });
111
- self._readyFuture.reject(err);
112
- });
113
- }
114
- // Calls "cb" once the effects of all "ready", "addHandleAndSendInitialAdds"
115
- // and observe callbacks which came before this call have been propagated to
116
- // all handles. "ready" must have already been called on this multiplexer.
117
- onFlush(cb) {
118
- var self = this;
119
- self._queue.queueTask(async () => {
120
- if (!self._ready())
121
- throw Error("only call onFlush on a multiplexer that will be ready");
122
- cb();
123
- });
124
- }
125
- callbackNames() {
126
- var self = this;
127
- if (self._ordered)
128
- return ["initialAdds", "addedBefore", "changed", "movedBefore", "removed"];
129
- else
130
- return ["initialAdds", "added", "changed", "removed"];
131
- }
132
- _ready() {
133
- return this._readyFuture.isResolved;
134
- }
135
- async _applyCallback(callbackName, args) {
136
- var self = this;
137
- self._queue.queueTask(async () => {
138
- // If we stopped in the meantime, do nothing.
139
- if (!self._handles)
140
- return;
141
- // First, apply the change to the cache.
142
- self._cache.applyChange[callbackName].apply(null, args);
143
- // If we haven't finished the initial adds, then we should only be getting
144
- // adds.
145
- if (!self._ready() &&
146
- (callbackName !== 'added' && callbackName !== 'addedBefore')) {
147
- throw new Error("Got " + callbackName + " during initial adds");
148
- }
149
- // don't actually send anything to the handles until initial adds are cached
150
- if (!self._ready())
151
- return;
152
- // Now multiplex the callbacks out to all observe handles. It's OK if
153
- // these calls yield; since we're inside a task, no other use of our queue
154
- // can continue until these are done. (But we do have to be careful to not
155
- // use a handle that got removed, because removeHandle does not use the
156
- // queue; thus, we iterate over an array of keys that we control.)
157
- for (const handleId of Object.keys(self._handles)) {
158
- var handle = self._handles && self._handles[handleId];
159
- if (!handle)
160
- return;
161
- var callback = handle['_' + callbackName];
162
- // clone arguments so that callbacks can mutate their arguments
163
- callback && callback.apply(null, handle.nonMutatingCallbacks ? args : (0, ejson_1.clone)(args));
164
- }
165
- });
166
- }
167
- }
168
- exports.ObserveMultiplexer = ObserveMultiplexer;
169
- let nextObserveHandleId = 1;
170
- // When the callbacks do not mutate the arguments, we can skip a lot of data clones
171
- class ObserveHandle {
172
- constructor(_multiplexer, callbacks, nonMutatingCallbacks = false) {
173
- this._multiplexer = _multiplexer;
174
- this.nonMutatingCallbacks = nonMutatingCallbacks;
175
- var self = this;
176
- // The end user is only supposed to call stop(). The other fields are
177
- // accessible to the multiplexer, though.
178
- for (const name of _multiplexer.callbackNames()) {
179
- if (callbacks[name]) {
180
- self['_' + name] = callbacks[name];
181
- }
182
- else if (name === "addedBefore" && callbacks.added) {
183
- // Special case: if you specify "added" and "movedBefore", you get an
184
- // ordered observe where for some reason you don't get ordering data on
185
- // the adds. I dunno, we wrote tests for it, there must have been a
186
- // reason.
187
- self._addedBefore = function (id, fields, before) {
188
- callbacks.added(id, fields);
189
- };
190
- }
191
- }
192
- self._stopped = false;
193
- self._id = nextObserveHandleId++;
194
- }
195
- stop() {
196
- var self = this;
197
- if (self._stopped)
198
- return;
199
- self._stopped = true;
200
- self._multiplexer.removeHandle(self._id);
201
- }
202
- }
203
- exports.ObserveHandle = ObserveHandle;
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ObserveHandle = exports.ObserveMultiplexer = void 0;
4
+ const ejson_1 = require("../ejson/ejson");
5
+ const caching_change_observer_1 = require("./caching_change_observer");
6
+ const synchronous_queue_1 = require("./synchronous-queue");
7
+ class ObserveMultiplexer {
8
+ constructor(options) {
9
+ this._readyFuture = { isResolved: false };
10
+ var self = this;
11
+ if (!options || !options.hasOwnProperty('ordered'))
12
+ throw Error("must specify ordered");
13
+ self._ordered = options.ordered;
14
+ self._onStop = options.onStop || function () { };
15
+ self._queue = new synchronous_queue_1._SynchronousQueue();
16
+ self._handles = {};
17
+ self._readyFuture.promise = new Promise((resolve, reject) => {
18
+ self._readyFuture.resolve = resolve;
19
+ self._readyFuture.reject = reject;
20
+ });
21
+ self._cache = new caching_change_observer_1._CachingChangeObserver({ ordered: options.ordered });
22
+ // Number of addHandleAndSendInitialAdds tasks scheduled but not yet
23
+ // running. removeHandle uses this to know if it's time to call the onStop
24
+ // callback.
25
+ self._addHandleTasksScheduledButNotPerformed = 0;
26
+ for (const callbackName of self.callbackNames()) {
27
+ self[callbackName] = async function ( /* ... */) {
28
+ await self._applyCallback(callbackName, Array.from(arguments));
29
+ };
30
+ }
31
+ }
32
+ async addHandleAndSendInitialAdds(handle) {
33
+ var self = this;
34
+ // Check this before calling runTask (even though runTask does the same
35
+ // check) so that we don't leak an ObserveMultiplexer on error by
36
+ // incrementing _addHandleTasksScheduledButNotPerformed and never
37
+ // decrementing it.
38
+ //if (!self._queue.safeToRunTask())
39
+ // throw new Error("Can't call observeChanges from an observe callback on the same query");
40
+ ++self._addHandleTasksScheduledButNotPerformed;
41
+ await self._queue.runTask(async () => {
42
+ self._handles[handle._id] = handle;
43
+ if (this._ready() && this._cache.docs.size > 0)
44
+ handle._initialAdds(this._cache.docs);
45
+ --self._addHandleTasksScheduledButNotPerformed;
46
+ });
47
+ // *outside* the task, since otherwise we'd deadlock
48
+ await self._readyFuture.promise;
49
+ }
50
+ // Remove an observe handle. If it was the last observe handle, call the
51
+ // onStop callback; you cannot add any more observe handles after this.
52
+ //
53
+ // This is not synchronized with polls and handle additions: this means that
54
+ // you can safely call it from within an observe callback, but it also means
55
+ // that we have to be careful when we iterate over _handles.
56
+ removeHandle(id) {
57
+ var self = this;
58
+ // This should not be possible: you can only call removeHandle by having
59
+ // access to the ObserveHandle, which isn't returned to user code until the
60
+ // multiplex is ready.
61
+ if (!self._ready())
62
+ throw new Error("Can't remove handles until the multiplex is ready");
63
+ delete self._handles[id];
64
+ if (Object.keys(self._handles).length === 0 && self._addHandleTasksScheduledButNotPerformed === 0) {
65
+ self._stop();
66
+ }
67
+ }
68
+ _stop(options) {
69
+ const self = this;
70
+ options = options || {};
71
+ // It shouldn't be possible for us to stop when all our handles still
72
+ // haven't been returned from observeChanges!
73
+ if (!self._ready() && !options.fromQueryError)
74
+ throw Error("surprising _stop: not ready");
75
+ // Call stop callback (which kills the underlying process which sends us
76
+ // callbacks and removes us from the connection's dictionary).
77
+ self._onStop();
78
+ // Cause future addHandleAndSendInitialAdds calls to throw (but the onStop
79
+ // callback should make our connection forget about us).
80
+ self._handles = null;
81
+ }
82
+ // Allows all addHandleAndSendInitialAdds calls to return, once all preceding
83
+ // adds have been processed. Does not block.
84
+ ready() {
85
+ this._queue.queueTask(async () => {
86
+ if (this._ready())
87
+ throw Error("can't make ObserveMultiplex ready twice!");
88
+ if (this._cache.docs.size > 0) {
89
+ for (const handleId of Object.keys(this._handles)) {
90
+ var handle = this._handles && this._handles[handleId];
91
+ if (handle)
92
+ handle._initialAdds(this._cache.docs);
93
+ }
94
+ }
95
+ this._readyFuture.resolve();
96
+ this._readyFuture.isResolved = true;
97
+ });
98
+ }
99
+ // If trying to execute the query results in an error, call this. This is
100
+ // intended for permanent errors, not transient network errors that could be
101
+ // fixed. It should only be called before ready(), because if you called ready
102
+ // that meant that you managed to run the query once. It will stop this
103
+ // ObserveMultiplex and cause addHandleAndSendInitialAdds calls (and thus
104
+ // observeChanges calls) to throw the error.
105
+ queryError(err) {
106
+ var self = this;
107
+ self._queue.runTask(async () => {
108
+ if (self._ready())
109
+ throw Error("can't claim query has an error after it worked!");
110
+ self._stop({ fromQueryError: true });
111
+ self._readyFuture.reject(err);
112
+ });
113
+ }
114
+ // Calls "cb" once the effects of all "ready", "addHandleAndSendInitialAdds"
115
+ // and observe callbacks which came before this call have been propagated to
116
+ // all handles. "ready" must have already been called on this multiplexer.
117
+ onFlush(cb) {
118
+ var self = this;
119
+ self._queue.queueTask(async () => {
120
+ if (!self._ready())
121
+ throw Error("only call onFlush on a multiplexer that will be ready");
122
+ cb();
123
+ });
124
+ }
125
+ callbackNames() {
126
+ var self = this;
127
+ if (self._ordered)
128
+ return ["initialAdds", "addedBefore", "changed", "movedBefore", "removed"];
129
+ else
130
+ return ["initialAdds", "added", "changed", "removed"];
131
+ }
132
+ _ready() {
133
+ return this._readyFuture.isResolved;
134
+ }
135
+ async _applyCallback(callbackName, args) {
136
+ var self = this;
137
+ self._queue.queueTask(async () => {
138
+ // If we stopped in the meantime, do nothing.
139
+ if (!self._handles)
140
+ return;
141
+ // First, apply the change to the cache.
142
+ self._cache.applyChange[callbackName].apply(null, args);
143
+ // If we haven't finished the initial adds, then we should only be getting
144
+ // adds.
145
+ if (!self._ready() &&
146
+ (callbackName !== 'added' && callbackName !== 'addedBefore')) {
147
+ throw new Error("Got " + callbackName + " during initial adds");
148
+ }
149
+ // don't actually send anything to the handles until initial adds are cached
150
+ if (!self._ready())
151
+ return;
152
+ // Now multiplex the callbacks out to all observe handles. It's OK if
153
+ // these calls yield; since we're inside a task, no other use of our queue
154
+ // can continue until these are done. (But we do have to be careful to not
155
+ // use a handle that got removed, because removeHandle does not use the
156
+ // queue; thus, we iterate over an array of keys that we control.)
157
+ for (const handleId of Object.keys(self._handles)) {
158
+ var handle = self._handles && self._handles[handleId];
159
+ if (!handle)
160
+ return;
161
+ var callback = handle['_' + callbackName];
162
+ // clone arguments so that callbacks can mutate their arguments
163
+ callback && callback.apply(null, handle.nonMutatingCallbacks ? args : (0, ejson_1.clone)(args));
164
+ }
165
+ });
166
+ }
167
+ }
168
+ exports.ObserveMultiplexer = ObserveMultiplexer;
169
+ let nextObserveHandleId = 1;
170
+ // When the callbacks do not mutate the arguments, we can skip a lot of data clones
171
+ class ObserveHandle {
172
+ constructor(_multiplexer, callbacks, nonMutatingCallbacks = false) {
173
+ this._multiplexer = _multiplexer;
174
+ this.nonMutatingCallbacks = nonMutatingCallbacks;
175
+ var self = this;
176
+ // The end user is only supposed to call stop(). The other fields are
177
+ // accessible to the multiplexer, though.
178
+ for (const name of _multiplexer.callbackNames()) {
179
+ if (callbacks[name]) {
180
+ self['_' + name] = callbacks[name];
181
+ }
182
+ else if (name === "addedBefore" && callbacks.added) {
183
+ // Special case: if you specify "added" and "movedBefore", you get an
184
+ // ordered observe where for some reason you don't get ordering data on
185
+ // the adds. I dunno, we wrote tests for it, there must have been a
186
+ // reason.
187
+ self._addedBefore = function (id, fields, before) {
188
+ callbacks.added(id, fields);
189
+ };
190
+ }
191
+ }
192
+ self._stopped = false;
193
+ self._id = nextObserveHandleId++;
194
+ }
195
+ stop() {
196
+ var self = this;
197
+ if (self._stopped)
198
+ return;
199
+ self._stopped = true;
200
+ self._multiplexer.removeHandle(self._id);
201
+ }
202
+ }
203
+ exports.ObserveHandle = ObserveHandle;