@libp2p/utils 6.7.1 → 6.7.2-a02cb0461
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/README.md +16 -1
- package/dist/index.min.js +6 -1
- package/dist/index.min.js.map +4 -4
- package/dist/src/abstract-message-stream.d.ts +129 -0
- package/dist/src/abstract-message-stream.d.ts.map +1 -0
- package/dist/src/abstract-message-stream.js +389 -0
- package/dist/src/abstract-message-stream.js.map +1 -0
- package/dist/src/abstract-multiaddr-connection.d.ts +26 -0
- package/dist/src/abstract-multiaddr-connection.d.ts.map +1 -0
- package/dist/src/abstract-multiaddr-connection.js +66 -0
- package/dist/src/abstract-multiaddr-connection.js.map +1 -0
- package/dist/src/abstract-stream-muxer.d.ts +53 -0
- package/dist/src/abstract-stream-muxer.d.ts.map +1 -0
- package/dist/src/abstract-stream-muxer.js +169 -0
- package/dist/src/abstract-stream-muxer.js.map +1 -0
- package/dist/src/abstract-stream.d.ts +14 -130
- package/dist/src/abstract-stream.d.ts.map +1 -1
- package/dist/src/abstract-stream.js +39 -321
- package/dist/src/abstract-stream.js.map +1 -1
- package/dist/src/errors.d.ts +8 -0
- package/dist/src/errors.d.ts.map +1 -1
- package/dist/src/errors.js +8 -0
- package/dist/src/errors.js.map +1 -1
- package/dist/src/index.d.ts +33 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +33 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/length-prefixed-decoder.d.ts +37 -0
- package/dist/src/length-prefixed-decoder.d.ts.map +1 -0
- package/dist/src/length-prefixed-decoder.js +64 -0
- package/dist/src/length-prefixed-decoder.js.map +1 -0
- package/dist/src/message-queue.d.ts +61 -0
- package/dist/src/message-queue.d.ts.map +1 -0
- package/dist/src/message-queue.js +93 -0
- package/dist/src/message-queue.js.map +1 -0
- package/dist/src/mock-muxer.d.ts +57 -0
- package/dist/src/mock-muxer.d.ts.map +1 -0
- package/dist/src/mock-muxer.js +204 -0
- package/dist/src/mock-muxer.js.map +1 -0
- package/dist/src/mock-stream.d.ts +31 -0
- package/dist/src/mock-stream.d.ts.map +1 -0
- package/dist/src/mock-stream.js +69 -0
- package/dist/src/mock-stream.js.map +1 -0
- package/dist/src/multiaddr/index.d.ts +7 -0
- package/dist/src/multiaddr/index.d.ts.map +1 -0
- package/dist/src/multiaddr/index.js +7 -0
- package/dist/src/multiaddr/index.js.map +1 -0
- package/dist/src/multiaddr-connection-pair.d.ts +25 -0
- package/dist/src/multiaddr-connection-pair.d.ts.map +1 -0
- package/dist/src/multiaddr-connection-pair.js +103 -0
- package/dist/src/multiaddr-connection-pair.js.map +1 -0
- package/dist/src/queue/index.d.ts +5 -0
- package/dist/src/queue/index.d.ts.map +1 -1
- package/dist/src/queue/index.js +24 -9
- package/dist/src/queue/index.js.map +1 -1
- package/dist/src/rate-limiter.d.ts +1 -15
- package/dist/src/rate-limiter.d.ts.map +1 -1
- package/dist/src/rate-limiter.js +1 -14
- package/dist/src/rate-limiter.js.map +1 -1
- package/dist/src/socket-writer.browser.d.ts +2 -0
- package/dist/src/socket-writer.browser.d.ts.map +1 -0
- package/dist/src/socket-writer.browser.js +4 -0
- package/dist/src/socket-writer.browser.js.map +1 -0
- package/dist/src/socket-writer.d.ts +19 -0
- package/dist/src/socket-writer.d.ts.map +1 -0
- package/dist/src/socket-writer.js +43 -0
- package/dist/src/socket-writer.js.map +1 -0
- package/dist/src/stream-pair.d.ts +42 -0
- package/dist/src/stream-pair.d.ts.map +1 -0
- package/dist/src/stream-pair.js +40 -0
- package/dist/src/stream-pair.js.map +1 -0
- package/dist/src/stream-utils.d.ts +199 -0
- package/dist/src/stream-utils.d.ts.map +1 -0
- package/dist/src/stream-utils.js +369 -0
- package/dist/src/stream-utils.js.map +1 -0
- package/package.json +19 -163
- package/src/abstract-message-stream.ts +549 -0
- package/src/abstract-multiaddr-connection.ts +93 -0
- package/src/abstract-stream-muxer.ts +239 -0
- package/src/abstract-stream.ts +51 -464
- package/src/errors.ts +10 -0
- package/src/index.ts +33 -1
- package/src/length-prefixed-decoder.ts +98 -0
- package/src/message-queue.ts +156 -0
- package/src/mock-muxer.ts +304 -0
- package/src/mock-stream.ts +101 -0
- package/src/multiaddr/index.ts +6 -0
- package/src/multiaddr-connection-pair.ts +147 -0
- package/src/queue/index.ts +30 -9
- package/src/rate-limiter.ts +3 -30
- package/src/socket-writer.browser.ts +3 -0
- package/src/socket-writer.ts +64 -0
- package/src/stream-pair.ts +90 -0
- package/src/stream-utils.ts +874 -0
- package/dist/src/abort-options.d.ts +0 -7
- package/dist/src/abort-options.d.ts.map +0 -1
- package/dist/src/abort-options.js +0 -14
- package/dist/src/abort-options.js.map +0 -1
- package/dist/src/array-equals.d.ts +0 -24
- package/dist/src/array-equals.d.ts.map +0 -1
- package/dist/src/array-equals.js +0 -31
- package/dist/src/array-equals.js.map +0 -1
- package/dist/src/close-source.d.ts +0 -4
- package/dist/src/close-source.d.ts.map +0 -1
- package/dist/src/close-source.js +0 -11
- package/dist/src/close-source.js.map +0 -1
- package/dist/src/close.d.ts +0 -21
- package/dist/src/close.d.ts.map +0 -1
- package/dist/src/close.js +0 -49
- package/dist/src/close.js.map +0 -1
- package/dist/src/stream-to-ma-conn.d.ts +0 -23
- package/dist/src/stream-to-ma-conn.d.ts.map +0 -1
- package/dist/src/stream-to-ma-conn.js +0 -75
- package/dist/src/stream-to-ma-conn.js.map +0 -1
- package/dist/typedoc-urls.json +0 -147
- package/src/abort-options.ts +0 -20
- package/src/array-equals.ts +0 -34
- package/src/close-source.ts +0 -14
- package/src/close.ts +0 -65
- package/src/stream-to-ma-conn.ts +0 -105
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { StreamMessageEvent } from '@libp2p/interface'
|
|
2
|
+
import { defaultLogger } from '@libp2p/logger'
|
|
3
|
+
import { multiaddr } from '@multiformats/multiaddr'
|
|
4
|
+
import { pEvent } from 'p-event'
|
|
5
|
+
import { raceSignal } from 'race-signal'
|
|
6
|
+
import { AbstractMultiaddrConnection } from './abstract-multiaddr-connection.ts'
|
|
7
|
+
import { MessageQueue } from './message-queue.ts'
|
|
8
|
+
import type { SendResult } from './abstract-message-stream.ts'
|
|
9
|
+
import type { AbstractMultiaddrConnectionInit } from './abstract-multiaddr-connection.ts'
|
|
10
|
+
import type { MessageQueueEvents, MessageQueueInit } from './message-queue.ts'
|
|
11
|
+
import type { AbortOptions, Logger, MultiaddrConnection, MessageStreamDirection, TypedEventTarget } from '@libp2p/interface'
|
|
12
|
+
import type { Multiaddr } from '@multiformats/multiaddr'
|
|
13
|
+
import type { Uint8ArrayList } from 'uint8arraylist'
|
|
14
|
+
|
|
15
|
+
interface MockMultiaddrConnectionMessages extends MessageQueueEvents {
|
|
16
|
+
close: Event
|
|
17
|
+
pause: Event
|
|
18
|
+
resume: Event
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface MockMultiaddrConnectionInit extends AbstractMultiaddrConnectionInit {
|
|
22
|
+
id: string,
|
|
23
|
+
log: Logger,
|
|
24
|
+
direction: MessageStreamDirection
|
|
25
|
+
local: MessageQueue<MockMultiaddrConnectionMessages>
|
|
26
|
+
remote: TypedEventTarget<MockMultiaddrConnectionMessages>
|
|
27
|
+
remoteAddr: Multiaddr
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let multiaddrConnectionId = 0
|
|
31
|
+
|
|
32
|
+
class MockMultiaddrConnection extends AbstractMultiaddrConnection {
|
|
33
|
+
private local: MessageQueue<MockMultiaddrConnectionMessages>
|
|
34
|
+
private remote: TypedEventTarget<MockMultiaddrConnectionMessages>
|
|
35
|
+
|
|
36
|
+
constructor (init: MockMultiaddrConnectionInit) {
|
|
37
|
+
super(init)
|
|
38
|
+
|
|
39
|
+
this.local = init.local
|
|
40
|
+
this.remote = init.remote
|
|
41
|
+
|
|
42
|
+
this.local.addEventListener('drain', () => {
|
|
43
|
+
this.safeDispatchEvent('drain')
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
this.remote.addEventListener('message', (evt) => {
|
|
47
|
+
if (this.status !== 'open') {
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
this.onData(evt.data)
|
|
52
|
+
})
|
|
53
|
+
this.remote.addEventListener('reset', (evt) => {
|
|
54
|
+
if (this.status !== 'open') {
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
this.onRemoteReset()
|
|
59
|
+
})
|
|
60
|
+
this.remote.addEventListener('close', (evt) => {
|
|
61
|
+
this.onTransportClosed()
|
|
62
|
+
})
|
|
63
|
+
this.remote.addEventListener('pause', (evt) => {
|
|
64
|
+
this.local.pause()
|
|
65
|
+
})
|
|
66
|
+
this.remote.addEventListener('resume', (evt) => {
|
|
67
|
+
this.local.resume()
|
|
68
|
+
})
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
sendData (data: Uint8ArrayList): SendResult {
|
|
72
|
+
const canSendMore = this.local.send(new StreamMessageEvent(data))
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
sentBytes: data.byteLength,
|
|
76
|
+
canSendMore
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
sendReset (): void {
|
|
81
|
+
this.local.send(new Event('reset'))
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async sendClose (options?: AbortOptions): Promise<void> {
|
|
85
|
+
if (this.local.needsDrain) {
|
|
86
|
+
await pEvent(this.local, 'drain', {
|
|
87
|
+
signal: options?.signal
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return raceSignal(new Promise<void>((resolve, reject) => {
|
|
92
|
+
this.local.send(new Event('close'))
|
|
93
|
+
this.local.onIdle().then(resolve, reject)
|
|
94
|
+
}), options?.signal)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
sendPause (): void {
|
|
98
|
+
this.local.send(new Event('pause'))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
sendResume (): void {
|
|
102
|
+
this.local.send(new Event('resume'))
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface MultiaddrConnectionPairOptions extends MessageQueueInit {
|
|
107
|
+
outbound?: Partial<MockMultiaddrConnectionInit>
|
|
108
|
+
inbound?: Partial<MockMultiaddrConnectionInit>
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function multiaddrConnectionPair (opts: MultiaddrConnectionPairOptions = {}): [MultiaddrConnection, MultiaddrConnection] {
|
|
112
|
+
const inboundId = `${multiaddrConnectionId++}`
|
|
113
|
+
const outboundId = `${multiaddrConnectionId++}`
|
|
114
|
+
|
|
115
|
+
const outboundLog = defaultLogger().forComponent(`libp2p:mock-maconn:outbound:${inboundId}`)
|
|
116
|
+
const inboundLog = defaultLogger().forComponent(`libp2p:mock-maconn:inbound:${outboundId}`)
|
|
117
|
+
|
|
118
|
+
const targetA = new MessageQueue<MockMultiaddrConnectionMessages>({
|
|
119
|
+
...opts,
|
|
120
|
+
log: outboundLog
|
|
121
|
+
})
|
|
122
|
+
const targetB = new MessageQueue<MockMultiaddrConnectionMessages>({
|
|
123
|
+
...opts,
|
|
124
|
+
log: inboundLog
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
return [
|
|
128
|
+
new MockMultiaddrConnection({
|
|
129
|
+
...opts.outbound,
|
|
130
|
+
id: outboundId,
|
|
131
|
+
direction: 'outbound',
|
|
132
|
+
local: targetA,
|
|
133
|
+
remote: targetB,
|
|
134
|
+
remoteAddr: opts?.outbound?.remoteAddr ?? multiaddr(`/ip4/127.0.0.1/tcp/${outboundId}`),
|
|
135
|
+
log: outboundLog
|
|
136
|
+
}),
|
|
137
|
+
new MockMultiaddrConnection({
|
|
138
|
+
...opts.inbound,
|
|
139
|
+
id: inboundId,
|
|
140
|
+
direction: 'inbound',
|
|
141
|
+
local: targetB,
|
|
142
|
+
remote: targetA,
|
|
143
|
+
remoteAddr: opts?.inbound?.remoteAddr ?? multiaddr(`/ip4/127.0.0.1/tcp/${inboundId}`),
|
|
144
|
+
log: inboundLog
|
|
145
|
+
})
|
|
146
|
+
]
|
|
147
|
+
}
|
package/src/queue/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AbortError } from '@libp2p/interface'
|
|
2
2
|
import { pushable } from 'it-pushable'
|
|
3
3
|
import { TypedEventEmitter } from 'main-event'
|
|
4
|
-
import {
|
|
4
|
+
import { pEvent } from 'p-event'
|
|
5
5
|
import { debounce } from '../debounce.js'
|
|
6
6
|
import { QueueFullError } from '../errors.js'
|
|
7
7
|
import { Job } from './job.js'
|
|
@@ -101,6 +101,8 @@ export interface QueueEvents<JobReturnType, JobOptions extends AbortOptions = Ab
|
|
|
101
101
|
|
|
102
102
|
/**
|
|
103
103
|
* A job has failed
|
|
104
|
+
*
|
|
105
|
+
* @deprecated Listen for the 'failure' event instead - it gives more context and is generally more useful, this event will be removed in a future release
|
|
104
106
|
*/
|
|
105
107
|
error: CustomEvent<Error>
|
|
106
108
|
|
|
@@ -129,6 +131,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
129
131
|
public queue: Array<Job<JobOptions, JobReturnType>>
|
|
130
132
|
private pending: number
|
|
131
133
|
private readonly sort?: Comparator<Job<JobOptions, JobReturnType>>
|
|
134
|
+
private paused: boolean
|
|
132
135
|
|
|
133
136
|
constructor (init: QueueInit<JobReturnType, JobOptions> = {}) {
|
|
134
137
|
super()
|
|
@@ -136,6 +139,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
136
139
|
this.concurrency = init.concurrency ?? Number.POSITIVE_INFINITY
|
|
137
140
|
this.maxSize = init.maxSize ?? Number.POSITIVE_INFINITY
|
|
138
141
|
this.pending = 0
|
|
142
|
+
this.paused = false
|
|
139
143
|
|
|
140
144
|
if (init.metricName != null) {
|
|
141
145
|
init.metrics?.registerMetricGroup(init.metricName, {
|
|
@@ -172,7 +176,24 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
172
176
|
this.safeDispatchEvent('idle')
|
|
173
177
|
}
|
|
174
178
|
|
|
179
|
+
pause (): void {
|
|
180
|
+
this.paused = true
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
resume (): void {
|
|
184
|
+
if (!this.paused) {
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
this.paused = false
|
|
189
|
+
this.tryToStartAnother()
|
|
190
|
+
}
|
|
191
|
+
|
|
175
192
|
private tryToStartAnother (): boolean {
|
|
193
|
+
if (this.paused) {
|
|
194
|
+
return false
|
|
195
|
+
}
|
|
196
|
+
|
|
176
197
|
if (this.size === 0) {
|
|
177
198
|
this.emitEmpty()
|
|
178
199
|
|
|
@@ -263,7 +284,6 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
263
284
|
}
|
|
264
285
|
}
|
|
265
286
|
|
|
266
|
-
this.safeDispatchEvent('error', { detail: err })
|
|
267
287
|
this.safeDispatchEvent('failure', { detail: { job, error: err } })
|
|
268
288
|
|
|
269
289
|
throw err
|
|
@@ -299,7 +319,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
299
319
|
return
|
|
300
320
|
}
|
|
301
321
|
|
|
302
|
-
await
|
|
322
|
+
await pEvent(this, 'empty', options)
|
|
303
323
|
}
|
|
304
324
|
|
|
305
325
|
/**
|
|
@@ -319,7 +339,8 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
319
339
|
return
|
|
320
340
|
}
|
|
321
341
|
|
|
322
|
-
await
|
|
342
|
+
await pEvent(this, 'next', {
|
|
343
|
+
...options,
|
|
323
344
|
filter: () => this.size < limit
|
|
324
345
|
})
|
|
325
346
|
}
|
|
@@ -338,7 +359,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
338
359
|
return
|
|
339
360
|
}
|
|
340
361
|
|
|
341
|
-
await
|
|
362
|
+
await pEvent(this, 'idle', options)
|
|
342
363
|
}
|
|
343
364
|
|
|
344
365
|
/**
|
|
@@ -395,8 +416,8 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
395
416
|
}
|
|
396
417
|
}
|
|
397
418
|
|
|
398
|
-
const
|
|
399
|
-
cleanup(evt.detail)
|
|
419
|
+
const onQueueFailure = (evt: CustomEvent<QueueJobFailure<JobReturnType, JobOptions>>): void => {
|
|
420
|
+
cleanup(evt.detail.error)
|
|
400
421
|
}
|
|
401
422
|
|
|
402
423
|
const onQueueIdle = (): void => {
|
|
@@ -410,7 +431,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
410
431
|
|
|
411
432
|
// add listeners
|
|
412
433
|
this.addEventListener('completed', onQueueJobComplete)
|
|
413
|
-
this.addEventListener('
|
|
434
|
+
this.addEventListener('failure', onQueueFailure)
|
|
414
435
|
this.addEventListener('idle', onQueueIdle)
|
|
415
436
|
options?.signal?.addEventListener('abort', onSignalAbort)
|
|
416
437
|
|
|
@@ -419,7 +440,7 @@ export class Queue<JobReturnType = unknown, JobOptions extends AbortOptions = Ab
|
|
|
419
440
|
} finally {
|
|
420
441
|
// remove listeners
|
|
421
442
|
this.removeEventListener('completed', onQueueJobComplete)
|
|
422
|
-
this.removeEventListener('
|
|
443
|
+
this.removeEventListener('failure', onQueueFailure)
|
|
423
444
|
this.removeEventListener('idle', onQueueIdle)
|
|
424
445
|
options?.signal?.removeEventListener('abort', onSignalAbort)
|
|
425
446
|
|
package/src/rate-limiter.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import delay from 'delay'
|
|
2
1
|
import { RateLimitError } from './errors.js'
|
|
3
2
|
|
|
4
3
|
export interface RateLimiterInit {
|
|
@@ -23,20 +22,6 @@ export interface RateLimiterInit {
|
|
|
23
22
|
*/
|
|
24
23
|
blockDuration?: number
|
|
25
24
|
|
|
26
|
-
/**
|
|
27
|
-
* Execute allowed actions evenly over duration
|
|
28
|
-
*
|
|
29
|
-
* @default false
|
|
30
|
-
*/
|
|
31
|
-
execEvenly?: boolean
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* ms, works with execEvenly=true option
|
|
35
|
-
*
|
|
36
|
-
* @default duration * 1000 / points
|
|
37
|
-
*/
|
|
38
|
-
execEvenlyMinDelayMs?: number
|
|
39
|
-
|
|
40
25
|
/**
|
|
41
26
|
* @default "rlflx"
|
|
42
27
|
*/
|
|
@@ -65,21 +50,17 @@ export class RateLimiter {
|
|
|
65
50
|
protected points: number
|
|
66
51
|
protected duration: number
|
|
67
52
|
protected blockDuration: number
|
|
68
|
-
protected execEvenly: boolean
|
|
69
|
-
protected execEvenlyMinDelayMs: number
|
|
70
53
|
protected keyPrefix: string
|
|
71
54
|
|
|
72
55
|
constructor (opts: RateLimiterInit = {}) {
|
|
73
56
|
this.points = opts.points ?? 4
|
|
74
57
|
this.duration = opts.duration ?? 1
|
|
75
58
|
this.blockDuration = opts.blockDuration ?? 0
|
|
76
|
-
this.execEvenly = opts.execEvenly ?? false
|
|
77
|
-
this.execEvenlyMinDelayMs = opts.execEvenlyMinDelayMs ?? (this.duration * 1000 / this.points)
|
|
78
59
|
this.keyPrefix = opts.keyPrefix ?? 'rlflx'
|
|
79
60
|
this.memoryStorage = new MemoryStorage()
|
|
80
61
|
}
|
|
81
62
|
|
|
82
|
-
|
|
63
|
+
consume (key: string, pointsToConsume: number = 1, options: GetKeySecDurationOptions = {}): RateLimiterResult {
|
|
83
64
|
const rlKey = this.getKey(key)
|
|
84
65
|
const secDuration = this._getKeySecDuration(options)
|
|
85
66
|
let res = this.memoryStorage.incrby(rlKey, pointsToConsume, secDuration)
|
|
@@ -93,14 +74,6 @@ export class RateLimiter {
|
|
|
93
74
|
}
|
|
94
75
|
|
|
95
76
|
throw new RateLimitError('Rate limit exceeded', res)
|
|
96
|
-
} else if (this.execEvenly && res.msBeforeNext > 0 && !res.isFirstInDuration) {
|
|
97
|
-
// Execute evenly
|
|
98
|
-
let delayMs = Math.ceil(res.msBeforeNext / (res.remainingPoints + 2))
|
|
99
|
-
if (delayMs < this.execEvenlyMinDelayMs) {
|
|
100
|
-
delayMs = res.consumedPoints * this.execEvenlyMinDelayMs
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
await delay(delayMs)
|
|
104
77
|
}
|
|
105
78
|
|
|
106
79
|
return res
|
|
@@ -241,8 +214,8 @@ export class MemoryStorage {
|
|
|
241
214
|
this.storage.delete(key)
|
|
242
215
|
}, durationMs)
|
|
243
216
|
|
|
244
|
-
if (record.timeoutId.unref != null) {
|
|
245
|
-
record.timeoutId.unref()
|
|
217
|
+
if ((record.timeoutId as any).unref != null) {
|
|
218
|
+
(record.timeoutId as any).unref()
|
|
246
219
|
}
|
|
247
220
|
}
|
|
248
221
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import stream from 'node:stream'
|
|
2
|
+
import { Uint8ArrayList } from 'uint8arraylist'
|
|
3
|
+
|
|
4
|
+
export interface SocketWriter {
|
|
5
|
+
/**
|
|
6
|
+
* Write any available data into the socket, if the socket's internal write
|
|
7
|
+
* buffer has available capacity
|
|
8
|
+
*/
|
|
9
|
+
pull (): boolean
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Write data into the socket, returns false if the socket's internal write
|
|
13
|
+
* buffer is at capacity
|
|
14
|
+
*/
|
|
15
|
+
write (data: Uint8Array | Uint8Array[] | Uint8ArrayList): boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @deprecated delete if unused
|
|
20
|
+
*/
|
|
21
|
+
export function socketWriter (socket: stream.Duplex): SocketWriter {
|
|
22
|
+
const queue = new Uint8ArrayList()
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
pull (): boolean {
|
|
26
|
+
if (socket.writableNeedDrain) {
|
|
27
|
+
return false
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
for (const buf of queue) {
|
|
31
|
+
queue.consume(buf.byteLength)
|
|
32
|
+
|
|
33
|
+
if (!socket.write(buf)) {
|
|
34
|
+
// continue writing after drain event. this is a synchronous operation
|
|
35
|
+
// so it will not interleave with the `this.writeToSocket()`
|
|
36
|
+
// invocation in this.sendData so all data will be sent in-order
|
|
37
|
+
if (queue.byteLength > 0) {
|
|
38
|
+
socket.once('drain', () => {
|
|
39
|
+
this.pull()
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return false
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return true
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
write (data: Uint8Array | Uint8Array[] | Uint8ArrayList): boolean {
|
|
51
|
+
if (Array.isArray(data)) {
|
|
52
|
+
queue.appendAll(data)
|
|
53
|
+
} else {
|
|
54
|
+
queue.append(data)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (socket.writableNeedDrain) {
|
|
58
|
+
return false
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return this.pull()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { pEvent } from 'p-event'
|
|
2
|
+
import { mockMuxer } from './mock-muxer.ts'
|
|
3
|
+
import { multiaddrConnectionPair } from './multiaddr-connection-pair.ts'
|
|
4
|
+
import { echo } from './stream-utils.ts'
|
|
5
|
+
import type { MockMultiaddrConnectionInit } from './multiaddr-connection-pair.ts'
|
|
6
|
+
import type { Stream, StreamOptions } from '@libp2p/interface'
|
|
7
|
+
|
|
8
|
+
export interface StreamPairOptions {
|
|
9
|
+
/**
|
|
10
|
+
* How long to wait in ms before sending messages
|
|
11
|
+
*
|
|
12
|
+
* @default 1
|
|
13
|
+
*/
|
|
14
|
+
delay?: number
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* If more than this many messages are sent within delay, write backpressure
|
|
18
|
+
* will be applied
|
|
19
|
+
*/
|
|
20
|
+
capacity?: number
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Simulate having pre-negotiated a protocol by passing it here
|
|
24
|
+
*/
|
|
25
|
+
protocol?: string
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Configuration options for the outbound stream
|
|
29
|
+
*/
|
|
30
|
+
outbound?: StreamOptions
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Configuration options for underlying outbound connection
|
|
34
|
+
*/
|
|
35
|
+
outboundConnection?: Partial<MockMultiaddrConnectionInit>
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Configuration options for the inbound stream
|
|
39
|
+
*/
|
|
40
|
+
inbound?: StreamOptions
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Configuration options for underlying inbound connection
|
|
44
|
+
*/
|
|
45
|
+
inboundConnection?: Partial<MockMultiaddrConnectionInit>
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Returns two streams connected to each other with a slight delay in sending
|
|
50
|
+
* messages to simulate a network
|
|
51
|
+
*/
|
|
52
|
+
export async function streamPair (opts: StreamPairOptions = {}): Promise<[Stream, Stream]> {
|
|
53
|
+
const [outboundConnection, inboundConnection] = multiaddrConnectionPair({
|
|
54
|
+
...opts,
|
|
55
|
+
outbound: opts.outboundConnection,
|
|
56
|
+
inbound: opts.inboundConnection
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
const localMuxer = mockMuxer({
|
|
60
|
+
streamOptions: opts.outbound
|
|
61
|
+
}).createStreamMuxer(outboundConnection)
|
|
62
|
+
const remoteMuxer = mockMuxer({
|
|
63
|
+
streamOptions: opts.inbound
|
|
64
|
+
}).createStreamMuxer(inboundConnection)
|
|
65
|
+
|
|
66
|
+
const [
|
|
67
|
+
inboundStream,
|
|
68
|
+
outboundStream
|
|
69
|
+
] = await Promise.all([
|
|
70
|
+
pEvent<'stream', CustomEvent<Stream>>(remoteMuxer, 'stream').then(evt => {
|
|
71
|
+
return evt.detail
|
|
72
|
+
}),
|
|
73
|
+
localMuxer.createStream({
|
|
74
|
+
...opts.outbound,
|
|
75
|
+
protocol: opts.protocol
|
|
76
|
+
})
|
|
77
|
+
])
|
|
78
|
+
|
|
79
|
+
return [
|
|
80
|
+
outboundStream,
|
|
81
|
+
inboundStream
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export async function echoStream (opts: StreamPairOptions = {}): Promise<Stream> {
|
|
86
|
+
const [outbound, inbound] = await streamPair(opts)
|
|
87
|
+
echo(inbound)
|
|
88
|
+
|
|
89
|
+
return outbound
|
|
90
|
+
}
|