@libp2p/utils 6.7.2-8484de8a2 → 6.7.2-87bc8d4fb

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 (164) hide show
  1. package/README.md +1 -1
  2. package/dist/index.min.js +1 -6
  3. package/dist/index.min.js.map +4 -4
  4. package/dist/src/abort-options.d.ts +7 -0
  5. package/dist/src/abort-options.d.ts.map +1 -0
  6. package/dist/src/abort-options.js +14 -0
  7. package/dist/src/abort-options.js.map +1 -0
  8. package/dist/src/abstract-stream.d.ts +130 -14
  9. package/dist/src/abstract-stream.d.ts.map +1 -1
  10. package/dist/src/abstract-stream.js +321 -39
  11. package/dist/src/abstract-stream.js.map +1 -1
  12. package/dist/src/array-equals.d.ts +24 -0
  13. package/dist/src/array-equals.d.ts.map +1 -0
  14. package/dist/src/array-equals.js +31 -0
  15. package/dist/src/array-equals.js.map +1 -0
  16. package/dist/src/close-source.d.ts +4 -0
  17. package/dist/src/close-source.d.ts.map +1 -0
  18. package/dist/src/close-source.js +11 -0
  19. package/dist/src/close-source.js.map +1 -0
  20. package/dist/src/close.d.ts +21 -0
  21. package/dist/src/close.d.ts.map +1 -0
  22. package/dist/src/close.js +49 -0
  23. package/dist/src/close.js.map +1 -0
  24. package/dist/src/errors.d.ts +0 -8
  25. package/dist/src/errors.d.ts.map +1 -1
  26. package/dist/src/errors.js +0 -8
  27. package/dist/src/errors.js.map +1 -1
  28. package/dist/src/get-thin-waist-addresses.browser.d.ts +1 -1
  29. package/dist/src/get-thin-waist-addresses.browser.d.ts.map +1 -1
  30. package/dist/src/get-thin-waist-addresses.browser.js +3 -4
  31. package/dist/src/get-thin-waist-addresses.browser.js.map +1 -1
  32. package/dist/src/get-thin-waist-addresses.d.ts +1 -1
  33. package/dist/src/get-thin-waist-addresses.d.ts.map +1 -1
  34. package/dist/src/get-thin-waist-addresses.js +9 -7
  35. package/dist/src/get-thin-waist-addresses.js.map +1 -1
  36. package/dist/src/index.d.ts +1 -33
  37. package/dist/src/index.d.ts.map +1 -1
  38. package/dist/src/index.js +1 -33
  39. package/dist/src/index.js.map +1 -1
  40. package/dist/src/multiaddr/is-global-unicast.d.ts.map +1 -1
  41. package/dist/src/multiaddr/is-global-unicast.js +9 -8
  42. package/dist/src/multiaddr/is-global-unicast.js.map +1 -1
  43. package/dist/src/multiaddr/is-ip-based.d.ts +6 -0
  44. package/dist/src/multiaddr/is-ip-based.d.ts.map +1 -0
  45. package/dist/src/multiaddr/is-ip-based.js +18 -0
  46. package/dist/src/multiaddr/is-ip-based.js.map +1 -0
  47. package/dist/src/multiaddr/is-link-local.d.ts.map +1 -1
  48. package/dist/src/multiaddr/is-link-local.js +16 -11
  49. package/dist/src/multiaddr/is-link-local.js.map +1 -1
  50. package/dist/src/multiaddr/is-loopback.d.ts.map +1 -1
  51. package/dist/src/multiaddr/is-loopback.js +5 -12
  52. package/dist/src/multiaddr/is-loopback.js.map +1 -1
  53. package/dist/src/multiaddr/is-network-address.d.ts.map +1 -1
  54. package/dist/src/multiaddr/is-network-address.js +16 -4
  55. package/dist/src/multiaddr/is-network-address.js.map +1 -1
  56. package/dist/src/multiaddr/is-private.d.ts.map +1 -1
  57. package/dist/src/multiaddr/is-private.js +10 -9
  58. package/dist/src/multiaddr/is-private.js.map +1 -1
  59. package/dist/src/queue/index.d.ts +0 -3
  60. package/dist/src/queue/index.d.ts.map +1 -1
  61. package/dist/src/queue/index.js +4 -20
  62. package/dist/src/queue/index.js.map +1 -1
  63. package/dist/src/rate-limiter.d.ts +15 -1
  64. package/dist/src/rate-limiter.d.ts.map +1 -1
  65. package/dist/src/rate-limiter.js +14 -1
  66. package/dist/src/rate-limiter.js.map +1 -1
  67. package/dist/src/stream-to-ma-conn.d.ts +23 -0
  68. package/dist/src/stream-to-ma-conn.d.ts.map +1 -0
  69. package/dist/src/stream-to-ma-conn.js +75 -0
  70. package/dist/src/stream-to-ma-conn.js.map +1 -0
  71. package/package.json +163 -19
  72. package/src/abort-options.ts +20 -0
  73. package/src/abstract-stream.ts +464 -51
  74. package/src/array-equals.ts +34 -0
  75. package/src/close-source.ts +14 -0
  76. package/src/close.ts +65 -0
  77. package/src/errors.ts +0 -10
  78. package/src/get-thin-waist-addresses.browser.ts +4 -5
  79. package/src/get-thin-waist-addresses.ts +12 -8
  80. package/src/index.ts +1 -33
  81. package/src/multiaddr/is-global-unicast.ts +11 -8
  82. package/src/multiaddr/is-ip-based.ts +21 -0
  83. package/src/multiaddr/is-link-local.ts +20 -11
  84. package/src/multiaddr/is-loopback.ts +7 -12
  85. package/src/multiaddr/is-network-address.ts +19 -4
  86. package/src/multiaddr/is-private.ts +14 -9
  87. package/src/queue/index.ts +4 -24
  88. package/src/rate-limiter.ts +30 -3
  89. package/src/stream-to-ma-conn.ts +106 -0
  90. package/dist/src/abstract-message-stream.d.ts +0 -129
  91. package/dist/src/abstract-message-stream.d.ts.map +0 -1
  92. package/dist/src/abstract-message-stream.js +0 -389
  93. package/dist/src/abstract-message-stream.js.map +0 -1
  94. package/dist/src/abstract-multiaddr-connection.d.ts +0 -26
  95. package/dist/src/abstract-multiaddr-connection.d.ts.map +0 -1
  96. package/dist/src/abstract-multiaddr-connection.js +0 -66
  97. package/dist/src/abstract-multiaddr-connection.js.map +0 -1
  98. package/dist/src/abstract-stream-muxer.d.ts +0 -53
  99. package/dist/src/abstract-stream-muxer.d.ts.map +0 -1
  100. package/dist/src/abstract-stream-muxer.js +0 -169
  101. package/dist/src/abstract-stream-muxer.js.map +0 -1
  102. package/dist/src/length-prefixed-decoder.d.ts +0 -37
  103. package/dist/src/length-prefixed-decoder.d.ts.map +0 -1
  104. package/dist/src/length-prefixed-decoder.js +0 -64
  105. package/dist/src/length-prefixed-decoder.js.map +0 -1
  106. package/dist/src/message-queue.d.ts +0 -61
  107. package/dist/src/message-queue.d.ts.map +0 -1
  108. package/dist/src/message-queue.js +0 -93
  109. package/dist/src/message-queue.js.map +0 -1
  110. package/dist/src/mock-muxer.d.ts +0 -57
  111. package/dist/src/mock-muxer.d.ts.map +0 -1
  112. package/dist/src/mock-muxer.js +0 -204
  113. package/dist/src/mock-muxer.js.map +0 -1
  114. package/dist/src/mock-stream.d.ts +0 -31
  115. package/dist/src/mock-stream.d.ts.map +0 -1
  116. package/dist/src/mock-stream.js +0 -69
  117. package/dist/src/mock-stream.js.map +0 -1
  118. package/dist/src/multiaddr/get-net-config.d.ts +0 -55
  119. package/dist/src/multiaddr/get-net-config.d.ts.map +0 -1
  120. package/dist/src/multiaddr/get-net-config.js +0 -54
  121. package/dist/src/multiaddr/get-net-config.js.map +0 -1
  122. package/dist/src/multiaddr/index.d.ts +0 -7
  123. package/dist/src/multiaddr/index.d.ts.map +0 -1
  124. package/dist/src/multiaddr/index.js +0 -7
  125. package/dist/src/multiaddr/index.js.map +0 -1
  126. package/dist/src/multiaddr/utils.d.ts +0 -5
  127. package/dist/src/multiaddr/utils.d.ts.map +0 -1
  128. package/dist/src/multiaddr/utils.js +0 -32
  129. package/dist/src/multiaddr/utils.js.map +0 -1
  130. package/dist/src/multiaddr-connection-pair.d.ts +0 -25
  131. package/dist/src/multiaddr-connection-pair.d.ts.map +0 -1
  132. package/dist/src/multiaddr-connection-pair.js +0 -103
  133. package/dist/src/multiaddr-connection-pair.js.map +0 -1
  134. package/dist/src/socket-writer.browser.d.ts +0 -2
  135. package/dist/src/socket-writer.browser.d.ts.map +0 -1
  136. package/dist/src/socket-writer.browser.js +0 -4
  137. package/dist/src/socket-writer.browser.js.map +0 -1
  138. package/dist/src/socket-writer.d.ts +0 -19
  139. package/dist/src/socket-writer.d.ts.map +0 -1
  140. package/dist/src/socket-writer.js +0 -43
  141. package/dist/src/socket-writer.js.map +0 -1
  142. package/dist/src/stream-pair.d.ts +0 -42
  143. package/dist/src/stream-pair.d.ts.map +0 -1
  144. package/dist/src/stream-pair.js +0 -40
  145. package/dist/src/stream-pair.js.map +0 -1
  146. package/dist/src/stream-utils.d.ts +0 -198
  147. package/dist/src/stream-utils.d.ts.map +0 -1
  148. package/dist/src/stream-utils.js +0 -369
  149. package/dist/src/stream-utils.js.map +0 -1
  150. package/src/abstract-message-stream.ts +0 -549
  151. package/src/abstract-multiaddr-connection.ts +0 -93
  152. package/src/abstract-stream-muxer.ts +0 -239
  153. package/src/length-prefixed-decoder.ts +0 -98
  154. package/src/message-queue.ts +0 -156
  155. package/src/mock-muxer.ts +0 -304
  156. package/src/mock-stream.ts +0 -101
  157. package/src/multiaddr/get-net-config.ts +0 -112
  158. package/src/multiaddr/index.ts +0 -6
  159. package/src/multiaddr/utils.ts +0 -46
  160. package/src/multiaddr-connection-pair.ts +0 -147
  161. package/src/socket-writer.browser.ts +0 -3
  162. package/src/socket-writer.ts +0 -64
  163. package/src/stream-pair.ts +0 -90
  164. package/src/stream-utils.ts +0 -873
@@ -1,239 +0,0 @@
1
- import { MuxerClosedError, TypedEventEmitter } from '@libp2p/interface'
2
- import { raceSignal } from 'race-signal'
3
- import { MaxEarlyStreamsError } from './errors.ts'
4
- import { isPromise } from './is-promise.ts'
5
- import type { AbstractStream } from './abstract-stream.ts'
6
- import type { AbortOptions, CounterGroup, CreateStreamOptions, EventHandler, Logger, MessageStream, Stream, StreamCloseEvent, StreamMessageEvent, StreamMuxer, StreamMuxerEvents, StreamMuxerOptions, StreamMuxerStatus, StreamOptions } from '@libp2p/interface'
7
- import type { Uint8ArrayList } from 'uint8arraylist'
8
-
9
- export interface AbstractStreamMuxerInit extends StreamMuxerOptions {
10
- /**
11
- * The protocol name for the muxer
12
- */
13
- protocol: string
14
-
15
- /**
16
- * The name of the muxer, used to create a new logging scope from the passed
17
- * connection's logger
18
- */
19
- name: string
20
-
21
- /**
22
- * A counter for muxer metrics
23
- */
24
- metrics?: CounterGroup
25
- }
26
-
27
- export abstract class AbstractStreamMuxer <MuxedStream extends AbstractStream = AbstractStream> extends TypedEventEmitter<StreamMuxerEvents<MuxedStream>> implements StreamMuxer<MuxedStream> {
28
- public streams: MuxedStream[]
29
- public protocol: string
30
- public status: StreamMuxerStatus
31
-
32
- protected log: Logger
33
- protected maConn: MessageStream
34
- protected streamOptions?: StreamOptions
35
- protected earlyStreams: MuxedStream[]
36
- protected maxEarlyStreams: number
37
-
38
- private readonly metrics?: CounterGroup
39
-
40
- constructor (maConn: MessageStream, init: AbstractStreamMuxerInit) {
41
- super()
42
-
43
- this.maConn = maConn
44
- this.protocol = init.protocol
45
- this.streams = []
46
- this.earlyStreams = []
47
- this.status = 'open'
48
- this.log = maConn.log.newScope(init.name)
49
- this.streamOptions = init.streamOptions
50
- this.maxEarlyStreams = init.maxEarlyStreams ?? 10
51
- this.metrics = init.metrics
52
-
53
- // read/write all data from/to underlying maConn
54
- const muxerMaConnOnMessage = (evt: StreamMessageEvent): void => {
55
- try {
56
- this.onData(evt.data)
57
- } catch (err: any) {
58
- this.abort(err)
59
- this.maConn.abort(err)
60
- }
61
- }
62
- this.maConn.addEventListener('message', muxerMaConnOnMessage)
63
-
64
- // signal stream writers when the underlying connection can accept more data
65
- const muxerMaConnOnDrain = (): void => {
66
- this.log('underlying stream drained, signal %d streams to continue writing', this.streams.length)
67
-
68
- this.streams.forEach(stream => {
69
- stream.onMuxerDrain()
70
- })
71
- }
72
- this.maConn.addEventListener('drain', muxerMaConnOnDrain)
73
-
74
- const muxerOnMaConnClose = (): void => {
75
- this.log('underlying stream closed with status %s and %d streams', this.status, this.streams.length)
76
- this.onTransportClosed()
77
- }
78
- this.maConn.addEventListener('close', muxerOnMaConnClose)
79
- }
80
-
81
- send (data: Uint8Array | Uint8ArrayList): boolean {
82
- const result = this.maConn.send(data)
83
-
84
- if (result === false) {
85
- this.log('underlying stream saturated, signal %d streams to pause writing', this.streams.length)
86
-
87
- this.streams.forEach(stream => {
88
- stream.onMuxerNeedsDrain()
89
- })
90
- }
91
-
92
- return result
93
- }
94
-
95
- async close (options?: AbortOptions): Promise<void> {
96
- if (this.status === 'closed' || this.status === 'closing') {
97
- return
98
- }
99
-
100
- this.status = 'closing'
101
-
102
- await raceSignal(Promise.all(
103
- [...this.streams].map(async s => {
104
- await s.close(options)
105
- })
106
- ), options?.signal)
107
-
108
- this.status = 'closed'
109
- }
110
-
111
- abort (err: Error): void {
112
- if (this.status === 'closed') {
113
- return
114
- }
115
-
116
- this.status = 'closing'
117
-
118
- ;[...this.streams].forEach(s => {
119
- s.abort(err)
120
- })
121
-
122
- this.status = 'closed'
123
- }
124
-
125
- onTransportClosed (err?: Error): void {
126
- this.status = 'closing'
127
-
128
- try {
129
- [...this.streams].forEach(stream => {
130
- stream.onTransportClosed(err)
131
- })
132
- } catch (err: any) {
133
- this.abort(err)
134
- }
135
-
136
- this.status = 'closed'
137
- }
138
-
139
- async createStream (options?: CreateStreamOptions): Promise<MuxedStream> {
140
- if (this.status !== 'open') {
141
- throw new MuxerClosedError()
142
- }
143
-
144
- let stream = this.onCreateStream({
145
- ...this.streamOptions,
146
- ...options
147
- })
148
-
149
- if (isPromise(stream)) {
150
- stream = await stream
151
- }
152
-
153
- this.streams.push(stream)
154
- this.cleanUpStream(stream)
155
-
156
- return stream
157
- }
158
-
159
- /**
160
- * Extending classes should invoke this method when a new stream was created
161
- * by the remote muxer
162
- */
163
- onRemoteStream (stream: MuxedStream): void {
164
- this.streams.push(stream)
165
- this.cleanUpStream(stream)
166
-
167
- if (this.listenerCount('stream') === 0) {
168
- // no listener has been added for the stream event yet, store the stream
169
- // to emit it later
170
- this.earlyStreams.push(stream)
171
-
172
- if (this.earlyStreams.length > this.maxEarlyStreams) {
173
- this.abort(new MaxEarlyStreamsError(`Too many early streams were opened - ${this.earlyStreams.length}/${this.maxEarlyStreams}`))
174
- }
175
-
176
- return
177
- }
178
-
179
- this.safeDispatchEvent('stream', {
180
- detail: stream
181
- })
182
- }
183
-
184
- private cleanUpStream (stream: Stream): void {
185
- const muxerOnStreamEnd = (evt: StreamCloseEvent): void => {
186
- const index = this.streams.findIndex(s => s === stream)
187
-
188
- if (index !== -1) {
189
- this.streams.splice(index, 1)
190
- }
191
-
192
- if (evt.error != null) {
193
- if (evt.local) {
194
- this.metrics?.increment({ [`${stream.direction}_stream_reset`]: true })
195
- } else {
196
- this.metrics?.increment({ [`${stream.direction}_stream_abort`]: true })
197
- }
198
- } else {
199
- this.metrics?.increment({ [`${stream.direction}_stream_end`]: true })
200
- }
201
- }
202
- stream.addEventListener('close', muxerOnStreamEnd)
203
-
204
- this.metrics?.increment({ [`${stream.direction}_stream`]: true })
205
- }
206
-
207
- addEventListener<K extends keyof StreamMuxerEvents<MuxedStream>>(type: K, listener: EventHandler<StreamMuxerEvents<MuxedStream>[K]> | null, options?: boolean | AddEventListenerOptions): void
208
- addEventListener (type: string, listener: EventHandler<Event>, options?: boolean | AddEventListenerOptions): void
209
- addEventListener (...args: any[]): void {
210
- // @ts-expect-error cannot ensure args has enough members
211
- super.addEventListener.apply(this, args)
212
-
213
- // if a 'stream' listener is being added and we have early streams, emit
214
- // them
215
- if (args[0] === 'stream' && this.earlyStreams.length > 0) {
216
- // event listeners can be added in constructors and often use object
217
- // properties - if this the case we can access a class member before it
218
- // has been initialized so dispatch the message in the microtask queue
219
- queueMicrotask(() => {
220
- this.earlyStreams.forEach(stream => {
221
- this.safeDispatchEvent('stream', {
222
- detail: stream
223
- })
224
- })
225
- this.earlyStreams = []
226
- })
227
- }
228
- }
229
-
230
- /**
231
- * A new outgoing stream needs to be created
232
- */
233
- abstract onCreateStream (options: CreateStreamOptions): MuxedStream | Promise<MuxedStream>
234
-
235
- /**
236
- * Multiplexed data was received from the remote muxer
237
- */
238
- abstract onData (data: Uint8Array | Uint8ArrayList): void
239
- }
@@ -1,98 +0,0 @@
1
- import { InvalidParametersError } from '@libp2p/interface'
2
- import * as varint from 'uint8-varint'
3
- import { Uint8ArrayList } from 'uint8arraylist'
4
- import { InvalidMessageLengthError } from './stream-utils.ts'
5
-
6
- const DEFAULT_MAX_BUFFER_SIZE = 1024 * 1024 * 4
7
- const DEFAULT_MAX_DATA_LENGTH = 1024 * 1024 * 4
8
-
9
- export interface LengthPrefixedDecoderInit {
10
- /**
11
- * How large the internal buffer is allowed to grow - attempting to store more
12
- * data than this will throw
13
- */
14
- maxBufferSize?: number
15
-
16
- /**
17
- * Throw an error if the message that would be read from the buffer is larger
18
- * than this value
19
- */
20
- maxDataLength?: number
21
-
22
- /**
23
- * Read a varint from the buffer
24
- */
25
- lengthDecoder?(data: Uint8ArrayList | Uint8Array): number
26
-
27
- /**
28
- * Return how many bytes it takes to encode the passed value
29
- */
30
- encodingLength?(length: number): number
31
- }
32
-
33
- /**
34
- * Decode length-prefixed data from a buffer
35
- */
36
- export class LengthPrefixedDecoder {
37
- private readonly buffer: Uint8ArrayList
38
- private readonly maxBufferSize: number
39
- private readonly lengthDecoder: (data: Uint8ArrayList | Uint8Array) => number
40
- private readonly maxDataLength: number
41
- private readonly encodingLength: (length: number) => number
42
-
43
- constructor (init: LengthPrefixedDecoderInit = {}) {
44
- this.buffer = new Uint8ArrayList()
45
- this.maxBufferSize = init.maxBufferSize ?? DEFAULT_MAX_BUFFER_SIZE
46
- this.maxDataLength = init.maxDataLength ?? DEFAULT_MAX_DATA_LENGTH
47
- this.lengthDecoder = init.lengthDecoder ?? varint.decode
48
- this.encodingLength = init.encodingLength ?? varint.encodingLength
49
- }
50
-
51
- /**
52
- * Decodes length-prefixed data
53
- */
54
- * decode (buf: Uint8Array | Uint8ArrayList): Generator<Uint8ArrayList> {
55
- this.buffer.append(buf)
56
-
57
- if (this.buffer.byteLength > this.maxBufferSize) {
58
- throw new InvalidParametersError(`Buffer length limit exceeded - ${this.buffer.byteLength}/${this.maxBufferSize}`)
59
- }
60
-
61
- // Loop to consume as many bytes from the buffer as possible
62
- // Eg: when a single chunk contains several frames
63
- while (true) {
64
- let dataLength: number
65
-
66
- try {
67
- dataLength = this.lengthDecoder(this.buffer)
68
- } catch (err) {
69
- if (err instanceof RangeError) {
70
- // ignore errors where we don't have enough data to read the length
71
- // prefix
72
- break
73
- }
74
-
75
- throw err
76
- }
77
-
78
- if (dataLength < 0 || dataLength > this.maxDataLength) {
79
- throw new InvalidMessageLengthError('Invalid message length')
80
- }
81
-
82
- const lengthLength = this.encodingLength(dataLength)
83
- const chunkLength = lengthLength + dataLength
84
-
85
- if (this.buffer.byteLength >= chunkLength) {
86
- const buf = this.buffer.sublist(lengthLength, chunkLength)
87
-
88
- this.buffer.consume(chunkLength)
89
-
90
- if (buf.byteLength > 0) {
91
- yield buf
92
- }
93
- } else {
94
- break
95
- }
96
- }
97
- }
98
- }
@@ -1,156 +0,0 @@
1
- import { StreamMessageEvent } from '@libp2p/interface'
2
- import delay from 'delay'
3
- import { TypedEventEmitter } from 'main-event'
4
- import { raceSignal } from 'race-signal'
5
- import { isUint8ArrayList, Uint8ArrayList } from 'uint8arraylist'
6
- import { Queue } from './queue/index.js'
7
- import type { AbortOptions, Logger } from '@libp2p/interface'
8
-
9
- const DEFAULT_CHUNK_SIZE = 1024 * 64
10
-
11
- export interface MessageQueueEvents {
12
- /**
13
- * Message data
14
- */
15
- message: StreamMessageEvent
16
-
17
- /**
18
- * Emitted when the queue is empty
19
- */
20
- drain: Event
21
-
22
- /**
23
- * The remote closed the connection abruptly
24
- */
25
- reset: Event
26
- }
27
-
28
- export interface MessageQueueInit {
29
- /**
30
- * How much delay there should be between each message send in ms (note that
31
- * even 0 introduces a small delay)
32
- *
33
- * @default 0
34
- */
35
- delay?: number
36
-
37
- /**
38
- * How many messages to hold in the send queue before applying backpressure to
39
- * the sender
40
- */
41
- capacity?: number
42
-
43
- /**
44
- * Data messages larger than this size will be chunked into smaller messages.
45
- *
46
- * Defaults to the maximum TCP package size.
47
- *
48
- * @default 65_536
49
- */
50
- chunkSize?: number
51
- }
52
-
53
- interface MessageQueueJobOptions extends AbortOptions {
54
- evt: Event
55
- }
56
-
57
- /**
58
- * Accepts events to emit after a short delay, and with a configurable maximum
59
- * queue capacity after which the send method will return false to let us
60
- * simulate write backpressure.
61
- */
62
- export class MessageQueue<Events> extends TypedEventEmitter<Events & MessageQueueEvents> {
63
- public needsDrain: boolean
64
-
65
- private queue: Queue<void, MessageQueueJobOptions>
66
- private capacity: number
67
- private delay: number
68
- private log: Logger
69
- private chunkSize: number
70
-
71
- constructor (init: MessageQueueInit & { log: Logger }) {
72
- super()
73
-
74
- this.needsDrain = false
75
- this.queue = new Queue({
76
- concurrency: 1
77
- })
78
- this.capacity = init.capacity ?? 5
79
- this.delay = init.delay ?? 0
80
- this.log = init.log
81
- this.chunkSize = init.chunkSize ?? DEFAULT_CHUNK_SIZE
82
-
83
- this.queue.addEventListener('idle', () => {
84
- if (this.needsDrain) {
85
- this.log('network send queue drained')
86
- this.needsDrain = false
87
- this.safeDispatchEvent('drain')
88
- } else {
89
- this.log('network send queue idle')
90
- }
91
- })
92
- }
93
-
94
- send (evt: Event): boolean {
95
- if (isMessageEvent(evt)) {
96
- // chunk outgoing messages to match TCP packet sizes
97
- const data = new Uint8ArrayList(evt.data)
98
-
99
- while (data.byteLength > 0) {
100
- const end = Math.min(this.chunkSize, data.byteLength)
101
- const chunk = data.sublist(0, end)
102
- data.consume(chunk.byteLength)
103
-
104
- const chunkEvent = new StreamMessageEvent(chunk)
105
-
106
- this.queue.add(async (opts) => {
107
- if (this.delay > 0) {
108
- await raceSignal(delay(this.delay), opts.signal)
109
- }
110
-
111
- this.dispatchEvent(opts.evt)
112
- }, {
113
- evt: chunkEvent
114
- })
115
- }
116
- } else {
117
- this.queue.add(async (opts) => {
118
- if (this.delay > 0) {
119
- await raceSignal(delay(this.delay), opts.signal)
120
- }
121
-
122
- this.dispatchEvent(opts.evt)
123
- }, {
124
- evt
125
- })
126
- }
127
-
128
- if (this.queue.size >= this.capacity) {
129
- this.log('network send queue full')
130
- this.needsDrain = true
131
- return false
132
- }
133
-
134
- return true
135
- }
136
-
137
- pause (): void {
138
- this.queue.pause()
139
- }
140
-
141
- resume (): void {
142
- this.queue.resume()
143
- }
144
-
145
- onIdle (): Promise<void> {
146
- return this.queue.onIdle()
147
- }
148
-
149
- size (): number {
150
- return this.queue.size
151
- }
152
- }
153
-
154
- function isMessageEvent (evt?: any): evt is StreamMessageEvent {
155
- return evt?.data instanceof Uint8Array || isUint8ArrayList(evt?.data)
156
- }