@nxtedition/deepstream.io-client-js 31.2.16 → 31.2.18
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,7 +1,7 @@
|
|
|
1
1
|
import * as C from '../constants/constants.js'
|
|
2
2
|
import * as messageBuilder from '../message/message-builder.js'
|
|
3
3
|
import * as messageParser from '../message/message-parser.js'
|
|
4
|
-
import
|
|
4
|
+
import LegacyListener from '../utils/legacy-listener.js'
|
|
5
5
|
import UnicastListener from '../utils/unicast-listener.js'
|
|
6
6
|
import EventEmitter from 'component-emitter2'
|
|
7
7
|
import * as rxjs from 'rxjs'
|
|
@@ -126,7 +126,7 @@ EventHandler.prototype.provide = function (pattern, callback, options) {
|
|
|
126
126
|
const listener =
|
|
127
127
|
options.mode?.toLowerCase() === 'unicast'
|
|
128
128
|
? new UnicastListener(C.TOPIC.EVENT, pattern, callback, this, options)
|
|
129
|
-
: new
|
|
129
|
+
: new LegacyListener(C.TOPIC.EVENT, pattern, callback, this, options)
|
|
130
130
|
|
|
131
131
|
this._listeners.set(pattern, listener)
|
|
132
132
|
return () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Record from './record.js'
|
|
2
|
-
import
|
|
2
|
+
import LegacyListener from '../utils/legacy-listener.js'
|
|
3
3
|
import UnicastListener from '../utils/unicast-listener.js'
|
|
4
4
|
import * as C from '../constants/constants.js'
|
|
5
5
|
import * as rxjs from 'rxjs'
|
|
@@ -84,9 +84,18 @@ function onTimeout(subscription) {
|
|
|
84
84
|
|
|
85
85
|
subscription.subscriber.error(
|
|
86
86
|
Object.assign(
|
|
87
|
-
new Error(
|
|
87
|
+
new Error(
|
|
88
|
+
!subscription.synced
|
|
89
|
+
? `timeout sync: ${subscription.record.name}`
|
|
90
|
+
: `timeout state: ${subscription.record.name} [${current}<${expected}]`,
|
|
91
|
+
),
|
|
88
92
|
{
|
|
89
93
|
code: 'ETIMEDOUT',
|
|
94
|
+
timeout: subscription.timeoutValue,
|
|
95
|
+
expected,
|
|
96
|
+
current,
|
|
97
|
+
synced: subscription.synced,
|
|
98
|
+
name: subscription.record.name,
|
|
90
99
|
},
|
|
91
100
|
),
|
|
92
101
|
)
|
|
@@ -119,7 +128,7 @@ class RecordHandler {
|
|
|
119
128
|
}
|
|
120
129
|
|
|
121
130
|
this._syncQueue = []
|
|
122
|
-
this._syncMap =
|
|
131
|
+
this._syncMap = new Map()
|
|
123
132
|
|
|
124
133
|
this.set = this.set.bind(this)
|
|
125
134
|
this.get = this.get.bind(this)
|
|
@@ -219,13 +228,18 @@ class RecordHandler {
|
|
|
219
228
|
* @returns {Record}
|
|
220
229
|
*/
|
|
221
230
|
getRecord(name) {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
231
|
+
if (typeof name !== 'string' || name.length === 0) {
|
|
232
|
+
throw new Error('invalid argument: name')
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (name.startsWith('null') || name.startsWith('undefined') || name === '[object Object]') {
|
|
236
|
+
this._client._$onError(
|
|
237
|
+
C.TOPIC.RECORD,
|
|
238
|
+
C.EVENT.USER_ERROR,
|
|
239
|
+
'name should not start with null or undefined',
|
|
240
|
+
name,
|
|
241
|
+
)
|
|
242
|
+
}
|
|
229
243
|
|
|
230
244
|
let record = this._records.get(name)
|
|
231
245
|
|
|
@@ -261,7 +275,7 @@ class RecordHandler {
|
|
|
261
275
|
const listener =
|
|
262
276
|
options.mode?.toLowerCase() === 'unicast'
|
|
263
277
|
? new UnicastListener(C.TOPIC.RECORD, pattern, callback, this, options)
|
|
264
|
-
: new
|
|
278
|
+
: new LegacyListener(C.TOPIC.RECORD, pattern, callback, this, options)
|
|
265
279
|
|
|
266
280
|
this._stats.listeners += 1
|
|
267
281
|
this._listeners.set(pattern, listener)
|
|
@@ -552,78 +566,78 @@ class RecordHandler {
|
|
|
552
566
|
* @returns {rxjs.Observable}
|
|
553
567
|
*/
|
|
554
568
|
_observe(defaults, name, ...args) {
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
let sync = defaults?.sync ?? false
|
|
562
|
-
|
|
563
|
-
let idx = 0
|
|
564
|
-
|
|
565
|
-
if (
|
|
566
|
-
idx < args.length &&
|
|
567
|
-
(args[idx] == null ||
|
|
568
|
-
typeof args[idx] === 'string' ||
|
|
569
|
-
Array.isArray(args[idx]) ||
|
|
570
|
-
typeof args[idx] === 'function')
|
|
571
|
-
) {
|
|
572
|
-
path = args[idx++]
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
if (idx < args.length && (args[idx] == null || typeof args[idx] === 'number')) {
|
|
576
|
-
state = args[idx++]
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
if (idx < args.length && (args[idx] == null || typeof args[idx] === 'object')) {
|
|
580
|
-
const options = args[idx++] || {}
|
|
581
|
-
|
|
582
|
-
if (options.signal !== undefined) {
|
|
583
|
-
signal = options.signal
|
|
584
|
-
}
|
|
569
|
+
let path
|
|
570
|
+
let state = defaults?.state ?? C.RECORD_STATE.CLIENT
|
|
571
|
+
let signal = null
|
|
572
|
+
let timeout = defaults?.timeout ?? 0
|
|
573
|
+
let dataOnly = defaults?.dataOnly ?? false
|
|
574
|
+
let sync = defaults?.sync ?? false
|
|
585
575
|
|
|
586
|
-
|
|
587
|
-
timeout = options.timeout
|
|
588
|
-
}
|
|
576
|
+
let idx = 0
|
|
589
577
|
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
578
|
+
if (
|
|
579
|
+
idx < args.length &&
|
|
580
|
+
(args[idx] == null ||
|
|
581
|
+
typeof args[idx] === 'string' ||
|
|
582
|
+
Array.isArray(args[idx]) ||
|
|
583
|
+
typeof args[idx] === 'function')
|
|
584
|
+
) {
|
|
585
|
+
path = args[idx++]
|
|
586
|
+
}
|
|
593
587
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
588
|
+
if (idx < args.length && (args[idx] == null || typeof args[idx] === 'number')) {
|
|
589
|
+
state = args[idx++]
|
|
590
|
+
}
|
|
597
591
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
}
|
|
592
|
+
if (idx < args.length && (args[idx] == null || typeof args[idx] === 'object')) {
|
|
593
|
+
const options = args[idx++] || {}
|
|
601
594
|
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}
|
|
595
|
+
if (options.signal !== undefined) {
|
|
596
|
+
signal = options.signal
|
|
605
597
|
}
|
|
606
598
|
|
|
607
|
-
if (
|
|
608
|
-
|
|
599
|
+
if (options.timeout !== undefined) {
|
|
600
|
+
timeout = options.timeout
|
|
609
601
|
}
|
|
610
602
|
|
|
611
|
-
if (
|
|
612
|
-
|
|
603
|
+
if (options.path !== undefined) {
|
|
604
|
+
path = options.path
|
|
613
605
|
}
|
|
614
606
|
|
|
615
|
-
if (
|
|
616
|
-
|
|
607
|
+
if (options.state !== undefined) {
|
|
608
|
+
state = options.state
|
|
617
609
|
}
|
|
618
610
|
|
|
619
|
-
if (
|
|
620
|
-
|
|
611
|
+
if (options.dataOnly !== undefined) {
|
|
612
|
+
dataOnly = options.dataOnly
|
|
621
613
|
}
|
|
622
614
|
|
|
623
|
-
if (
|
|
624
|
-
|
|
615
|
+
if (options.sync !== undefined) {
|
|
616
|
+
sync = options.sync
|
|
625
617
|
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (typeof state === 'string') {
|
|
621
|
+
state = C.RECORD_STATE[state.toUpperCase()]
|
|
622
|
+
}
|
|
626
623
|
|
|
624
|
+
if (!Number.isInteger(state) || state < 0) {
|
|
625
|
+
throw new Error('invalid argument: state')
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
if (!Number.isInteger(timeout) || timeout < 0) {
|
|
629
|
+
throw new Error('invalid argument: timeout')
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (typeof dataOnly !== 'boolean') {
|
|
633
|
+
throw new Error('invalid argument: dataOnly')
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (typeof sync !== 'boolean') {
|
|
637
|
+
throw new Error('invalid argument: sync')
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
return new rxjs.Observable((subscriber) => {
|
|
627
641
|
// TODO (perf): Make a class
|
|
628
642
|
const subscription = {
|
|
629
643
|
/** @readonly @type {unknown} */
|
|
@@ -649,6 +663,9 @@ class RecordHandler {
|
|
|
649
663
|
data: kEmpty,
|
|
650
664
|
/** @type {boolean} */
|
|
651
665
|
synced: false,
|
|
666
|
+
|
|
667
|
+
index: -1,
|
|
668
|
+
onUpdate,
|
|
652
669
|
}
|
|
653
670
|
|
|
654
671
|
subscriber.add(() => {
|
|
@@ -664,7 +681,7 @@ class RecordHandler {
|
|
|
664
681
|
}
|
|
665
682
|
|
|
666
683
|
if (subscription.record) {
|
|
667
|
-
subscription.record.
|
|
684
|
+
subscription.record._unobserve(subscription)
|
|
668
685
|
subscription.record.unref()
|
|
669
686
|
subscription.record = null
|
|
670
687
|
}
|
|
@@ -675,11 +692,11 @@ class RecordHandler {
|
|
|
675
692
|
utils.addAbortListener(subscription.signal, subscription.abort)
|
|
676
693
|
}
|
|
677
694
|
|
|
678
|
-
subscription.record = this.getRecord(name)
|
|
695
|
+
subscription.record = this.getRecord(name)
|
|
696
|
+
subscription.record._observe(subscription)
|
|
679
697
|
|
|
680
698
|
if (sync) {
|
|
681
|
-
|
|
682
|
-
this._sync(onSync, sync === true ? 'WEAK' : sync, subscription)
|
|
699
|
+
this._sync(onSync, sync, subscription)
|
|
683
700
|
} else {
|
|
684
701
|
onSync(subscription)
|
|
685
702
|
}
|
|
@@ -700,8 +717,8 @@ class RecordHandler {
|
|
|
700
717
|
return true
|
|
701
718
|
}
|
|
702
719
|
|
|
703
|
-
const sync = this._syncMap
|
|
704
|
-
|
|
720
|
+
const sync = this._syncMap.get(token)
|
|
721
|
+
this._syncMap.delete(token)
|
|
705
722
|
|
|
706
723
|
if (!sync) {
|
|
707
724
|
return true
|
|
@@ -744,10 +761,10 @@ class RecordHandler {
|
|
|
744
761
|
this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.PUT, update)
|
|
745
762
|
}
|
|
746
763
|
|
|
747
|
-
const syncMap =
|
|
748
|
-
for (const sync of
|
|
764
|
+
const syncMap = new Map()
|
|
765
|
+
for (const sync of this._syncMap.values()) {
|
|
749
766
|
const token = xuid()
|
|
750
|
-
syncMap
|
|
767
|
+
syncMap.set(token, sync)
|
|
751
768
|
this._connection.sendMsg(
|
|
752
769
|
C.TOPIC.RECORD,
|
|
753
770
|
C.ACTIONS.SYNC,
|
|
@@ -782,7 +799,7 @@ class RecordHandler {
|
|
|
782
799
|
const token = xuid()
|
|
783
800
|
const queue = this._syncQueue.splice(0)
|
|
784
801
|
|
|
785
|
-
this._syncMap
|
|
802
|
+
this._syncMap.set(token, { queue, type })
|
|
786
803
|
this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SYNC, type ? [token, type] : [token])
|
|
787
804
|
}, 1)
|
|
788
805
|
}
|
package/src/record/record.js
CHANGED
|
@@ -20,7 +20,13 @@ class Record {
|
|
|
20
20
|
this._state = C.RECORD_STATE.VOID
|
|
21
21
|
this._refs = 0
|
|
22
22
|
this._subscriptions = []
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
/** @type {Array|null} */
|
|
25
|
+
this._emittingArr = null
|
|
26
|
+
/** @type {number} */
|
|
27
|
+
this._emittingIndex = -1
|
|
28
|
+
|
|
29
|
+
this._observers = []
|
|
24
30
|
|
|
25
31
|
/** @type Map? */ this._updating = null
|
|
26
32
|
/** @type Array? */ this._patching = null
|
|
@@ -88,9 +94,8 @@ class Record {
|
|
|
88
94
|
* @returns {Record}
|
|
89
95
|
*/
|
|
90
96
|
subscribe(fn, opaque = null) {
|
|
91
|
-
if (this.
|
|
97
|
+
if (this._emittingArr == this._subscriptions) {
|
|
92
98
|
this._subscriptions = this._subscriptions.slice()
|
|
93
|
-
this._emitting = false
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
this._subscriptions.push(fn, opaque)
|
|
@@ -105,9 +110,8 @@ class Record {
|
|
|
105
110
|
* @returns {Record}
|
|
106
111
|
*/
|
|
107
112
|
unsubscribe(fn, opaque = null) {
|
|
108
|
-
if (this.
|
|
113
|
+
if (this._emittingArr == this._subscriptions) {
|
|
109
114
|
this._subscriptions = this._subscriptions.slice()
|
|
110
|
-
this._emitting = false
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
let idx = -1
|
|
@@ -128,6 +132,41 @@ class Record {
|
|
|
128
132
|
return this
|
|
129
133
|
}
|
|
130
134
|
|
|
135
|
+
/**
|
|
136
|
+
* @note Subscribers are unordered.
|
|
137
|
+
* @param {{ index: number, onUpdate: (Record) => void}} subscription
|
|
138
|
+
*/
|
|
139
|
+
_observe(subscription) {
|
|
140
|
+
if (subscription.index != null && subscription.index !== -1) {
|
|
141
|
+
throw new Error('already observing')
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
subscription.index = this._observers.push(subscription) - 1
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* @param {{ index: number, onUpdate: (Record) => void}} subscription
|
|
149
|
+
*/
|
|
150
|
+
_unobserve(subscription) {
|
|
151
|
+
if (subscription.index == null || subscription.index === -1) {
|
|
152
|
+
throw new Error('not observing')
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (this._emittingArr === this._observers) {
|
|
156
|
+
// TODO (perf): Shift from start if emitting?
|
|
157
|
+
this._observers = this._observers.slice()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const idx = subscription.index
|
|
161
|
+
const tmp = this._observers.pop()
|
|
162
|
+
subscription.index = -1
|
|
163
|
+
|
|
164
|
+
if (tmp !== subscription) {
|
|
165
|
+
this._observers[idx] = tmp
|
|
166
|
+
this._observers[idx].index = idx
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
131
170
|
get(path) {
|
|
132
171
|
if (!path) {
|
|
133
172
|
return this._data
|
|
@@ -515,18 +554,41 @@ class Record {
|
|
|
515
554
|
}
|
|
516
555
|
|
|
517
556
|
_emitUpdate() {
|
|
518
|
-
this.
|
|
557
|
+
if (this._emittingArr != null) {
|
|
558
|
+
throw new Error('cannot reenter emitUpdate')
|
|
559
|
+
}
|
|
519
560
|
|
|
520
|
-
|
|
521
|
-
|
|
561
|
+
try {
|
|
562
|
+
const arr = this._subscriptions
|
|
563
|
+
const len = arr.length
|
|
522
564
|
|
|
523
|
-
|
|
524
|
-
|
|
565
|
+
this._emittingArr = arr
|
|
566
|
+
for (let n = 0; n < len; n += 2) {
|
|
567
|
+
this._emittingIndex = n
|
|
568
|
+
// TODO (fix): What if this throws?
|
|
569
|
+
arr[n + 0](this, arr[n + 1])
|
|
570
|
+
}
|
|
571
|
+
} finally {
|
|
572
|
+
this._emittingArr = null
|
|
573
|
+
this._emittingIndex = -1
|
|
525
574
|
}
|
|
526
575
|
|
|
527
|
-
|
|
576
|
+
try {
|
|
577
|
+
const arr = this._observers
|
|
578
|
+
const len = arr.length
|
|
528
579
|
|
|
529
|
-
|
|
580
|
+
this._emittingArr = arr
|
|
581
|
+
for (let n = 0; n < len; n++) {
|
|
582
|
+
this._emittingIndex = n
|
|
583
|
+
// TODO (fix): What if this throws?
|
|
584
|
+
arr[n].onUpdate(this)
|
|
585
|
+
}
|
|
586
|
+
} finally {
|
|
587
|
+
this._emittingArr = null
|
|
588
|
+
this._emittingIndex = -1
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
this._handler._client.emit('recordUpdated', this)
|
|
530
592
|
}
|
|
531
593
|
}
|
|
532
594
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as rxjs from 'rxjs'
|
|
2
2
|
import * as C from '../constants/constants.js'
|
|
3
|
-
import { h64ToString, findBigIntPaths } from '
|
|
3
|
+
import { h64ToString, findBigIntPaths } from './utils.js'
|
|
4
4
|
|
|
5
5
|
export default class Listener {
|
|
6
6
|
constructor(topic, pattern, callback, handler, { recursive = false, stringify = null } = {}) {
|