@nxtedition/deepstream.io-client-js 23.3.6 → 23.4.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.
- package/package.json +1 -1
- package/src/default-options.js +0 -2
- package/src/message/connection.js +9 -43
- package/src/record/record-handler.js +43 -74
- package/src/record/record.js +14 -3
package/package.json
CHANGED
package/src/default-options.js
CHANGED
|
@@ -32,8 +32,6 @@ const Connection = function (client, url, options) {
|
|
|
32
32
|
this._reconnectTimeout = null
|
|
33
33
|
this._reconnectionAttempt = 0
|
|
34
34
|
this._endpoint = null
|
|
35
|
-
this._lastHeartBeat = null
|
|
36
|
-
this._heartbeatInterval = null
|
|
37
35
|
|
|
38
36
|
this._processingRecv = false
|
|
39
37
|
this._recvMessages = this._recvMessages.bind(this)
|
|
@@ -96,7 +94,7 @@ Connection.prototype.sendMsg2 = function (topic, action, p0, p1) {
|
|
|
96
94
|
}
|
|
97
95
|
|
|
98
96
|
Connection.prototype.close = function () {
|
|
99
|
-
while (this._sendQueue.
|
|
97
|
+
while (!this._sendQueue.isEmpty()) {
|
|
100
98
|
this._submit(this._sendQueue.shift())
|
|
101
99
|
}
|
|
102
100
|
this._reset()
|
|
@@ -199,27 +197,8 @@ Connection.prototype._sendAuthParams = function () {
|
|
|
199
197
|
this._submit(authMessage)
|
|
200
198
|
}
|
|
201
199
|
|
|
202
|
-
Connection.prototype._checkHeartBeat = function () {
|
|
203
|
-
const heartBeatTolerance = this._options.heartbeatInterval * 3
|
|
204
|
-
|
|
205
|
-
if (Date.now() - this._lastHeartBeat > heartBeatTolerance) {
|
|
206
|
-
clearInterval(this._heartbeatInterval)
|
|
207
|
-
this._endpoint.close()
|
|
208
|
-
const err = new Error(`heartbeat not received in the last ${heartBeatTolerance} milliseconds`)
|
|
209
|
-
this._client._$onError(C.TOPIC.CONNECTION, C.EVENT.CONNECTION_ERROR, err)
|
|
210
|
-
} else {
|
|
211
|
-
this._submit(messageBuilder.getMsg(C.TOPIC.CONNECTION, C.ACTIONS.PING))
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
200
|
Connection.prototype._onOpen = function () {
|
|
216
201
|
this._clearReconnect()
|
|
217
|
-
this._lastHeartBeat = Date.now()
|
|
218
|
-
this._heartbeatInterval = setInterval(
|
|
219
|
-
this._checkHeartBeat.bind(this),
|
|
220
|
-
this._options.heartbeatInterval
|
|
221
|
-
)
|
|
222
|
-
this._heartbeatInterval.unref?.()
|
|
223
202
|
this._setState(C.CONNECTION_STATE.AWAITING_CONNECTION)
|
|
224
203
|
}
|
|
225
204
|
|
|
@@ -306,20 +285,13 @@ Connection.prototype._recvMessages = function (deadline) {
|
|
|
306
285
|
}
|
|
307
286
|
|
|
308
287
|
Connection.prototype._reset = function () {
|
|
309
|
-
clearInterval(this._heartbeatInterval)
|
|
310
|
-
this._heartbeatInterval = null
|
|
311
|
-
this._lastHeartBeat = null
|
|
312
|
-
|
|
313
288
|
this._recvQueue = new FixedQueue()
|
|
314
289
|
this._sendQueue = new FixedQueue()
|
|
315
290
|
}
|
|
316
291
|
|
|
317
292
|
Connection.prototype._handleConnectionResponse = function (message) {
|
|
318
293
|
if (message.action === C.ACTIONS.PING) {
|
|
319
|
-
this._lastHeartBeat = Date.now()
|
|
320
294
|
this._submit(messageBuilder.getMsg(C.TOPIC.CONNECTION, C.ACTIONS.PONG))
|
|
321
|
-
} else if (message.action === C.ACTIONS.PONG) {
|
|
322
|
-
this._lastHeartBeat = Date.now()
|
|
323
295
|
} else if (message.action === C.ACTIONS.ACK) {
|
|
324
296
|
this._setState(C.CONNECTION_STATE.AWAITING_AUTHENTICATION)
|
|
325
297
|
if (this._authParams) {
|
|
@@ -394,13 +366,10 @@ Connection.prototype._tryReconnect = function () {
|
|
|
394
366
|
|
|
395
367
|
if (this._reconnectionAttempt < this._options.maxReconnectAttempts) {
|
|
396
368
|
this._setState(C.CONNECTION_STATE.RECONNECTING)
|
|
397
|
-
this._reconnectTimeout = setTimeout(
|
|
398
|
-
this.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
this._options.reconnectIntervalIncrement * this._reconnectionAttempt
|
|
402
|
-
)
|
|
403
|
-
)
|
|
369
|
+
this._reconnectTimeout = setTimeout(() => {
|
|
370
|
+
this._reconnectTimeout = null
|
|
371
|
+
this._createEndpoint()
|
|
372
|
+
}, Math.min(this._options.maxReconnectInterval, this._options.reconnectIntervalIncrement * this._reconnectionAttempt))
|
|
404
373
|
this._reconnectionAttempt++
|
|
405
374
|
} else {
|
|
406
375
|
this._clearReconnect()
|
|
@@ -409,14 +378,11 @@ Connection.prototype._tryReconnect = function () {
|
|
|
409
378
|
}
|
|
410
379
|
}
|
|
411
380
|
|
|
412
|
-
Connection.prototype._tryOpen = function () {
|
|
413
|
-
this._createEndpoint()
|
|
414
|
-
this._reconnectTimeout = null
|
|
415
|
-
}
|
|
416
|
-
|
|
417
381
|
Connection.prototype._clearReconnect = function () {
|
|
418
|
-
|
|
419
|
-
|
|
382
|
+
if (this._reconnectTimeout) {
|
|
383
|
+
clearTimeout(this._reconnectTimeout)
|
|
384
|
+
this._reconnectTimeout = null
|
|
385
|
+
}
|
|
420
386
|
this._reconnectionAttempt = 0
|
|
421
387
|
}
|
|
422
388
|
|
|
@@ -24,7 +24,6 @@ class RecordHandler {
|
|
|
24
24
|
this._records = new Map()
|
|
25
25
|
this._listeners = new Map()
|
|
26
26
|
this._prune = new Map()
|
|
27
|
-
this._purge = new Set()
|
|
28
27
|
this._patch = new Set()
|
|
29
28
|
this._now = Date.now()
|
|
30
29
|
this._pruning = false
|
|
@@ -34,8 +33,6 @@ class RecordHandler {
|
|
|
34
33
|
updating: 0,
|
|
35
34
|
}
|
|
36
35
|
|
|
37
|
-
this._purgeCapacity = options.cacheSize
|
|
38
|
-
|
|
39
36
|
this._syncEmitter = new EventEmitter()
|
|
40
37
|
|
|
41
38
|
this.set = this.set.bind(this)
|
|
@@ -52,8 +49,6 @@ class RecordHandler {
|
|
|
52
49
|
this._client.on(C.EVENT.CONNECTED, this._onConnectionStateChange.bind(this))
|
|
53
50
|
|
|
54
51
|
const prune = () => {
|
|
55
|
-
this._pruning = false
|
|
56
|
-
|
|
57
52
|
let counter = 0
|
|
58
53
|
for (const [rec, timestamp] of this._prune) {
|
|
59
54
|
if (this._now - timestamp < 1e3) {
|
|
@@ -64,59 +59,26 @@ class RecordHandler {
|
|
|
64
59
|
continue
|
|
65
60
|
}
|
|
66
61
|
|
|
67
|
-
invariant(rec._refs === 0, 'record must have no refs')
|
|
68
|
-
|
|
69
62
|
rec._unsubscribe()
|
|
70
63
|
|
|
71
|
-
this.
|
|
64
|
+
this._records.delete(rec.name)
|
|
72
65
|
this._prune.delete(rec)
|
|
73
66
|
|
|
74
67
|
if (counter++ > 1024) {
|
|
75
|
-
this._pruning = true
|
|
76
68
|
this._schedule(prune)
|
|
77
69
|
return
|
|
78
70
|
}
|
|
79
71
|
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const purge = () => {
|
|
83
|
-
this._purging = false
|
|
84
72
|
|
|
85
|
-
|
|
86
|
-
return
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
let counter = 0
|
|
90
|
-
for (const rec of this._purge) {
|
|
91
|
-
if (this._purge.size < this._purgeCapacity) {
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
invariant(rec._refs === 0, 'record must have no refs')
|
|
96
|
-
|
|
97
|
-
this._records.delete(rec.name)
|
|
98
|
-
this._purge.delete(rec)
|
|
99
|
-
|
|
100
|
-
if (counter++ > 1024) {
|
|
101
|
-
this._purging = true
|
|
102
|
-
this._schedule(purge)
|
|
103
|
-
return
|
|
104
|
-
}
|
|
105
|
-
}
|
|
73
|
+
this._pruning = false
|
|
106
74
|
}
|
|
107
75
|
|
|
108
76
|
const pruneInterval = setInterval(() => {
|
|
109
77
|
this._now = Date.now()
|
|
110
|
-
|
|
111
78
|
if (!this._pruning) {
|
|
112
79
|
this._pruning = true
|
|
113
80
|
this._schedule(prune)
|
|
114
81
|
}
|
|
115
|
-
|
|
116
|
-
if (!this._purging) {
|
|
117
|
-
this._purging = true
|
|
118
|
-
this._schedule(purge)
|
|
119
|
-
}
|
|
120
82
|
}, 1e3)
|
|
121
83
|
pruneInterval.unref?.()
|
|
122
84
|
}
|
|
@@ -125,7 +87,6 @@ class RecordHandler {
|
|
|
125
87
|
if (rec.refs === 0) {
|
|
126
88
|
this._prune.set(rec, this._now)
|
|
127
89
|
} else if (rec.refs === 1) {
|
|
128
|
-
this._purge.delete(rec)
|
|
129
90
|
this._prune.delete(rec)
|
|
130
91
|
}
|
|
131
92
|
}
|
|
@@ -140,7 +101,6 @@ class RecordHandler {
|
|
|
140
101
|
listeners: this._listeners.size,
|
|
141
102
|
records: this._records.size,
|
|
142
103
|
pruning: this._prune.size,
|
|
143
|
-
purging: this._purge.size,
|
|
144
104
|
}
|
|
145
105
|
}
|
|
146
106
|
|
|
@@ -194,13 +154,19 @@ class RecordHandler {
|
|
|
194
154
|
}
|
|
195
155
|
|
|
196
156
|
sync(options) {
|
|
197
|
-
return new Promise((resolve) => {
|
|
157
|
+
return new Promise((resolve, reject) => {
|
|
158
|
+
const timeoutValue = options?.timeout ?? 2 * 60e3
|
|
159
|
+
const signal = options?.signal
|
|
160
|
+
|
|
161
|
+
if (signal?.aborted) {
|
|
162
|
+
reject(new utils.AbortError())
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
198
166
|
let done = false
|
|
199
167
|
let token
|
|
200
|
-
let
|
|
168
|
+
let timeoutHandle
|
|
201
169
|
|
|
202
|
-
const timeoutValue = 2 * 60e3
|
|
203
|
-
const signal = options?.signal
|
|
204
170
|
const records = [...this._patch]
|
|
205
171
|
|
|
206
172
|
const onDone = (val) => {
|
|
@@ -212,9 +178,9 @@ class RecordHandler {
|
|
|
212
178
|
|
|
213
179
|
signal?.removeEventListener('abort', onAbort)
|
|
214
180
|
|
|
215
|
-
if (
|
|
216
|
-
clearTimeout(
|
|
217
|
-
|
|
181
|
+
if (timeoutHandle) {
|
|
182
|
+
clearTimeout(timeoutHandle)
|
|
183
|
+
timeoutHandle = null
|
|
218
184
|
}
|
|
219
185
|
|
|
220
186
|
if (token) {
|
|
@@ -240,8 +206,8 @@ class RecordHandler {
|
|
|
240
206
|
const onTimeout = () => {
|
|
241
207
|
const elapsed = Date.now() - this._connected
|
|
242
208
|
if (elapsed < timeoutValue) {
|
|
243
|
-
|
|
244
|
-
|
|
209
|
+
timeoutHandle = setTimeout(onTimeout, timeoutValue - elapsed)
|
|
210
|
+
timeoutHandle.unref?.()
|
|
245
211
|
} else {
|
|
246
212
|
for (const rec of records.filter((rec) => !rec.isReady)) {
|
|
247
213
|
this._client._$onError(C.TOPIC.RECORD, C.EVENT.TIMEOUT, 'record timeout', [
|
|
@@ -262,8 +228,10 @@ class RecordHandler {
|
|
|
262
228
|
rec.ref()
|
|
263
229
|
}
|
|
264
230
|
|
|
265
|
-
|
|
266
|
-
|
|
231
|
+
if (timeoutValue) {
|
|
232
|
+
timeoutHandle = setTimeout(onTimeout, timeoutValue)
|
|
233
|
+
timeoutHandle.unref?.()
|
|
234
|
+
}
|
|
267
235
|
|
|
268
236
|
signal?.addEventListener('abort', onAbort)
|
|
269
237
|
|
|
@@ -337,7 +305,7 @@ class RecordHandler {
|
|
|
337
305
|
let path
|
|
338
306
|
let state = defaults ? defaults.state : undefined
|
|
339
307
|
let signal
|
|
340
|
-
let
|
|
308
|
+
let timeoutValue = defaults ? defaults.timeout : undefined
|
|
341
309
|
let dataOnly = defaults ? defaults.dataOnly : undefined
|
|
342
310
|
|
|
343
311
|
let idx = 0
|
|
@@ -356,7 +324,7 @@ class RecordHandler {
|
|
|
356
324
|
signal = options.signal
|
|
357
325
|
|
|
358
326
|
if (options.timeout != null) {
|
|
359
|
-
|
|
327
|
+
timeoutValue = options.timeout
|
|
360
328
|
}
|
|
361
329
|
|
|
362
330
|
if (options.path != null) {
|
|
@@ -390,7 +358,11 @@ class RecordHandler {
|
|
|
390
358
|
)
|
|
391
359
|
}
|
|
392
360
|
|
|
393
|
-
|
|
361
|
+
if (signal?.aborted) {
|
|
362
|
+
return rxjs.throwError(() => new utils.AbortError())
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return new rxjs.Observable((o) => {
|
|
394
366
|
let timeoutHandle
|
|
395
367
|
let prevData = kEmpty
|
|
396
368
|
|
|
@@ -404,8 +376,9 @@ class RecordHandler {
|
|
|
404
376
|
timeoutHandle = null
|
|
405
377
|
}
|
|
406
378
|
|
|
379
|
+
const nextData = path ? record.get(path) : record.data
|
|
380
|
+
|
|
407
381
|
if (dataOnly) {
|
|
408
|
-
const nextData = record.get(path)
|
|
409
382
|
if (nextData !== prevData) {
|
|
410
383
|
prevData = nextData
|
|
411
384
|
o.next(nextData)
|
|
@@ -414,27 +387,25 @@ class RecordHandler {
|
|
|
414
387
|
o.next({
|
|
415
388
|
name: record.name,
|
|
416
389
|
version: record.version,
|
|
417
|
-
data:
|
|
390
|
+
data: nextData,
|
|
418
391
|
state: record.state,
|
|
419
392
|
})
|
|
420
393
|
}
|
|
421
394
|
}
|
|
422
395
|
|
|
423
|
-
const record = this.getRecord(name)
|
|
424
|
-
|
|
425
|
-
record.subscribe(onUpdate)
|
|
396
|
+
const record = this.getRecord(name).subscribe(onUpdate)
|
|
426
397
|
|
|
427
|
-
if (
|
|
398
|
+
if (timeoutValue && state && record.state < state) {
|
|
428
399
|
timeoutHandle = setTimeout(() => {
|
|
429
400
|
const expected = C.RECORD_STATE_NAME[state]
|
|
430
401
|
const current = C.RECORD_STATE_NAME[record.state]
|
|
431
402
|
o.error(
|
|
432
403
|
Object.assign(
|
|
433
|
-
new Error(`timeout after ${
|
|
404
|
+
new Error(`timeout after ${timeoutValue / 1e3}s: ${name} [${current}<${expected}]`),
|
|
434
405
|
{ code: 'ETIMEDOUT' }
|
|
435
406
|
)
|
|
436
407
|
)
|
|
437
|
-
},
|
|
408
|
+
}, timeoutValue)
|
|
438
409
|
timeoutHandle.unref?.()
|
|
439
410
|
}
|
|
440
411
|
|
|
@@ -442,19 +413,17 @@ class RecordHandler {
|
|
|
442
413
|
onUpdate(record)
|
|
443
414
|
}
|
|
444
415
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
record.unref()
|
|
416
|
+
const abort = () => {
|
|
417
|
+
o.error(new utils.AbortError())
|
|
448
418
|
}
|
|
449
|
-
})
|
|
450
419
|
|
|
451
|
-
|
|
452
|
-
// TODO (perf): This a slow way to implement.
|
|
453
|
-
x$ = signal.aborted ? rxjs.EMPTY : x$.pipe(rx.takeUntil(rxjs.fromEvent(signal, 'abort')))
|
|
454
|
-
x$ = x$.pipe(rx.throwIfEmpty(() => new utils.AbortError()))
|
|
455
|
-
}
|
|
420
|
+
signal?.addEventListener('abort', abort)
|
|
456
421
|
|
|
457
|
-
|
|
422
|
+
return () => {
|
|
423
|
+
record.unsubscribe(onUpdate).unref()
|
|
424
|
+
signal?.removeEventListener('abort', abort)
|
|
425
|
+
}
|
|
426
|
+
})
|
|
458
427
|
}
|
|
459
428
|
|
|
460
429
|
_$handle(message) {
|
package/src/record/record.js
CHANGED
|
@@ -46,21 +46,29 @@ class Record {
|
|
|
46
46
|
|
|
47
47
|
ref() {
|
|
48
48
|
this._refs += 1
|
|
49
|
-
this._handler._onRef(this)
|
|
50
49
|
if (this._refs === 1) {
|
|
51
50
|
this._subscribe()
|
|
52
51
|
}
|
|
52
|
+
|
|
53
|
+
this._handler._onRef(this)
|
|
54
|
+
|
|
55
|
+
return this
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
unref() {
|
|
56
59
|
invariant(this._refs > 0, this._name + ' missing refs')
|
|
57
60
|
|
|
58
61
|
this._refs -= 1
|
|
62
|
+
|
|
59
63
|
this._handler._onRef(this)
|
|
64
|
+
|
|
65
|
+
return this
|
|
60
66
|
}
|
|
61
67
|
|
|
62
68
|
subscribe(fn) {
|
|
63
69
|
this._subscriptions.push(fn)
|
|
70
|
+
|
|
71
|
+
return this
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
unsubscribe(fn) {
|
|
@@ -68,10 +76,12 @@ class Record {
|
|
|
68
76
|
if (idx !== -1) {
|
|
69
77
|
this._subscriptions.splice(idx, 1)
|
|
70
78
|
}
|
|
79
|
+
|
|
80
|
+
return this
|
|
71
81
|
}
|
|
72
82
|
|
|
73
83
|
get(path) {
|
|
74
|
-
return jsonPath.get(this._data, path)
|
|
84
|
+
return path ? jsonPath.get(this._data, path) : this._data
|
|
75
85
|
}
|
|
76
86
|
|
|
77
87
|
set(pathOrData, dataOrNil) {
|
|
@@ -110,6 +120,7 @@ class Record {
|
|
|
110
120
|
}
|
|
111
121
|
}
|
|
112
122
|
|
|
123
|
+
// TODO (fix): timeout + signal
|
|
113
124
|
when(stateOrNull) {
|
|
114
125
|
invariant(this._refs > 0, this._name + ' missing refs')
|
|
115
126
|
|
|
@@ -130,8 +141,8 @@ class Record {
|
|
|
130
141
|
return
|
|
131
142
|
}
|
|
132
143
|
|
|
133
|
-
this.unsubscribe(onUpdate)
|
|
134
144
|
this.unref()
|
|
145
|
+
this.unsubscribe(onUpdate)
|
|
135
146
|
|
|
136
147
|
resolve(null)
|
|
137
148
|
}
|