@nxtedition/deepstream.io-client-js 28.0.2 → 30.0.0
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/record/record-handler.js +12 -10
- package/src/record/record.js +16 -5
- package/src/utils/multicast-listener.js +179 -147
- package/src/utils/unicast-listener.js +43 -26
- package/src/utils/utils.js +1 -4
package/package.json
CHANGED
|
@@ -95,7 +95,8 @@ class RecordHandler {
|
|
|
95
95
|
this._options = options
|
|
96
96
|
this._connection = connection
|
|
97
97
|
this._client = client
|
|
98
|
-
this.
|
|
98
|
+
this._recordsByName = new Map()
|
|
99
|
+
this._recordsByKey = new Map()
|
|
99
100
|
this._listeners = new Map()
|
|
100
101
|
this._pruning = new Set()
|
|
101
102
|
this._patching = new Map()
|
|
@@ -132,7 +133,7 @@ class RecordHandler {
|
|
|
132
133
|
|
|
133
134
|
for (const rec of pruning) {
|
|
134
135
|
rec._$dispose()
|
|
135
|
-
this.
|
|
136
|
+
this._recordsByName.delete(rec.name)
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
this._stats.pruning -= pruning.size
|
|
@@ -215,13 +216,14 @@ class RecordHandler {
|
|
|
215
216
|
`invalid name ${name}`,
|
|
216
217
|
)
|
|
217
218
|
|
|
218
|
-
let record = this.
|
|
219
|
+
let record = this._recordsByName.get(name)
|
|
219
220
|
|
|
220
221
|
if (!record) {
|
|
221
222
|
record = new Record(name, this)
|
|
222
223
|
this._stats.records += 1
|
|
223
224
|
this._stats.created += 1
|
|
224
|
-
this.
|
|
225
|
+
this._recordsByName.set(record.name, record)
|
|
226
|
+
this._recordsByKey.set(record.name, record)
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
return record.ref()
|
|
@@ -617,11 +619,11 @@ class RecordHandler {
|
|
|
617
619
|
}
|
|
618
620
|
|
|
619
621
|
_$handle(message) {
|
|
620
|
-
let
|
|
622
|
+
let key
|
|
621
623
|
if (message.action === C.ACTIONS.ERROR) {
|
|
622
|
-
|
|
624
|
+
key = message.data[1]
|
|
623
625
|
} else {
|
|
624
|
-
|
|
626
|
+
key = message.data[0]
|
|
625
627
|
}
|
|
626
628
|
|
|
627
629
|
if (message.action === C.ACTIONS.SYNC) {
|
|
@@ -629,12 +631,12 @@ class RecordHandler {
|
|
|
629
631
|
return true
|
|
630
632
|
}
|
|
631
633
|
|
|
632
|
-
const listener = this._listeners.get(
|
|
634
|
+
const listener = this._listeners.get(key)
|
|
633
635
|
if (listener && listener._$onMessage(message)) {
|
|
634
636
|
return true
|
|
635
637
|
}
|
|
636
638
|
|
|
637
|
-
const record = this.
|
|
639
|
+
const record = this._recordsByKey.get(key)
|
|
638
640
|
if (record && record._$onMessage(message)) {
|
|
639
641
|
return true
|
|
640
642
|
}
|
|
@@ -647,7 +649,7 @@ class RecordHandler {
|
|
|
647
649
|
listener._$onConnectionStateChange(connected)
|
|
648
650
|
}
|
|
649
651
|
|
|
650
|
-
for (const record of this.
|
|
652
|
+
for (const record of this._recordsByName.values()) {
|
|
651
653
|
record._$onConnectionStateChange(connected)
|
|
652
654
|
}
|
|
653
655
|
|
package/src/record/record.js
CHANGED
|
@@ -15,6 +15,7 @@ class Record {
|
|
|
15
15
|
|
|
16
16
|
this._handler = handler
|
|
17
17
|
this._name = name
|
|
18
|
+
this._key = utils.h64ToString(name)
|
|
18
19
|
this._version = ''
|
|
19
20
|
this._data = jsonPath.EMPTY
|
|
20
21
|
this._state = C.RECORD_STATE.VOID
|
|
@@ -24,7 +25,15 @@ class Record {
|
|
|
24
25
|
|
|
25
26
|
/** @type Map? */ this._updating = null
|
|
26
27
|
/** @type Array? */ this._patching = null
|
|
27
|
-
this._subscribed = connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [
|
|
28
|
+
this._subscribed = connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [
|
|
29
|
+
this._key,
|
|
30
|
+
this._name,
|
|
31
|
+
])
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** @type { string} */
|
|
35
|
+
get key() {
|
|
36
|
+
return this._key
|
|
28
37
|
}
|
|
29
38
|
|
|
30
39
|
/** @type {string} */
|
|
@@ -62,7 +71,8 @@ class Record {
|
|
|
62
71
|
if (this._refs === 1) {
|
|
63
72
|
this._handler._onPruning(this, false)
|
|
64
73
|
this._subscribed =
|
|
65
|
-
this._subscribed ||
|
|
74
|
+
this._subscribed ||
|
|
75
|
+
connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._key, this._name])
|
|
66
76
|
}
|
|
67
77
|
return this
|
|
68
78
|
}
|
|
@@ -324,7 +334,8 @@ class Record {
|
|
|
324
334
|
|
|
325
335
|
if (connected) {
|
|
326
336
|
this._subscribed =
|
|
327
|
-
this._refs > 0 &&
|
|
337
|
+
this._refs > 0 &&
|
|
338
|
+
connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.SUBSCRIBE, [this._key, this._name])
|
|
328
339
|
|
|
329
340
|
if (this._updating) {
|
|
330
341
|
for (const update of this._updating.values()) {
|
|
@@ -349,7 +360,7 @@ class Record {
|
|
|
349
360
|
invariant(!this._updating, 'must not have updates')
|
|
350
361
|
|
|
351
362
|
if (this._subscribed) {
|
|
352
|
-
connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UNSUBSCRIBE, [this.
|
|
363
|
+
connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UNSUBSCRIBE, [this._key])
|
|
353
364
|
this._subscribed = false
|
|
354
365
|
}
|
|
355
366
|
|
|
@@ -371,7 +382,7 @@ class Record {
|
|
|
371
382
|
const prevVersion = this._version
|
|
372
383
|
const nextVersion = this._makeVersion(parseInt(prevVersion) + 1)
|
|
373
384
|
|
|
374
|
-
const update = [this.
|
|
385
|
+
const update = [this._key, nextVersion, jsonPath.stringify(nextData), prevVersion]
|
|
375
386
|
|
|
376
387
|
if (!this._updating) {
|
|
377
388
|
this._onUpdating(true)
|
|
@@ -1,6 +1,176 @@
|
|
|
1
1
|
import * as rxjs from 'rxjs'
|
|
2
2
|
import * as C from '../constants/constants.js'
|
|
3
3
|
import { h64ToString } from '../utils/utils.js'
|
|
4
|
+
import * as timers from '../utils/timers.js'
|
|
5
|
+
|
|
6
|
+
class Provider {
|
|
7
|
+
#sending = false
|
|
8
|
+
#accepted = false
|
|
9
|
+
#value$ = null
|
|
10
|
+
#name
|
|
11
|
+
#key
|
|
12
|
+
#version
|
|
13
|
+
#timeout
|
|
14
|
+
#valueSubscription
|
|
15
|
+
#patternSubscription
|
|
16
|
+
#observer
|
|
17
|
+
#listener
|
|
18
|
+
|
|
19
|
+
constructor(name, listener) {
|
|
20
|
+
this.#name = name
|
|
21
|
+
this.#key = h64ToString(name)
|
|
22
|
+
this.#listener = listener
|
|
23
|
+
this.#observer = {
|
|
24
|
+
next: (value) => {
|
|
25
|
+
if (value == null) {
|
|
26
|
+
this.next(null) // TODO (fix): This is weird...
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (this.#listener._topic === C.TOPIC.EVENT) {
|
|
31
|
+
this.#listener._handler.emit(this.#name, value)
|
|
32
|
+
} else if (this.#listener._topic === C.TOPIC.RECORD) {
|
|
33
|
+
if (typeof value !== 'object' && typeof value !== 'string') {
|
|
34
|
+
this.#listener._error(this.#name, 'invalid value')
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const body = typeof value !== 'string' ? this.#listener._stringify(value) : value
|
|
39
|
+
const hash = h64ToString(body)
|
|
40
|
+
const version = `INF-${hash}`
|
|
41
|
+
|
|
42
|
+
if (this.#version !== version) {
|
|
43
|
+
this.#version = version
|
|
44
|
+
this.#listener._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UPDATE, [
|
|
45
|
+
this.#key,
|
|
46
|
+
version,
|
|
47
|
+
body,
|
|
48
|
+
])
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
error: (err) => {
|
|
53
|
+
this.error(err)
|
|
54
|
+
},
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.#start()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
dispose() {
|
|
61
|
+
this.#stop()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
accept() {
|
|
65
|
+
if (!this.#value$) {
|
|
66
|
+
return
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (this.#valueSubscription) {
|
|
70
|
+
this.#listener._error(this.#name, 'invalid accept: listener started')
|
|
71
|
+
} else {
|
|
72
|
+
// TODO (fix): provider.version = message.data[2]
|
|
73
|
+
this.#valueSubscription = this.#value$.subscribe(this.#observer)
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
reject() {
|
|
78
|
+
this.#listener._error(this.#name, 'invalid reject: not implemented')
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
next(value$) {
|
|
82
|
+
if (!value$) {
|
|
83
|
+
value$ = null
|
|
84
|
+
} else if (typeof value$.subscribe !== 'function') {
|
|
85
|
+
value$ = rxjs.of(value$) // Compat for recursive with value
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (Boolean(this.#value$) !== Boolean(value$) && !this.#sending) {
|
|
89
|
+
this.#sending = true
|
|
90
|
+
// TODO (fix): Why async?
|
|
91
|
+
queueMicrotask(() => {
|
|
92
|
+
this.#sending = false
|
|
93
|
+
|
|
94
|
+
if (!this.#patternSubscription) {
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const accepted = Boolean(this.#value$)
|
|
99
|
+
if (this.#accepted === accepted) {
|
|
100
|
+
return
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.#listener._connection.sendMsg(
|
|
104
|
+
this.#listener._topic,
|
|
105
|
+
accepted ? C.ACTIONS.LISTEN_ACCEPT : C.ACTIONS.LISTEN_REJECT,
|
|
106
|
+
[this.#listener._pattern, this.#key],
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
this.#version = null
|
|
110
|
+
this.#accepted = accepted
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.#value$ = value$
|
|
115
|
+
|
|
116
|
+
if (this.#valueSubscription) {
|
|
117
|
+
this.#valueSubscription.unsubscribe()
|
|
118
|
+
this.#valueSubscription = this.#value$?.subscribe(this.#observer)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
error(err) {
|
|
123
|
+
this.#stop()
|
|
124
|
+
// TODO (feat): backoff retryCount * delay?
|
|
125
|
+
// TODO (feat): backoff option?
|
|
126
|
+
this.#timeout = timers.setTimeout(
|
|
127
|
+
(provider) => {
|
|
128
|
+
provider.start()
|
|
129
|
+
},
|
|
130
|
+
10e3,
|
|
131
|
+
this,
|
|
132
|
+
)
|
|
133
|
+
this.#listener._error(this.#name, err)
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
#start() {
|
|
137
|
+
try {
|
|
138
|
+
const ret$ = this.#listener._callback(this.#name)
|
|
139
|
+
if (this.#listener._recursive && typeof ret$?.subscribe === 'function') {
|
|
140
|
+
this.patternSubscription = ret$.subscribe(this)
|
|
141
|
+
} else {
|
|
142
|
+
this.patternSubscription = rxjs.of(ret$).subscribe(this)
|
|
143
|
+
}
|
|
144
|
+
} catch (err) {
|
|
145
|
+
this.#listener._error(this.#name, err)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#stop() {
|
|
150
|
+
if (this.#listener.connected && this.#accepted) {
|
|
151
|
+
this.#listener._connection.sendMsg(this.#listener._topic, C.ACTIONS.LISTEN_REJECT, [
|
|
152
|
+
this.#listener._pattern,
|
|
153
|
+
this.#key,
|
|
154
|
+
])
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
this.#value$ = null
|
|
158
|
+
this.#version = null
|
|
159
|
+
this.#accepted = false
|
|
160
|
+
this.#sending = false
|
|
161
|
+
|
|
162
|
+
if (this.#timeout) {
|
|
163
|
+
timers.clearTimeout(this.#timeout)
|
|
164
|
+
this.#timeout = null
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
this.#patternSubscription?.unsubscribe()
|
|
168
|
+
this.#patternSubscription = null
|
|
169
|
+
|
|
170
|
+
this.#valueSubscription?.unsubscribe()
|
|
171
|
+
this.#valueSubscription = null
|
|
172
|
+
}
|
|
173
|
+
}
|
|
4
174
|
|
|
5
175
|
export default class Listener {
|
|
6
176
|
constructor(topic, pattern, callback, handler, { recursive = false, stringify = null } = {}) {
|
|
@@ -51,158 +221,20 @@ export default class Listener {
|
|
|
51
221
|
if (message.action === C.ACTIONS.SUBSCRIPTION_FOR_PATTERN_FOUND) {
|
|
52
222
|
if (this._subscriptions.has(name)) {
|
|
53
223
|
this._error(name, 'invalid add: listener exists')
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// TODO (refactor): Move to class
|
|
58
|
-
const provider = {
|
|
59
|
-
name,
|
|
60
|
-
value$: null,
|
|
61
|
-
sending: false,
|
|
62
|
-
accepted: false,
|
|
63
|
-
version: null,
|
|
64
|
-
timeout: null,
|
|
65
|
-
patternSubscription: null,
|
|
66
|
-
valueSubscription: null,
|
|
67
|
-
}
|
|
68
|
-
provider.stop = () => {
|
|
69
|
-
if (this.connected && provider.accepted) {
|
|
70
|
-
this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [
|
|
71
|
-
this._pattern,
|
|
72
|
-
provider.name,
|
|
73
|
-
])
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
provider.value$ = null
|
|
77
|
-
provider.version = null
|
|
78
|
-
provider.accepted = false
|
|
79
|
-
provider.sending = false
|
|
80
|
-
|
|
81
|
-
clearTimeout(provider.timeout)
|
|
82
|
-
provider.timeout = null
|
|
83
|
-
|
|
84
|
-
provider.patternSubscription?.unsubscribe()
|
|
85
|
-
provider.patternSubscription = null
|
|
86
|
-
|
|
87
|
-
provider.valueSubscription?.unsubscribe()
|
|
88
|
-
provider.valueSubscription = null
|
|
89
|
-
}
|
|
90
|
-
provider.send = () => {
|
|
91
|
-
provider.sending = false
|
|
92
|
-
|
|
93
|
-
if (!provider.patternSubscription) {
|
|
94
|
-
return
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
const accepted = Boolean(provider.value$)
|
|
98
|
-
if (provider.accepted === accepted) {
|
|
99
|
-
return
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
this._connection.sendMsg(
|
|
103
|
-
this._topic,
|
|
104
|
-
accepted ? C.ACTIONS.LISTEN_ACCEPT : C.ACTIONS.LISTEN_REJECT,
|
|
105
|
-
[this._pattern, provider.name],
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
provider.version = null
|
|
109
|
-
provider.accepted = accepted
|
|
110
|
-
}
|
|
111
|
-
provider.next = (value$) => {
|
|
112
|
-
if (!value$) {
|
|
113
|
-
value$ = null
|
|
114
|
-
} else if (typeof value$.subscribe !== 'function') {
|
|
115
|
-
value$ = rxjs.of(value$) // Compat for recursive with value
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (Boolean(provider.value$) !== Boolean(value$) && !provider.sending) {
|
|
119
|
-
provider.sending = true
|
|
120
|
-
queueMicrotask(provider.send)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
provider.value$ = value$
|
|
124
|
-
|
|
125
|
-
if (provider.valueSubscription) {
|
|
126
|
-
provider.valueSubscription.unsubscribe()
|
|
127
|
-
provider.valueSubscription = provider.value$?.subscribe(provider.observer)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
provider.error = (err) => {
|
|
131
|
-
provider.stop()
|
|
132
|
-
// TODO (feat): backoff retryCount * delay?
|
|
133
|
-
// TODO (feat): backoff option?
|
|
134
|
-
provider.timeout = setTimeout(() => {
|
|
135
|
-
provider.start()
|
|
136
|
-
}, 10e3)
|
|
137
|
-
this._error(provider.name, err)
|
|
138
|
-
}
|
|
139
|
-
provider.observer = {
|
|
140
|
-
next: (value) => {
|
|
141
|
-
if (value == null) {
|
|
142
|
-
provider.next(null) // TODO (fix): This is weird...
|
|
143
|
-
return
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (this._topic === C.TOPIC.EVENT) {
|
|
147
|
-
this._handler.emit(provider.name, value)
|
|
148
|
-
} else if (this._topic === C.TOPIC.RECORD) {
|
|
149
|
-
if (typeof value !== 'object' && typeof value !== 'string') {
|
|
150
|
-
this._error(provider.name, 'invalid value')
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const body = typeof value !== 'string' ? this._stringify(value) : value
|
|
155
|
-
const hash = h64ToString(body)
|
|
156
|
-
const version = `INF-${hash}`
|
|
157
|
-
|
|
158
|
-
if (provider.version !== version) {
|
|
159
|
-
provider.version = version
|
|
160
|
-
this._connection.sendMsg(C.TOPIC.RECORD, C.ACTIONS.UPDATE, [
|
|
161
|
-
provider.name,
|
|
162
|
-
version,
|
|
163
|
-
body,
|
|
164
|
-
])
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
},
|
|
168
|
-
error: provider.error,
|
|
169
|
-
}
|
|
170
|
-
provider.start = () => {
|
|
171
|
-
try {
|
|
172
|
-
const ret$ = this._callback(name)
|
|
173
|
-
if (this._recursive && typeof ret$?.subscribe === 'function') {
|
|
174
|
-
provider.patternSubscription = ret$.subscribe(provider)
|
|
175
|
-
} else {
|
|
176
|
-
provider.patternSubscription = rxjs.of(ret$).subscribe(provider)
|
|
177
|
-
}
|
|
178
|
-
} catch (err) {
|
|
179
|
-
this._error(provider.name, err)
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
provider.start()
|
|
184
|
-
|
|
185
|
-
this._subscriptions.set(provider.name, provider)
|
|
186
|
-
} else if (message.action === C.ACTIONS.LISTEN_ACCEPT) {
|
|
187
|
-
const provider = this._subscriptions.get(name)
|
|
188
|
-
if (!provider?.value$) {
|
|
189
|
-
return
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (provider.valueSubscription) {
|
|
193
|
-
this._error(name, 'invalid accept: listener started')
|
|
194
224
|
} else {
|
|
195
|
-
|
|
196
|
-
provider.valueSubscription = provider.value$.subscribe(provider.observer)
|
|
225
|
+
this._subscriptions.set(name, new Provider(name, this))
|
|
197
226
|
}
|
|
227
|
+
} else if (message.action === C.ACTIONS.LISTEN_ACCEPT) {
|
|
228
|
+
this._subscriptions.get(name)?.accept()
|
|
229
|
+
} else if (message.action === C.ACTIONS.LISTEN_REJECT) {
|
|
230
|
+
this._subscriptions.get(name)?.reject()
|
|
198
231
|
} else if (message.action === C.ACTIONS.SUBSCRIPTION_FOR_PATTERN_REMOVED) {
|
|
199
232
|
const provider = this._subscriptions.get(name)
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
this.
|
|
233
|
+
if (provider) {
|
|
234
|
+
provider.dispose()
|
|
235
|
+
this._subscriptions.delete(name)
|
|
203
236
|
} else {
|
|
204
|
-
|
|
205
|
-
this._subscriptions.delete(provider.name)
|
|
237
|
+
this._error(name, 'invalid remove: listener missing')
|
|
206
238
|
}
|
|
207
239
|
} else {
|
|
208
240
|
return false
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
-
import * as rxjs from 'rxjs'
|
|
2
1
|
import * as C from '../constants/constants.js'
|
|
3
2
|
import { h64ToString } from '../utils/utils.js'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
class Observer {
|
|
5
|
+
#name
|
|
6
|
+
#key
|
|
7
|
+
#listener
|
|
8
|
+
#version = ''
|
|
9
|
+
|
|
10
|
+
constructor(name, listener) {
|
|
11
|
+
this.#name = name
|
|
12
|
+
this.#key = h64ToString(name)
|
|
13
|
+
this.#listener = listener
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
next(value) {
|
|
7
17
|
let data
|
|
8
18
|
if (value && typeof value === 'string') {
|
|
9
19
|
if (value.charAt(0) !== '{' && value.charAt(0) !== '[') {
|
|
@@ -16,10 +26,34 @@ const PIPE = rxjs.pipe(
|
|
|
16
26
|
throw new Error(`invalid value: ${value}`)
|
|
17
27
|
}
|
|
18
28
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
29
|
+
const version = data ? `INF-${h64ToString(data)}` : ''
|
|
30
|
+
if (this.#version === version) {
|
|
31
|
+
return
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (version) {
|
|
35
|
+
this.#listener._connection.sendMsg(this.#listener._topic, C.ACTIONS.UPDATE, [
|
|
36
|
+
this.#key,
|
|
37
|
+
version,
|
|
38
|
+
data,
|
|
39
|
+
])
|
|
40
|
+
} else {
|
|
41
|
+
this.#listener._connection.sendMsg(this.#listener._topic, C.ACTIONS.LISTEN_REJECT, [
|
|
42
|
+
this.#listener._pattern,
|
|
43
|
+
this.#key,
|
|
44
|
+
])
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
this.#version = version
|
|
48
|
+
}
|
|
49
|
+
error(err) {
|
|
50
|
+
this.#listener._error(this.#name, err)
|
|
51
|
+
this.#listener._connection.sendMsg(this.#listener._topic, C.ACTIONS.LISTEN_REJECT, [
|
|
52
|
+
this.#listener._pattern,
|
|
53
|
+
this.#key,
|
|
54
|
+
])
|
|
55
|
+
}
|
|
56
|
+
}
|
|
23
57
|
|
|
24
58
|
export default class Listener {
|
|
25
59
|
constructor(topic, pattern, callback, handler, opts) {
|
|
@@ -65,28 +99,11 @@ export default class Listener {
|
|
|
65
99
|
try {
|
|
66
100
|
value$ = this._callback(name)
|
|
67
101
|
} catch (err) {
|
|
68
|
-
|
|
102
|
+
this._error(name, err)
|
|
69
103
|
}
|
|
70
104
|
|
|
71
105
|
if (value$) {
|
|
72
|
-
|
|
73
|
-
next: (data) => {
|
|
74
|
-
if (data == null) {
|
|
75
|
-
this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
|
|
76
|
-
this._subscriptions.delete(name)
|
|
77
|
-
subscription.unsubscribe()
|
|
78
|
-
} else {
|
|
79
|
-
const version = `INF-${h64ToString(data)}`
|
|
80
|
-
this._connection.sendMsg(this._topic, C.ACTIONS.UPDATE, [name, version, data])
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
error: (err) => {
|
|
84
|
-
this._error(name, err)
|
|
85
|
-
this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
|
|
86
|
-
this._subscriptions.delete(name)
|
|
87
|
-
},
|
|
88
|
-
})
|
|
89
|
-
this._subscriptions.set(name, subscription)
|
|
106
|
+
this._subscriptions.set(name, value$.subscribe(new Observer(name, this)))
|
|
90
107
|
} else {
|
|
91
108
|
this._connection.sendMsg(this._topic, C.ACTIONS.LISTEN_REJECT, [this._pattern, name])
|
|
92
109
|
}
|
package/src/utils/utils.js
CHANGED
|
@@ -177,10 +177,7 @@ export function removeAbortListener(signal, handler) {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
|
|
181
|
-
// const HASHER = await xxhash()
|
|
182
|
-
let HASHER
|
|
183
|
-
xxhash().then((hasher) => (HASHER = hasher))
|
|
180
|
+
const HASHER = await xxhash()
|
|
184
181
|
|
|
185
182
|
export function h64ToString(str) {
|
|
186
183
|
return HASHER.h64ToString(str)
|