@libp2p/utils 5.0.3 → 5.1.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.
@@ -1,8 +1,9 @@
1
1
  import PQueue from 'p-queue';
2
2
  import type { PeerId } from '@libp2p/interface';
3
+ import type { AbortOptions } from 'it-pushable';
3
4
  import type { QueueAddOptions, Options, Queue } from 'p-queue';
4
- interface RunFunction {
5
- (): Promise<unknown>;
5
+ interface RunFunction<T> {
6
+ (options?: AbortOptions): Promise<T>;
6
7
  }
7
8
  export interface PeerPriorityQueueOptions extends QueueAddOptions {
8
9
  peerId: PeerId;
@@ -11,23 +12,31 @@ export interface PeerPriorityQueueOptions extends QueueAddOptions {
11
12
  * Port of https://github.com/sindresorhus/p-queue/blob/main/source/priority-queue.ts
12
13
  * that adds support for filtering jobs by peer id
13
14
  */
14
- declare class PeerPriorityQueue implements Queue<RunFunction, PeerPriorityQueueOptions> {
15
+ declare class PeerPriorityQueue implements Queue<RunFunction<unknown>, PeerPriorityQueueOptions> {
15
16
  #private;
16
- enqueue(run: RunFunction, options?: Partial<PeerPriorityQueueOptions>): void;
17
- dequeue(): RunFunction | undefined;
18
- filter(options: Readonly<Partial<PeerPriorityQueueOptions>>): RunFunction[];
17
+ enqueue(run: RunFunction<unknown>, options?: Partial<PeerPriorityQueueOptions>): void;
18
+ dequeue(): RunFunction<unknown> | undefined;
19
+ filter(options: Readonly<Partial<PeerPriorityQueueOptions>>): Array<RunFunction<unknown>>;
19
20
  get size(): number;
20
21
  }
21
22
  /**
22
23
  * Extends PQueue to add support for querying queued jobs by peer id
23
24
  */
24
25
  export declare class PeerJobQueue extends PQueue<PeerPriorityQueue, PeerPriorityQueueOptions> {
26
+ private readonly results;
25
27
  constructor(options?: Options<PeerPriorityQueue, PeerPriorityQueueOptions>);
26
28
  /**
27
- * Returns true if this queue has a job for the passed peer id that has not yet
28
- * started to run
29
+ * Returns true if this queue has a job for the passed peer id that has not
30
+ * yet started to run
29
31
  */
30
32
  hasJob(peerId: PeerId): boolean;
33
+ /**
34
+ * Returns a promise for the result of the job in the queue for the passed
35
+ * peer id.
36
+ */
37
+ joinJob<Result = void>(peerId: PeerId): Promise<Result>;
38
+ add<T>(fn: RunFunction<T>, opts: PeerPriorityQueueOptions): Promise<T>;
39
+ clear(): void;
31
40
  }
32
41
  export {};
33
42
  //# sourceMappingURL=peer-job-queue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"peer-job-queue.d.ts","sourceRoot":"","sources":["../../src/peer-job-queue.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,SAAS,CAAA;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAuB9D,UAAU,WAAW;IAAG,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;CAAE;AAE9C,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC/D,MAAM,EAAE,MAAM,CAAA;CACf;AAQD;;;GAGG;AACH,cAAM,iBAAkB,YAAW,KAAK,CAAC,WAAW,EAAE,wBAAwB,CAAC;;IAG7E,OAAO,CAAE,GAAG,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,IAAI;IA0B7E,OAAO,IAAK,WAAW,GAAG,SAAS;IAKnC,MAAM,CAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,GAAG,WAAW,EAAE;IAc5E,IAAI,IAAI,IAAK,MAAM,CAElB;CACF;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;gBACtE,OAAO,GAAE,OAAO,CAAC,iBAAiB,EAAE,wBAAwB,CAAM;IAO/E;;;OAGG;IACH,MAAM,CAAE,MAAM,EAAE,MAAM,GAAG,OAAO;CAKjC"}
1
+ {"version":3,"file":"peer-job-queue.d.ts","sourceRoot":"","sources":["../../src/peer-job-queue.ts"],"names":[],"mappings":"AAKA,OAAO,MAAM,MAAM,SAAS,CAAA;AAC5B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE/C,OAAO,KAAK,EAAE,eAAe,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAA;AAuB9D,UAAU,WAAW,CAAC,CAAC;IACrB,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;CACrC;AAED,MAAM,WAAW,wBAAyB,SAAQ,eAAe;IAC/D,MAAM,EAAE,MAAM,CAAA;CACf;AAQD;;;GAGG;AACH,cAAM,iBAAkB,YAAW,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,wBAAwB,CAAC;;IAGtF,OAAO,CAAE,GAAG,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,IAAI;IA0BtF,OAAO,IAAK,WAAW,CAAC,OAAO,CAAC,GAAG,SAAS;IAK5C,MAAM,CAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,wBAAwB,CAAC,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IAc1F,IAAI,IAAI,IAAK,MAAM,CAElB;CACF;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,MAAM,CAAC,iBAAiB,EAAE,wBAAwB,CAAC;IACnF,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAsC;gBAEjD,OAAO,GAAE,OAAO,CAAC,iBAAiB,EAAE,wBAAwB,CAAM;IAS/E;;;OAGG;IACH,MAAM,CAAE,MAAM,EAAE,MAAM,GAAG,OAAO;IAMhC;;;OAGG;IACG,OAAO,CAAE,MAAM,GAAG,IAAI,EAAG,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBzD,GAAG,CAAE,CAAC,EAAG,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,wBAAwB,GAAG,OAAO,CAAC,CAAC,CAAC;IAkC9E,KAAK,IAAK,IAAI;CAIf"}
@@ -1,5 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
  import { CodeError, ERR_INVALID_PARAMETERS } from '@libp2p/interface';
3
+ import { PeerMap } from '@libp2p/peer-collections';
4
+ import pDefer from 'p-defer';
3
5
  import PQueue from 'p-queue';
4
6
  // Port of lower_bound from https://en.cppreference.com/w/cpp/algorithm/lower_bound
5
7
  // Used to compute insertion index to keep queue sorted after insertion
@@ -62,20 +64,69 @@ class PeerPriorityQueue {
62
64
  * Extends PQueue to add support for querying queued jobs by peer id
63
65
  */
64
66
  export class PeerJobQueue extends PQueue {
67
+ results;
65
68
  constructor(options = {}) {
66
69
  super({
67
70
  ...options,
68
71
  queueClass: PeerPriorityQueue
69
72
  });
73
+ this.results = new PeerMap();
70
74
  }
71
75
  /**
72
- * Returns true if this queue has a job for the passed peer id that has not yet
73
- * started to run
76
+ * Returns true if this queue has a job for the passed peer id that has not
77
+ * yet started to run
74
78
  */
75
79
  hasJob(peerId) {
76
80
  return this.sizeBy({
77
81
  peerId
78
82
  }) > 0;
79
83
  }
84
+ /**
85
+ * Returns a promise for the result of the job in the queue for the passed
86
+ * peer id.
87
+ */
88
+ async joinJob(peerId) {
89
+ let deferred = this.results.get(peerId);
90
+ if (deferred == null) {
91
+ throw new CodeError('No job found for peer id', 'ERR_NO_JOB_FOR_PEER_ID');
92
+ }
93
+ if (deferred === true) {
94
+ // a job has been added but so far nothing has tried to join the job
95
+ deferred = pDefer();
96
+ this.results.set(peerId, deferred);
97
+ }
98
+ return deferred.promise;
99
+ }
100
+ async add(fn, opts) {
101
+ const peerId = opts?.peerId;
102
+ if (peerId == null) {
103
+ throw new CodeError('missing peer id', ERR_INVALID_PARAMETERS);
104
+ }
105
+ this.results.set(opts.peerId, true);
106
+ return super.add(async (opts) => {
107
+ try {
108
+ const value = await fn(opts);
109
+ const deferred = this.results.get(peerId);
110
+ if (deferred != null && deferred !== true) {
111
+ deferred.resolve(value);
112
+ }
113
+ return value;
114
+ }
115
+ catch (err) {
116
+ const deferred = this.results.get(peerId);
117
+ if (deferred != null && deferred !== true) {
118
+ deferred.reject(err);
119
+ }
120
+ throw err;
121
+ }
122
+ finally {
123
+ this.results.delete(peerId);
124
+ }
125
+ }, opts);
126
+ }
127
+ clear() {
128
+ this.results.clear();
129
+ super.clear();
130
+ }
80
131
  }
81
132
  //# sourceMappingURL=peer-job-queue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"peer-job-queue.js","sourceRoot":"","sources":["../../src/peer-job-queue.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"peer-job-queue.js","sourceRoot":"","sources":["../../src/peer-job-queue.ts"],"names":[],"mappings":"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"}
@@ -31,7 +31,7 @@ export function streamToMaConnection(props) {
31
31
  // If the source errored the socket will already have been destroyed by
32
32
  // toIterable.duplex(). If the socket errored it will already be
33
33
  // destroyed. There's nothing to do here except log the error & return.
34
- log(err);
34
+ log.error('%s error in sink', remoteAddr, err);
35
35
  }
36
36
  }
37
37
  finally {
@@ -1 +1 @@
1
- {"version":3,"file":"stream-to-ma-conn.js","sourceRoot":"","sources":["../../src/stream-to-ma-conn.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAE,KAAuB;IAC3D,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,yBAAyB,CAAC,CAAA;IAE1D,IAAI,UAAU,GAAG,KAAK,CAAA;IACtB,IAAI,WAAW,GAAG,KAAK,CAAA;IAEvB,0DAA0D;IAC1D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7C,MAAM,CAAC,KAAK,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE;QAC/B,MAAM,WAAW,CAAC,OAAO,CAAC,CAAA;QAC1B,KAAK,CAAC,IAAI,CAAC,CAAA;IACb,CAAC,CAAA;IAED,0DAA0D;IAC1D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7C,MAAM,CAAC,KAAK,GAAG,CAAC,GAAG,EAAE,EAAE;QACrB,WAAW,CAAC,GAAG,CAAC,CAAA;QAChB,KAAK,CAAC,IAAI,CAAC,CAAA;IACb,CAAC,CAAA;IAED,yDAAyD;IACzD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3C,MAAM,CAAC,IAAI,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;QAC1B,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,kCAAkC;YAClC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC3B,uEAAuE;gBACvE,gEAAgE;gBAChE,uEAAuE;gBACvE,GAAG,CAAC,GAAG,CAAC,CAAA;YACV,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,WAAW,GAAG,IAAI,CAAA;YAClB,KAAK,EAAE,CAAA;QACT,CAAC;IACH,CAAC,CAAA;IAED,MAAM,MAAM,GAAwB;QAClC,GAAG;QACH,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,CAAC,KAAK,SAAU,CAAC;YACvB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBACvC,IAAI,IAAI,YAAY,UAAU,EAAE,CAAC;wBAC/B,MAAM,IAAI,CAAA;oBACZ,CAAC;yBAAM,CAAC;wBACN,KAAM,CAAC,CAAC,IAAI,CAAA;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,UAAU,GAAG,IAAI,CAAA;gBACjB,KAAK,EAAE,CAAA;YACT,CAAC;QACH,CAAC,EAAE,CAAC;QACJ,UAAU;QACV,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;QAChD,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAA;IAED,SAAS,KAAK,CAAE,KAAe;QAC7B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,UAAU,GAAG,IAAI,CAAA;YACjB,WAAW,GAAG,IAAI,CAAA;QACpB,CAAC;QAED,IAAI,UAAU,IAAI,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;YAC/D,MAAM,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACpC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
1
+ {"version":3,"file":"stream-to-ma-conn.js","sourceRoot":"","sources":["../../src/stream-to-ma-conn.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAAE,KAAuB;IAC3D,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,KAAK,CAAA;IAC5C,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,yBAAyB,CAAC,CAAA;IAE1D,IAAI,UAAU,GAAG,KAAK,CAAA;IACtB,IAAI,WAAW,GAAG,KAAK,CAAA;IAEvB,0DAA0D;IAC1D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7C,MAAM,CAAC,KAAK,GAAG,KAAK,EAAE,OAAO,EAAE,EAAE;QAC/B,MAAM,WAAW,CAAC,OAAO,CAAC,CAAA;QAC1B,KAAK,CAAC,IAAI,CAAC,CAAA;IACb,CAAC,CAAA;IAED,0DAA0D;IAC1D,MAAM,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7C,MAAM,CAAC,KAAK,GAAG,CAAC,GAAG,EAAE,EAAE;QACrB,WAAW,CAAC,GAAG,CAAC,CAAA;QAChB,KAAK,CAAC,IAAI,CAAC,CAAA;IACb,CAAC,CAAA;IAED,yDAAyD;IACzD,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC3C,MAAM,CAAC,IAAI,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,MAAM,UAAU,CAAC,MAAM,CAAC,CAAA;QAC1B,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,kCAAkC;YAClC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gBAC3B,uEAAuE;gBACvE,gEAAgE;gBAChE,uEAAuE;gBACvE,GAAG,CAAC,KAAK,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,CAAC,CAAA;YAChD,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,WAAW,GAAG,IAAI,CAAA;YAClB,KAAK,EAAE,CAAA;QACT,CAAC;IACH,CAAC,CAAA;IAED,MAAM,MAAM,GAAwB;QAClC,GAAG;QACH,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,MAAM,EAAE,CAAC,KAAK,SAAU,CAAC;YACvB,IAAI,CAAC;gBACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;oBACvC,IAAI,IAAI,YAAY,UAAU,EAAE,CAAC;wBAC/B,MAAM,IAAI,CAAA;oBACZ,CAAC;yBAAM,CAAC;wBACN,KAAM,CAAC,CAAC,IAAI,CAAA;oBACd,CAAC;gBACH,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,UAAU,GAAG,IAAI,CAAA;gBACjB,KAAK,EAAE,CAAA;YACT,CAAC;QACH,CAAC,EAAE,CAAC;QACJ,UAAU;QACV,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE;QAChD,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,KAAK,EAAE,MAAM,CAAC,KAAK;KACpB,CAAA;IAED,SAAS,KAAK,CAAE,KAAe;QAC7B,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACnB,UAAU,GAAG,IAAI,CAAA;YACjB,WAAW,GAAG,IAAI,CAAA;QACpB,CAAC;QAED,IAAI,UAAU,IAAI,WAAW,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;YAC/D,MAAM,CAAC,QAAQ,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QACpC,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@libp2p/utils",
3
- "version": "5.0.3",
3
+ "version": "5.1.0",
4
4
  "description": "Package to aggregate shared logic and dependencies for the libp2p ecosystem",
5
5
  "license": "Apache-2.0 OR MIT",
6
6
  "homepage": "https://github.com/libp2p/js-libp2p/tree/main/packages/utils#readme",
@@ -112,13 +112,14 @@
112
112
  "dependencies": {
113
113
  "@chainsafe/is-ip": "^2.0.2",
114
114
  "@libp2p/interface": "^1.0.2",
115
+ "@libp2p/peer-collections": "^5.1.1",
115
116
  "@multiformats/multiaddr": "^12.1.10",
116
117
  "@multiformats/multiaddr-matcher": "^1.1.0",
117
118
  "get-iterator": "^2.0.1",
118
119
  "is-loopback-addr": "^2.0.1",
119
120
  "it-pushable": "^3.2.2",
120
121
  "it-stream-types": "^2.0.1",
121
- "p-queue": "^7.4.1",
122
+ "p-queue": "^8.0.0",
122
123
  "private-ip": "^3.0.1",
123
124
  "race-signal": "^1.0.1",
124
125
  "uint8arraylist": "^2.4.3"
@@ -1,8 +1,12 @@
1
1
  /* eslint-disable @typescript-eslint/no-non-null-assertion */
2
2
 
3
3
  import { CodeError, ERR_INVALID_PARAMETERS } from '@libp2p/interface'
4
+ import { PeerMap } from '@libp2p/peer-collections'
5
+ import pDefer from 'p-defer'
4
6
  import PQueue from 'p-queue'
5
7
  import type { PeerId } from '@libp2p/interface'
8
+ import type { AbortOptions } from 'it-pushable'
9
+ import type { DeferredPromise } from 'p-defer'
6
10
  import type { QueueAddOptions, Options, Queue } from 'p-queue'
7
11
 
8
12
  // Port of lower_bound from https://en.cppreference.com/w/cpp/algorithm/lower_bound
@@ -26,7 +30,9 @@ function lowerBound<T> (array: readonly T[], value: T, comparator: (a: T, b: T)
26
30
  return first
27
31
  }
28
32
 
29
- interface RunFunction { (): Promise<unknown> }
33
+ interface RunFunction<T> {
34
+ (options?: AbortOptions): Promise<T>
35
+ }
30
36
 
31
37
  export interface PeerPriorityQueueOptions extends QueueAddOptions {
32
38
  peerId: PeerId
@@ -35,17 +41,17 @@ export interface PeerPriorityQueueOptions extends QueueAddOptions {
35
41
  interface PeerJob {
36
42
  priority: number
37
43
  peerId: PeerId
38
- run: RunFunction
44
+ run: RunFunction<any>
39
45
  }
40
46
 
41
47
  /**
42
48
  * Port of https://github.com/sindresorhus/p-queue/blob/main/source/priority-queue.ts
43
49
  * that adds support for filtering jobs by peer id
44
50
  */
45
- class PeerPriorityQueue implements Queue<RunFunction, PeerPriorityQueueOptions> {
51
+ class PeerPriorityQueue implements Queue<RunFunction<unknown>, PeerPriorityQueueOptions> {
46
52
  readonly #queue: PeerJob[] = []
47
53
 
48
- enqueue (run: RunFunction, options?: Partial<PeerPriorityQueueOptions>): void {
54
+ enqueue (run: RunFunction<unknown>, options?: Partial<PeerPriorityQueueOptions>): void {
49
55
  const peerId = options?.peerId
50
56
  const priority = options?.priority ?? 0
51
57
 
@@ -71,23 +77,23 @@ class PeerPriorityQueue implements Queue<RunFunction, PeerPriorityQueueOptions>
71
77
  this.#queue.splice(index, 0, element)
72
78
  }
73
79
 
74
- dequeue (): RunFunction | undefined {
80
+ dequeue (): RunFunction<unknown> | undefined {
75
81
  const item = this.#queue.shift()
76
82
  return item?.run
77
83
  }
78
84
 
79
- filter (options: Readonly<Partial<PeerPriorityQueueOptions>>): RunFunction[] {
85
+ filter (options: Readonly<Partial<PeerPriorityQueueOptions>>): Array<RunFunction<unknown>> {
80
86
  if (options.peerId != null) {
81
87
  const peerId = options.peerId
82
88
 
83
89
  return this.#queue.filter(
84
90
  (element: Readonly<PeerPriorityQueueOptions>) => peerId.equals(element.peerId)
85
- ).map((element: Readonly<{ run: RunFunction }>) => element.run)
91
+ ).map((element: Readonly<{ run: RunFunction<unknown> }>) => element.run)
86
92
  }
87
93
 
88
94
  return this.#queue.filter(
89
95
  (element: Readonly<PeerPriorityQueueOptions>) => element.priority === options.priority
90
- ).map((element: Readonly<{ run: RunFunction }>) => element.run)
96
+ ).map((element: Readonly<{ run: RunFunction<unknown> }>) => element.run)
91
97
  }
92
98
 
93
99
  get size (): number {
@@ -99,20 +105,83 @@ class PeerPriorityQueue implements Queue<RunFunction, PeerPriorityQueueOptions>
99
105
  * Extends PQueue to add support for querying queued jobs by peer id
100
106
  */
101
107
  export class PeerJobQueue extends PQueue<PeerPriorityQueue, PeerPriorityQueueOptions> {
108
+ private readonly results: PeerMap<DeferredPromise<any> | true>
109
+
102
110
  constructor (options: Options<PeerPriorityQueue, PeerPriorityQueueOptions> = {}) {
103
111
  super({
104
112
  ...options,
105
113
  queueClass: PeerPriorityQueue
106
114
  })
115
+
116
+ this.results = new PeerMap()
107
117
  }
108
118
 
109
119
  /**
110
- * Returns true if this queue has a job for the passed peer id that has not yet
111
- * started to run
120
+ * Returns true if this queue has a job for the passed peer id that has not
121
+ * yet started to run
112
122
  */
113
123
  hasJob (peerId: PeerId): boolean {
114
124
  return this.sizeBy({
115
125
  peerId
116
126
  }) > 0
117
127
  }
128
+
129
+ /**
130
+ * Returns a promise for the result of the job in the queue for the passed
131
+ * peer id.
132
+ */
133
+ async joinJob <Result = void> (peerId: PeerId): Promise<Result> {
134
+ let deferred = this.results.get(peerId)
135
+
136
+ if (deferred == null) {
137
+ throw new CodeError('No job found for peer id', 'ERR_NO_JOB_FOR_PEER_ID')
138
+ }
139
+
140
+ if (deferred === true) {
141
+ // a job has been added but so far nothing has tried to join the job
142
+ deferred = pDefer<Result>()
143
+ this.results.set(peerId, deferred)
144
+ }
145
+
146
+ return deferred.promise
147
+ }
148
+
149
+ async add <T> (fn: RunFunction<T>, opts: PeerPriorityQueueOptions): Promise<T> {
150
+ const peerId = opts?.peerId
151
+
152
+ if (peerId == null) {
153
+ throw new CodeError('missing peer id', ERR_INVALID_PARAMETERS)
154
+ }
155
+
156
+ this.results.set(opts.peerId, true)
157
+
158
+ return super.add(async (opts?: AbortOptions) => {
159
+ try {
160
+ const value = await fn(opts)
161
+
162
+ const deferred = this.results.get(peerId)
163
+
164
+ if (deferred != null && deferred !== true) {
165
+ deferred.resolve(value)
166
+ }
167
+
168
+ return value
169
+ } catch (err) {
170
+ const deferred = this.results.get(peerId)
171
+
172
+ if (deferred != null && deferred !== true) {
173
+ deferred.reject(err)
174
+ }
175
+
176
+ throw err
177
+ } finally {
178
+ this.results.delete(peerId)
179
+ }
180
+ }, opts) as Promise<T>
181
+ }
182
+
183
+ clear (): void {
184
+ this.results.clear()
185
+ super.clear()
186
+ }
118
187
  }
@@ -44,7 +44,7 @@ export function streamToMaConnection (props: StreamProperties): MultiaddrConnect
44
44
  // If the source errored the socket will already have been destroyed by
45
45
  // toIterable.duplex(). If the socket errored it will already be
46
46
  // destroyed. There's nothing to do here except log the error & return.
47
- log(err)
47
+ log.error('%s error in sink', remoteAddr, err)
48
48
  }
49
49
  } finally {
50
50
  closedWrite = true