@lodestar/beacon-node 1.40.0-rc.2 → 1.40.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/lib/chain/archiveStore/archiveStore.d.ts.map +1 -1
- package/lib/chain/archiveStore/archiveStore.js +10 -4
- package/lib/chain/archiveStore/archiveStore.js.map +1 -1
- package/lib/chain/blocks/importBlock.d.ts.map +1 -1
- package/lib/chain/blocks/importBlock.js +9 -1
- package/lib/chain/blocks/importBlock.js.map +1 -1
- package/lib/chain/chain.d.ts.map +1 -1
- package/lib/chain/chain.js +5 -2
- package/lib/chain/chain.js.map +1 -1
- package/lib/chain/lightClient/index.d.ts +2 -0
- package/lib/chain/lightClient/index.d.ts.map +1 -1
- package/lib/chain/lightClient/index.js +10 -4
- package/lib/chain/lightClient/index.js.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts +7 -7
- package/lib/chain/seenCache/seenGossipBlockInput.d.ts.map +1 -1
- package/lib/chain/seenCache/seenGossipBlockInput.js +20 -9
- package/lib/chain/seenCache/seenGossipBlockInput.js.map +1 -1
- package/lib/util/queue/itemQueue.d.ts +10 -0
- package/lib/util/queue/itemQueue.d.ts.map +1 -1
- package/lib/util/queue/itemQueue.js +57 -0
- package/lib/util/queue/itemQueue.js.map +1 -1
- package/package.json +15 -15
- package/src/chain/archiveStore/archiveStore.ts +10 -4
- package/src/chain/blocks/importBlock.ts +9 -1
- package/src/chain/chain.ts +5 -2
- package/src/chain/lightClient/index.ts +11 -4
- package/src/chain/seenCache/seenGossipBlockInput.ts +28 -9
- package/src/util/queue/itemQueue.ts +62 -0
|
@@ -24,6 +24,8 @@ export class JobItemQueue<Args extends any[], R> {
|
|
|
24
24
|
private readonly metrics?: QueueMetrics;
|
|
25
25
|
private runningJobs = 0;
|
|
26
26
|
private lastYield = 0;
|
|
27
|
+
/** Resolvers waiting for space in the queue */
|
|
28
|
+
private spaceWaiters: (() => void)[] = [];
|
|
27
29
|
|
|
28
30
|
constructor(
|
|
29
31
|
private readonly itemProcessor: (...args: Args) => Promise<R>,
|
|
@@ -72,12 +74,57 @@ export class JobItemQueue<Args extends any[], R> {
|
|
|
72
74
|
});
|
|
73
75
|
}
|
|
74
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Returns a promise that resolves when there is space in the queue.
|
|
79
|
+
* If the queue already has space, resolves immediately (noop).
|
|
80
|
+
* Use this to apply backpressure when the caller should wait rather than
|
|
81
|
+
* have push() throw QUEUE_MAX_LENGTH.
|
|
82
|
+
*/
|
|
83
|
+
async waitForSpace(): Promise<void> {
|
|
84
|
+
if (this.opts.signal.aborted) {
|
|
85
|
+
throw new QueueError({code: QueueErrorCode.QUEUE_ABORTED});
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (this.jobs.length < this.opts.maxLength) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return new Promise<void>((resolve, reject) => {
|
|
93
|
+
let settled = false;
|
|
94
|
+
|
|
95
|
+
const onAbort = (): void => {
|
|
96
|
+
if (settled) return;
|
|
97
|
+
settled = true;
|
|
98
|
+
const index = this.spaceWaiters.indexOf(wrappedResolve);
|
|
99
|
+
if (index >= 0) {
|
|
100
|
+
this.spaceWaiters.splice(index, 1);
|
|
101
|
+
}
|
|
102
|
+
reject(new QueueError({code: QueueErrorCode.QUEUE_ABORTED}));
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const wrappedResolve = (): void => {
|
|
106
|
+
if (settled) return;
|
|
107
|
+
settled = true;
|
|
108
|
+
this.opts.signal.removeEventListener("abort", onAbort);
|
|
109
|
+
resolve();
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
this.spaceWaiters.push(wrappedResolve);
|
|
113
|
+
this.opts.signal.addEventListener("abort", onAbort, {once: true});
|
|
114
|
+
|
|
115
|
+
// Re-check after attaching listener to close the race window where
|
|
116
|
+
// signal.abort() fires between the initial check and addEventListener
|
|
117
|
+
if (this.opts.signal.aborted) onAbort();
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
75
121
|
getItems(): {args: Args; addedTimeMs: number}[] {
|
|
76
122
|
return this.jobs.map((job) => ({args: job.args, addedTimeMs: job.addedTimeMs}));
|
|
77
123
|
}
|
|
78
124
|
|
|
79
125
|
dropAllJobs = (): void => {
|
|
80
126
|
this.jobs.clear();
|
|
127
|
+
this.notifySpaceWaiters();
|
|
81
128
|
};
|
|
82
129
|
|
|
83
130
|
private runJob = async (): Promise<void> => {
|
|
@@ -115,10 +162,25 @@ export class JobItemQueue<Args extends any[], R> {
|
|
|
115
162
|
|
|
116
163
|
this.runningJobs = Math.max(0, this.runningJobs - 1);
|
|
117
164
|
|
|
165
|
+
// Notify any waiters that space is available
|
|
166
|
+
this.notifySpaceWaiters();
|
|
167
|
+
|
|
118
168
|
// Potentially run a new job
|
|
119
169
|
void this.runJob();
|
|
120
170
|
};
|
|
121
171
|
|
|
172
|
+
private notifySpaceWaiters(): void {
|
|
173
|
+
// Compute available slots once to avoid thundering herd: resolved waiters
|
|
174
|
+
// won't push() until the next microtask, so jobs.length doesn't change
|
|
175
|
+
// inside this loop. Without the cap we'd wake ALL waiters on a single slot.
|
|
176
|
+
let available = this.opts.maxLength - this.jobs.length;
|
|
177
|
+
while (available > 0 && this.spaceWaiters.length > 0) {
|
|
178
|
+
const resolve = this.spaceWaiters.shift();
|
|
179
|
+
if (resolve) resolve();
|
|
180
|
+
available--;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
122
184
|
private abortAllJobs = (): void => {
|
|
123
185
|
while (this.jobs.length > 0) {
|
|
124
186
|
const job = this.jobs.pop();
|