@nxtedition/deepstream.io-client-js 23.4.35 → 23.4.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxtedition/deepstream.io-client-js",
3
- "version": "23.4.35",
3
+ "version": "23.4.37",
4
4
  "description": "the javascript client for deepstream.io",
5
5
  "homepage": "http://deepstream.io",
6
6
  "bugs": {
@@ -124,7 +124,7 @@ class RecordHandler {
124
124
  if (!record) {
125
125
  record = new Record(name, this)
126
126
  this._records.set(name, record)
127
- this._stats.destroyed--
127
+ this._stats.created++
128
128
  } else {
129
129
  record.ref()
130
130
  }
@@ -163,122 +163,55 @@ class RecordHandler {
163
163
  }
164
164
  }
165
165
 
166
- sync(options) {
167
- return new Promise((resolve, reject) => {
168
- const timeoutValue = options?.timeout ?? 2 * 60e3
169
- const signal = options?.signal
170
-
171
- if (signal?.aborted) {
172
- reject(new utils.AbortError())
173
- return
174
- }
175
-
176
- let done = false
177
- let token
178
- let timeoutHandle
179
-
180
- const records = [...this._pending]
166
+ sync() {
167
+ return new Promise((resolve) => {
168
+ let counter = 0
181
169
 
182
- const onDone = (val) => {
183
- if (done) {
170
+ const onUpdate = (rec) => {
171
+ if (rec.pending) {
184
172
  return
185
173
  }
186
174
 
187
- done = true
175
+ rec.unsubscribe(onUpdate)
176
+ rec.unref()
177
+ counter -= 1
188
178
 
189
- signal?.removeEventListener('abort', onAbort)
190
-
191
- if (timeoutHandle) {
192
- timers.clearTimeout(timeoutHandle)
193
- timeoutHandle = null
179
+ if (counter > 0) {
180
+ return
194
181
  }
195
182
 
196
- if (token) {
197
- this._syncEmitter.off(token, onToken)
198
- token = null
199
- }
183
+ if (!this._syncQueue) {
184
+ this._syncQueue = []
185
+ queueMicrotask(() => {
186
+ const syncQueue = this._syncQueue
187
+ if (!syncQueue) {
188
+ return
189
+ }
190
+
191
+ const token = xuid()
192
+
193
+ this._syncQueue = null
194
+ this._syncEmitter.once(token, () => {
195
+ for (const callback of syncQueue) {
196
+ callback()
197
+ }
198
+ })
200
199
 
201
- for (const rec of records) {
202
- rec.unref()
200
+ if (this._connected) {
201
+ this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SYNC, [token])
202
+ }
203
+ })
203
204
  }
204
205
 
205
- resolve(val)
206
- }
207
-
208
- const onToken = () => {
209
- onDone(true)
210
- }
211
-
212
- const onAbort = () => {
213
- onDone(Promise.reject(new utils.AbortError()))
206
+ this._syncQueue.push(resolve)
214
207
  }
215
208
 
216
- const onTimeout = () => {
217
- const elapsed = Date.now() - this._connected
218
- if (elapsed < timeoutValue) {
219
- timeoutHandle = timers.setTimeout(onTimeout, timeoutValue - elapsed)
220
- } else {
221
- for (const rec of records.filter((rec) => !rec.isReady)) {
222
- this._client._$onError(C.TOPIC.RECORD, C.EVENT.TIMEOUT, 'record timeout', [
223
- rec.name,
224
- rec.version,
225
- rec.state,
226
- ...(rec._entry ?? []),
227
- ])
228
- }
229
-
230
- this._client._$onError(C.TOPIC.RECORD, C.EVENT.TIMEOUT, 'sync timeout', [token])
231
-
232
- onDone(false)
233
- }
234
- }
235
-
236
- for (const rec of records) {
209
+ for (const rec of this._pending) {
237
210
  rec.ref()
238
- }
239
-
240
- if (timeoutValue) {
241
- timeoutHandle = timers.setTimeout(onTimeout, timeoutValue)
242
- }
243
-
244
- signal?.addEventListener('abort', onAbort)
245
-
246
- Promise.all(records.map((rec) => rec.when())).then(
247
- () => {
248
- if (done) {
249
- return
250
- }
251
-
252
- if (!this._syncQueue) {
253
- this._syncQueue = []
254
- queueMicrotask(this._syncAll)
255
- }
256
-
257
- this._syncQueue.push(onToken)
258
- },
259
- (err) => onDone(Promise.reject(err))
260
- )
261
- })
262
- }
263
-
264
- _syncAll() {
265
- if (!this._syncQueue) {
266
- return
267
- }
268
-
269
- const syncQueue = this._syncQueue
270
- const token = xuid()
271
-
272
- this._syncQueue = null
273
- this._syncEmitter.once(token, () => {
274
- for (const callback of syncQueue) {
275
- callback()
211
+ rec.subscribe(onUpdate)
212
+ counter += 1
276
213
  }
277
214
  })
278
-
279
- if (this._connected) {
280
- this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SYNC, [token])
281
- }
282
215
  }
283
216
 
284
217
  set(name, ...args) {
@@ -19,6 +19,7 @@ class Record {
19
19
  this._refs = 1
20
20
  this._subscribed = false
21
21
  this._subscriptions = []
22
+ this._subscriptionsEmitting = false
22
23
  this._updating = null
23
24
  this._patches = null
24
25
  this._pending = false
@@ -72,12 +73,22 @@ class Record {
72
73
  }
73
74
 
74
75
  subscribe(fn) {
76
+ if (this._subscriptionsEmitting) {
77
+ this._subscriptions = this._subscriptions.slice()
78
+ this._subscriptionsEmitting = false
79
+ }
80
+
75
81
  this._subscriptions.push(fn)
76
82
 
77
83
  return this
78
84
  }
79
85
 
80
86
  unsubscribe(fn) {
87
+ if (this._subscriptionsEmitting) {
88
+ this._subscriptions = this._subscriptions.slice()
89
+ this._subscriptionsEmitting = false
90
+ }
91
+
81
92
  const idx = this._subscriptions.indexOf(fn)
82
93
  if (idx !== -1) {
83
94
  this._subscriptions.splice(idx, 1)
@@ -200,8 +211,13 @@ class Record {
200
211
  }
201
212
 
202
213
  _emitUpdate() {
203
- for (const fn of this._subscriptions.slice()) {
204
- fn(this)
214
+ try {
215
+ this._subscriptionsEmitting = true
216
+ for (const fn of this._subscriptions) {
217
+ fn(this)
218
+ }
219
+ } finally {
220
+ this._subscriptionsEmitting = false
205
221
  }
206
222
  }
207
223
 
@@ -266,6 +282,7 @@ class Record {
266
282
  if (!this._pending) {
267
283
  this._pending = true
268
284
  this._handler._onPending(this)
285
+ this._emitUpdate()
269
286
  }
270
287
 
271
288
  const connection = this._handler._connection
@@ -305,6 +322,7 @@ class Record {
305
322
  const prevData = this._data
306
323
  const prevVersion = this._version
307
324
  const prevState = this._state
325
+ const prevPending = this._pending
308
326
 
309
327
  if (this._updating?.delete(version)) {
310
328
  this._handler._stats.updating -= 1
@@ -337,7 +355,12 @@ class Record {
337
355
  this._state = this._version.charAt(0) === 'I' ? Record.STATE.STALE : Record.STATE.SERVER
338
356
  }
339
357
 
340
- if (this._data !== prevData || this._version !== prevVersion || this._state !== prevState) {
358
+ if (
359
+ this._data !== prevData ||
360
+ this._version !== prevVersion ||
361
+ this._state !== prevState ||
362
+ this._pending !== prevPending
363
+ ) {
341
364
  this._emitUpdate()
342
365
  }
343
366
  }