@aztec/prover-client 0.66.0 → 0.67.1-devnet

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 (83) hide show
  1. package/dest/block_builder/light.d.ts +4 -3
  2. package/dest/block_builder/light.d.ts.map +1 -1
  3. package/dest/block_builder/light.js +30 -20
  4. package/dest/index.d.ts +0 -1
  5. package/dest/index.d.ts.map +1 -1
  6. package/dest/index.js +1 -2
  7. package/dest/mocks/fixtures.d.ts +3 -3
  8. package/dest/mocks/fixtures.d.ts.map +1 -1
  9. package/dest/mocks/fixtures.js +2 -2
  10. package/dest/mocks/test_context.d.ts +10 -9
  11. package/dest/mocks/test_context.d.ts.map +1 -1
  12. package/dest/mocks/test_context.js +24 -13
  13. package/dest/orchestrator/block-building-helpers.d.ts +10 -6
  14. package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
  15. package/dest/orchestrator/block-building-helpers.js +27 -16
  16. package/dest/orchestrator/block-proving-state.d.ts +6 -5
  17. package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
  18. package/dest/orchestrator/block-proving-state.js +16 -8
  19. package/dest/orchestrator/epoch-proving-state.d.ts +1 -1
  20. package/dest/orchestrator/epoch-proving-state.d.ts.map +1 -1
  21. package/dest/orchestrator/epoch-proving-state.js +3 -3
  22. package/dest/orchestrator/orchestrator.d.ts +11 -8
  23. package/dest/orchestrator/orchestrator.d.ts.map +1 -1
  24. package/dest/orchestrator/orchestrator.js +94 -58
  25. package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
  26. package/dest/orchestrator/orchestrator_metrics.js +2 -5
  27. package/dest/prover-agent/memory-proving-queue.d.ts +2 -1
  28. package/dest/prover-agent/memory-proving-queue.d.ts.map +1 -1
  29. package/dest/prover-agent/memory-proving-queue.js +241 -224
  30. package/dest/prover-agent/prover-agent.d.ts +11 -2
  31. package/dest/prover-agent/prover-agent.d.ts.map +1 -1
  32. package/dest/prover-agent/prover-agent.js +187 -160
  33. package/dest/prover-client/prover-client.d.ts +2 -3
  34. package/dest/prover-client/prover-client.d.ts.map +1 -1
  35. package/dest/prover-client/prover-client.js +6 -9
  36. package/dest/proving_broker/broker_prover_facade.d.ts +26 -0
  37. package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -0
  38. package/dest/proving_broker/broker_prover_facade.js +107 -0
  39. package/dest/proving_broker/proving_agent.d.ts +4 -3
  40. package/dest/proving_broker/proving_agent.d.ts.map +1 -1
  41. package/dest/proving_broker/proving_agent.js +74 -65
  42. package/dest/proving_broker/proving_broker.d.ts +27 -7
  43. package/dest/proving_broker/proving_broker.d.ts.map +1 -1
  44. package/dest/proving_broker/proving_broker.js +405 -258
  45. package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
  46. package/dest/proving_broker/proving_broker_database/persisted.js +4 -8
  47. package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
  48. package/dest/proving_broker/proving_broker_instrumentation.js +2 -8
  49. package/dest/proving_broker/proving_job_controller.d.ts +2 -1
  50. package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
  51. package/dest/proving_broker/proving_job_controller.js +15 -14
  52. package/dest/proving_broker/rpc.js +2 -2
  53. package/dest/test/mock_prover.d.ts +6 -6
  54. package/dest/test/mock_prover.d.ts.map +1 -1
  55. package/dest/test/mock_prover.js +5 -5
  56. package/package.json +18 -13
  57. package/src/block_builder/light.ts +31 -22
  58. package/src/index.ts +0 -1
  59. package/src/mocks/fixtures.ts +4 -4
  60. package/src/mocks/test_context.ts +39 -24
  61. package/src/orchestrator/block-building-helpers.ts +33 -20
  62. package/src/orchestrator/block-proving-state.ts +17 -6
  63. package/src/orchestrator/epoch-proving-state.ts +0 -2
  64. package/src/orchestrator/orchestrator.ts +111 -62
  65. package/src/orchestrator/orchestrator_metrics.ts +1 -11
  66. package/src/prover-agent/memory-proving-queue.ts +12 -7
  67. package/src/prover-agent/prover-agent.ts +67 -48
  68. package/src/prover-client/prover-client.ts +5 -12
  69. package/src/proving_broker/{caching_broker_facade.ts → broker_prover_facade.ts} +62 -85
  70. package/src/proving_broker/proving_agent.ts +74 -78
  71. package/src/proving_broker/proving_broker.ts +240 -73
  72. package/src/proving_broker/proving_broker_database/persisted.ts +2 -8
  73. package/src/proving_broker/proving_broker_instrumentation.ts +0 -7
  74. package/src/proving_broker/proving_job_controller.ts +13 -12
  75. package/src/proving_broker/rpc.ts +1 -1
  76. package/src/test/mock_prover.ts +7 -3
  77. package/dest/proving_broker/caching_broker_facade.d.ts +0 -30
  78. package/dest/proving_broker/caching_broker_facade.d.ts.map +0 -1
  79. package/dest/proving_broker/caching_broker_facade.js +0 -150
  80. package/dest/proving_broker/prover_cache/memory.d.ts +0 -9
  81. package/dest/proving_broker/prover_cache/memory.d.ts.map +0 -1
  82. package/dest/proving_broker/prover_cache/memory.js +0 -16
  83. package/src/proving_broker/prover_cache/memory.ts +0 -20
@@ -1,284 +1,433 @@
1
+ import { __esDecorate, __runInitializers } from "tslib";
1
2
  import { ProvingRequestType, } from '@aztec/circuit-types';
2
- import { createDebugLogger } from '@aztec/foundation/log';
3
+ import { asyncPool } from '@aztec/foundation/async-pool';
4
+ import { createLogger } from '@aztec/foundation/log';
3
5
  import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
4
6
  import { PriorityMemoryQueue } from '@aztec/foundation/queue';
5
7
  import { Timer } from '@aztec/foundation/timer';
8
+ import { trackSpan } from '@aztec/telemetry-client';
6
9
  import assert from 'assert';
7
10
  import { ProvingBrokerInstrumentation } from './proving_broker_instrumentation.js';
8
11
  /**
9
12
  * A broker that manages proof requests and distributes them to workers based on their priority.
10
13
  * It takes a backend that is responsible for storing and retrieving proof requests and results.
11
14
  */
12
- export class ProvingBroker {
13
- constructor(database, client, { jobTimeoutMs = 30000, timeoutIntervalMs = 10000, maxRetries = 3 } = {}, logger = createDebugLogger('aztec:prover-client:proving-broker')) {
14
- this.database = database;
15
- this.logger = logger;
16
- this.queues = {
17
- [ProvingRequestType.PUBLIC_VM]: new PriorityMemoryQueue(provingJobComparator),
18
- [ProvingRequestType.TUBE_PROOF]: new PriorityMemoryQueue(provingJobComparator),
19
- [ProvingRequestType.PRIVATE_KERNEL_EMPTY]: new PriorityMemoryQueue(provingJobComparator),
20
- [ProvingRequestType.PRIVATE_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
21
- [ProvingRequestType.PUBLIC_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
22
- [ProvingRequestType.MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
23
- [ProvingRequestType.ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
24
- [ProvingRequestType.BLOCK_MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
25
- [ProvingRequestType.BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
26
- [ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
27
- [ProvingRequestType.BASE_PARITY]: new PriorityMemoryQueue(provingJobComparator),
28
- [ProvingRequestType.ROOT_PARITY]: new PriorityMemoryQueue(provingJobComparator),
29
- };
30
- // holds a copy of the database in memory in order to quickly fulfill requests
31
- // this is fine because this broker is the only one that can modify the database
32
- this.jobsCache = new Map();
33
- // as above, but for results
34
- this.resultsCache = new Map();
35
- // tracks when each job was enqueued
36
- this.enqueuedAt = new Map();
37
- // keeps track of which jobs are currently being processed
38
- // in the event of a crash this information is lost, but that's ok
39
- // the next time the broker starts it will recreate jobsCache and still
40
- // accept results from the workers
41
- this.inProgress = new Map();
42
- // keep track of which proving job has been retried
43
- this.retries = new Map();
44
- // a map of promises that will be resolved when a job is settled
45
- this.promises = new Map();
46
- this.timeSource = () => Math.floor(Date.now() / 1000);
47
- this.measureQueueDepth = (type) => {
48
- return this.queues[type].length();
49
- };
50
- this.countActiveJobs = (type) => {
51
- let count = 0;
52
- for (const { id } of this.inProgress.values()) {
53
- const job = this.jobsCache.get(id);
54
- if (job?.type === type) {
55
- count++;
15
+ let ProvingBroker = (() => {
16
+ var _a;
17
+ let _instanceExtraInitializers = [];
18
+ let _cleanupPass_decorators;
19
+ return _a = class ProvingBroker {
20
+ constructor(database, client, { jobTimeoutMs = 30000, timeoutIntervalMs = 10000, maxRetries = 3, maxEpochsToKeepResultsFor = 1, maxParallelCleanUps = 20, } = {}, logger = createLogger('prover-client:proving-broker')) {
21
+ this.database = (__runInitializers(this, _instanceExtraInitializers), database);
22
+ this.logger = logger;
23
+ this.queues = {
24
+ [ProvingRequestType.PUBLIC_VM]: new PriorityMemoryQueue(provingJobComparator),
25
+ [ProvingRequestType.TUBE_PROOF]: new PriorityMemoryQueue(provingJobComparator),
26
+ [ProvingRequestType.PRIVATE_KERNEL_EMPTY]: new PriorityMemoryQueue(provingJobComparator),
27
+ [ProvingRequestType.PRIVATE_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
28
+ [ProvingRequestType.PUBLIC_BASE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
29
+ [ProvingRequestType.MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
30
+ [ProvingRequestType.ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
31
+ [ProvingRequestType.BLOCK_MERGE_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
32
+ [ProvingRequestType.BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
33
+ [ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP]: new PriorityMemoryQueue(provingJobComparator),
34
+ [ProvingRequestType.BASE_PARITY]: new PriorityMemoryQueue(provingJobComparator),
35
+ [ProvingRequestType.ROOT_PARITY]: new PriorityMemoryQueue(provingJobComparator),
36
+ };
37
+ // holds a copy of the database in memory in order to quickly fulfill requests
38
+ // this is fine because this broker is the only one that can modify the database
39
+ this.jobsCache = new Map();
40
+ // as above, but for results
41
+ this.resultsCache = new Map();
42
+ // tracks when each job was enqueued
43
+ this.enqueuedAt = new Map();
44
+ // keeps track of which jobs are currently being processed
45
+ // in the event of a crash this information is lost, but that's ok
46
+ // the next time the broker starts it will recreate jobsCache and still
47
+ // accept results from the workers
48
+ this.inProgress = new Map();
49
+ // keep track of which proving job has been retried
50
+ this.retries = new Map();
51
+ // a map of promises that will be resolved when a job is settled
52
+ this.promises = new Map();
53
+ this.msTimeSource = () => Date.now();
54
+ /**
55
+ * The broker keeps track of the highest epoch its seen.
56
+ * This information is used for garbage collection: once it reaches the next epoch, it can start pruning the database of old state.
57
+ * This clean up pass is only done against _settled_ jobs. This pass will not cancel jobs that are in-progress or in-queue.
58
+ * It is a client responsibility to cancel jobs if they are no longer necessary.
59
+ * Example:
60
+ * proving epoch 11 - the broker will wipe all setlled jobs for epochs 9 and lower
61
+ * finished proving epoch 11 and got first job for epoch 12 -> the broker will wipe all setlled jobs for epochs 10 and lower
62
+ * reorged back to end of epoch 10 -> epoch 11 is skipped and epoch 12 starts -> the broker will wipe all setlled jobs for epochs 10 and lower
63
+ */
64
+ this.epochHeight = 0;
65
+ this.maxEpochsToKeepResultsFor = 1;
66
+ this.measureQueueDepth = (type) => {
67
+ return this.queues[type].length();
68
+ };
69
+ this.countActiveJobs = (type) => {
70
+ let count = 0;
71
+ for (const { id } of this.inProgress.values()) {
72
+ const job = this.jobsCache.get(id);
73
+ if (job?.type === type) {
74
+ count++;
75
+ }
76
+ }
77
+ return count;
78
+ };
79
+ this.tracer = client.getTracer('ProvingBroker');
80
+ this.instrumentation = new ProvingBrokerInstrumentation(client);
81
+ this.cleanupPromise = new RunningPromise(this.cleanupPass.bind(this), this.logger, timeoutIntervalMs);
82
+ this.jobTimeoutMs = jobTimeoutMs;
83
+ this.maxRetries = maxRetries;
84
+ this.maxEpochsToKeepResultsFor = maxEpochsToKeepResultsFor;
85
+ this.maxParallelCleanUps = maxParallelCleanUps;
86
+ }
87
+ start() {
88
+ for (const [item, result] of this.database.allProvingJobs()) {
89
+ this.logger.info(`Restoring proving job id=${item.id} settled=${!!result}`, {
90
+ provingJobId: item.id,
91
+ status: result ? result.status : 'pending',
92
+ });
93
+ this.jobsCache.set(item.id, item);
94
+ this.promises.set(item.id, promiseWithResolvers());
95
+ if (result) {
96
+ this.promises.get(item.id).resolve(result);
97
+ this.resultsCache.set(item.id, result);
98
+ }
99
+ else {
100
+ this.enqueueJobInternal(item);
101
+ }
56
102
  }
103
+ this.cleanupPromise.start();
104
+ this.instrumentation.monitorQueueDepth(this.measureQueueDepth);
105
+ this.instrumentation.monitorActiveJobs(this.countActiveJobs);
106
+ return Promise.resolve();
57
107
  }
58
- return count;
59
- };
60
- this.timeoutCheck = () => {
61
- const inProgressEntries = Array.from(this.inProgress.entries());
62
- for (const [id, metadata] of inProgressEntries) {
108
+ async stop() {
109
+ await this.cleanupPromise.stop();
110
+ }
111
+ async enqueueProvingJob(job) {
112
+ if (this.jobsCache.has(job.id)) {
113
+ const existing = this.jobsCache.get(job.id);
114
+ assert.deepStrictEqual(job, existing, 'Duplicate proving job ID');
115
+ this.logger.debug(`Duplicate proving job id=${job.id} epochNumber=${job.epochNumber}. Ignoring`, {
116
+ provingJobId: job.id,
117
+ });
118
+ return;
119
+ }
120
+ if (this.isJobStale(job)) {
121
+ this.logger.warn(`Tried enqueueing stale proving job id=${job.id} epochNumber=${job.epochNumber}`, {
122
+ provingJobId: job.id,
123
+ });
124
+ throw new Error(`Epoch too old: job epoch ${job.epochNumber}, current epoch: ${this.epochHeight}`);
125
+ }
126
+ this.logger.info(`New proving job id=${job.id} epochNumber=${job.epochNumber}`, { provingJobId: job.id });
127
+ try {
128
+ // do this first so it acts as a "lock". If this job is enqueued again while we're saving it the if at the top will catch it.
129
+ this.jobsCache.set(job.id, job);
130
+ await this.database.addProvingJob(job);
131
+ this.enqueueJobInternal(job);
132
+ }
133
+ catch (err) {
134
+ this.logger.error(`Failed to save proving job id=${job.id}: ${err}`, err, { provingJobId: job.id });
135
+ this.jobsCache.delete(job.id);
136
+ throw err;
137
+ }
138
+ }
139
+ waitForJobToSettle(id) {
140
+ const promiseWithResolvers = this.promises.get(id);
141
+ if (!promiseWithResolvers) {
142
+ this.logger.warn(`Job id=${id} not found`, { provingJobId: id });
143
+ return Promise.resolve({ status: 'rejected', reason: `Job ${id} not found` });
144
+ }
145
+ return promiseWithResolvers.promise;
146
+ }
147
+ async cancelProvingJob(id) {
148
+ if (!this.jobsCache.has(id)) {
149
+ this.logger.warn(`Can't cancel a job that doesn't exist id=${id}`, { provingJobId: id });
150
+ return;
151
+ }
152
+ // notify listeners of the cancellation
153
+ if (!this.resultsCache.has(id)) {
154
+ this.logger.info(`Cancelling job id=${id}`, { provingJobId: id });
155
+ await this.reportProvingJobError(id, 'Aborted', false);
156
+ }
157
+ }
158
+ async cleanUpProvingJobState(id) {
159
+ if (!this.jobsCache.has(id)) {
160
+ this.logger.warn(`Can't clean up a job that doesn't exist id=${id}`, { provingJobId: id });
161
+ return;
162
+ }
163
+ if (!this.resultsCache.has(id)) {
164
+ this.logger.warn(`Can't cleanup busy proving job: id=${id}`, { provingJobId: id });
165
+ return;
166
+ }
167
+ this.logger.debug(`Cleaning up state for job id=${id}`, { provingJobId: id });
168
+ await this.database.deleteProvingJobAndResult(id);
169
+ this.jobsCache.delete(id);
170
+ this.promises.delete(id);
171
+ this.resultsCache.delete(id);
172
+ this.inProgress.delete(id);
173
+ this.retries.delete(id);
174
+ }
175
+ getProvingJobStatus(id) {
176
+ const result = this.resultsCache.get(id);
177
+ if (result) {
178
+ return Promise.resolve(result);
179
+ }
180
+ else {
181
+ // no result yet, check if we know the item
182
+ const item = this.jobsCache.get(id);
183
+ if (!item) {
184
+ this.logger.warn(`Proving job id=${id} not found`, { provingJobId: id });
185
+ return Promise.resolve({ status: 'not-found' });
186
+ }
187
+ return Promise.resolve({ status: this.inProgress.has(id) ? 'in-progress' : 'in-queue' });
188
+ }
189
+ }
190
+ // eslint-disable-next-line require-await
191
+ async getProvingJob(filter = { allowList: [] }) {
192
+ const allowedProofs = Array.isArray(filter.allowList) && filter.allowList.length > 0
193
+ ? [...filter.allowList]
194
+ : Object.values(ProvingRequestType).filter((x) => typeof x === 'number');
195
+ allowedProofs.sort(proofTypeComparator);
196
+ for (const proofType of allowedProofs) {
197
+ const queue = this.queues[proofType];
198
+ let enqueuedJob;
199
+ // exhaust the queue and make sure we're not sending a job that's already in progress
200
+ // or has already been completed
201
+ // this can happen if the broker crashes and restarts
202
+ // it's possible agents will report progress or results for jobs that are in the queue (after the restart)
203
+ while ((enqueuedJob = queue.getImmediate())) {
204
+ const job = this.jobsCache.get(enqueuedJob.id);
205
+ if (job && !this.inProgress.has(enqueuedJob.id) && !this.resultsCache.has(enqueuedJob.id)) {
206
+ const time = this.msTimeSource();
207
+ this.inProgress.set(job.id, {
208
+ id: job.id,
209
+ startedAt: time,
210
+ lastUpdatedAt: time,
211
+ });
212
+ const enqueuedAt = this.enqueuedAt.get(job.id);
213
+ if (enqueuedAt) {
214
+ this.instrumentation.recordJobWait(job.type, enqueuedAt);
215
+ }
216
+ return { job, time };
217
+ }
218
+ }
219
+ }
220
+ return undefined;
221
+ }
222
+ async reportProvingJobError(id, err, retry = false) {
223
+ const info = this.inProgress.get(id);
63
224
  const item = this.jobsCache.get(id);
225
+ const retries = this.retries.get(id) ?? 0;
64
226
  if (!item) {
65
- this.logger.warn(`Proving job id=${id} not found. Removing it from the queue.`);
66
- this.inProgress.delete(id);
67
- continue;
227
+ this.logger.warn(`Can't set error on unknown proving job id=${id} err=${err}`, { provingJoId: id });
228
+ return;
229
+ }
230
+ if (!info) {
231
+ this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`, {
232
+ provingJobId: id,
233
+ });
68
234
  }
69
- const msSinceLastUpdate = (this.timeSource() - metadata.lastUpdatedAt) * 1000;
70
- if (msSinceLastUpdate >= this.jobTimeoutMs) {
71
- this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`);
235
+ else {
72
236
  this.inProgress.delete(id);
237
+ }
238
+ if (this.resultsCache.has(id)) {
239
+ this.logger.warn(`Proving job id=${id} is already settled, ignoring err=${err}`, {
240
+ provingJobId: id,
241
+ });
242
+ return;
243
+ }
244
+ if (retry && retries + 1 < this.maxRetries && !this.isJobStale(item)) {
245
+ this.logger.info(`Retrying proving job id=${id} type=${ProvingRequestType[item.type]} retry=${retries + 1} err=${err}`, {
246
+ provingJobId: id,
247
+ });
248
+ this.retries.set(id, retries + 1);
73
249
  this.enqueueJobInternal(item);
74
- this.instrumentation.incTimedOutJobs(item.type);
250
+ this.instrumentation.incRetriedJobs(item.type);
251
+ return;
252
+ }
253
+ this.logger.info(`Marking proving job as failed id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1} err=${err}`, {
254
+ provingJobId: id,
255
+ });
256
+ // save the result to the cache and notify clients of the job status
257
+ // this should work even if our database breaks because the result is cached in memory
258
+ const result = { status: 'rejected', reason: String(err) };
259
+ this.resultsCache.set(id, result);
260
+ this.promises.get(id).resolve(result);
261
+ this.instrumentation.incRejectedJobs(item.type);
262
+ if (info) {
263
+ const duration = this.msTimeSource() - info.startedAt;
264
+ this.instrumentation.recordJobDuration(item.type, duration);
265
+ }
266
+ try {
267
+ await this.database.setProvingJobError(id, err);
268
+ }
269
+ catch (saveErr) {
270
+ this.logger.error(`Failed to save proving job error status id=${id} jobErr=${err}`, saveErr, {
271
+ provingJobId: id,
272
+ });
273
+ throw saveErr;
75
274
  }
76
275
  }
77
- };
78
- this.instrumentation = new ProvingBrokerInstrumentation(client);
79
- this.timeoutPromise = new RunningPromise(this.timeoutCheck, timeoutIntervalMs);
80
- this.jobTimeoutMs = jobTimeoutMs;
81
- this.maxRetries = maxRetries;
82
- }
83
- start() {
84
- for (const [item, result] of this.database.allProvingJobs()) {
85
- this.logger.info(`Restoring proving job id=${item.id} settled=${!!result}`);
86
- this.jobsCache.set(item.id, item);
87
- this.promises.set(item.id, promiseWithResolvers());
88
- if (result) {
89
- this.promises.get(item.id).resolve(result);
90
- this.resultsCache.set(item.id, result);
276
+ reportProvingJobProgress(id, startedAt, filter) {
277
+ const job = this.jobsCache.get(id);
278
+ if (!job) {
279
+ this.logger.warn(`Proving job id=${id} does not exist`, { provingJobId: id });
280
+ return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
281
+ }
282
+ if (this.resultsCache.has(id)) {
283
+ this.logger.warn(`Proving job id=${id} has already been completed`, { provingJobId: id });
284
+ return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
285
+ }
286
+ const metadata = this.inProgress.get(id);
287
+ const now = this.msTimeSource();
288
+ if (!metadata) {
289
+ this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} not found in the in-progress cache, adding it`, { provingJobId: id });
290
+ // the queue will still contain the item at this point!
291
+ // we need to be careful when popping off the queue to make sure we're not sending
292
+ // a job that's already in progress
293
+ this.inProgress.set(id, {
294
+ id,
295
+ startedAt,
296
+ lastUpdatedAt: this.msTimeSource(),
297
+ });
298
+ return Promise.resolve(undefined);
299
+ }
300
+ else if (startedAt <= metadata.startedAt) {
301
+ if (startedAt < metadata.startedAt) {
302
+ this.logger.info(`Proving job id=${id} type=${ProvingRequestType[job.type]} startedAt=${startedAt} older agent has taken job`, { provingJobId: id });
303
+ }
304
+ else {
305
+ this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} heartbeat`, { provingJobId: id });
306
+ }
307
+ metadata.startedAt = startedAt;
308
+ metadata.lastUpdatedAt = now;
309
+ return Promise.resolve(undefined);
310
+ }
311
+ else if (filter) {
312
+ this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} already being worked on by another agent. Sending new one`, { provingJobId: id });
313
+ return this.getProvingJob(filter);
314
+ }
315
+ else {
316
+ return Promise.resolve(undefined);
317
+ }
91
318
  }
92
- else {
93
- this.logger.debug(`Re-enqueuing proving job id=${item.id}`);
94
- this.enqueueJobInternal(item);
319
+ async reportProvingJobSuccess(id, value) {
320
+ const info = this.inProgress.get(id);
321
+ const item = this.jobsCache.get(id);
322
+ const retries = this.retries.get(id) ?? 0;
323
+ if (!item) {
324
+ this.logger.warn(`Proving job id=${id} not found`, { provingJobId: id });
325
+ return;
326
+ }
327
+ if (!info) {
328
+ this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`, {
329
+ provingJobId: id,
330
+ });
331
+ }
332
+ else {
333
+ this.inProgress.delete(id);
334
+ }
335
+ if (this.resultsCache.has(id)) {
336
+ this.logger.warn(`Proving job id=${id} already settled, ignoring result`, { provingJobId: id });
337
+ return;
338
+ }
339
+ this.logger.info(`Proving job complete id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1}`, { provingJobId: id });
340
+ // save result to our local cache and notify clients
341
+ // if save to database fails, that's ok because we have the result in memory
342
+ // if the broker crashes and needs the result again, we're covered because we can just recompute it
343
+ const result = { status: 'fulfilled', value };
344
+ this.resultsCache.set(id, result);
345
+ this.promises.get(id).resolve(result);
346
+ this.instrumentation.incResolvedJobs(item.type);
347
+ if (info) {
348
+ const duration = this.msTimeSource() - info.startedAt;
349
+ this.instrumentation.recordJobDuration(item.type, duration);
350
+ }
351
+ try {
352
+ await this.database.setProvingJobResult(id, value);
353
+ }
354
+ catch (saveErr) {
355
+ this.logger.error(`Failed to save proving job result id=${id}`, saveErr, {
356
+ provingJobId: id,
357
+ });
358
+ throw saveErr;
359
+ }
95
360
  }
96
- }
97
- this.timeoutPromise.start();
98
- this.instrumentation.monitorQueueDepth(this.measureQueueDepth);
99
- this.instrumentation.monitorActiveJobs(this.countActiveJobs);
100
- return Promise.resolve();
101
- }
102
- stop() {
103
- return this.timeoutPromise.stop();
104
- }
105
- async enqueueProvingJob(job) {
106
- if (this.jobsCache.has(job.id)) {
107
- const existing = this.jobsCache.get(job.id);
108
- assert.deepStrictEqual(job, existing, 'Duplicate proving job ID');
109
- return;
110
- }
111
- await this.database.addProvingJob(job);
112
- this.jobsCache.set(job.id, job);
113
- this.enqueueJobInternal(job);
114
- }
115
- waitForJobToSettle(id) {
116
- const promiseWithResolvers = this.promises.get(id);
117
- if (!promiseWithResolvers) {
118
- return Promise.resolve({ status: 'rejected', reason: `Job ${id} not found` });
119
- }
120
- return promiseWithResolvers.promise;
121
- }
122
- async removeAndCancelProvingJob(id) {
123
- this.logger.info(`Cancelling job id=${id}`);
124
- await this.database.deleteProvingJobAndResult(id);
125
- // notify listeners of the cancellation
126
- if (!this.resultsCache.has(id)) {
127
- this.promises.get(id)?.resolve({ status: 'rejected', reason: 'Aborted' });
128
- }
129
- this.jobsCache.delete(id);
130
- this.promises.delete(id);
131
- this.resultsCache.delete(id);
132
- this.inProgress.delete(id);
133
- this.retries.delete(id);
134
- }
135
- getProvingJobStatus(id) {
136
- const result = this.resultsCache.get(id);
137
- if (result) {
138
- return Promise.resolve(result);
139
- }
140
- else {
141
- // no result yet, check if we know the item
142
- const item = this.jobsCache.get(id);
143
- if (!item) {
144
- this.logger.warn(`Proving job id=${id} not found`);
145
- return Promise.resolve({ status: 'not-found' });
361
+ async cleanupPass() {
362
+ await this.cleanupStaleJobs();
363
+ await this.reEnqueueExpiredJobs();
146
364
  }
147
- return Promise.resolve({ status: this.inProgress.has(id) ? 'in-progress' : 'in-queue' });
148
- }
149
- }
150
- // eslint-disable-next-line require-await
151
- async getProvingJob(filter = { allowList: [] }) {
152
- const allowedProofs = Array.isArray(filter.allowList) && filter.allowList.length > 0
153
- ? [...filter.allowList]
154
- : Object.values(ProvingRequestType).filter((x) => typeof x === 'number');
155
- allowedProofs.sort(proofTypeComparator);
156
- for (const proofType of allowedProofs) {
157
- const queue = this.queues[proofType];
158
- let job;
159
- // exhaust the queue and make sure we're not sending a job that's already in progress
160
- // or has already been completed
161
- // this can happen if the broker crashes and restarts
162
- // it's possible agents will report progress or results for jobs that are in the queue (after the restart)
163
- while ((job = queue.getImmediate())) {
164
- if (!this.inProgress.has(job.id) && !this.resultsCache.has(job.id)) {
165
- const time = this.timeSource();
166
- this.inProgress.set(job.id, {
167
- id: job.id,
168
- startedAt: time,
169
- lastUpdatedAt: time,
365
+ async cleanupStaleJobs() {
366
+ const jobIds = Array.from(this.jobsCache.keys());
367
+ const jobsToClean = [];
368
+ for (const id of jobIds) {
369
+ const job = this.jobsCache.get(id);
370
+ const isComplete = this.resultsCache.has(id);
371
+ if (isComplete && this.isJobStale(job)) {
372
+ jobsToClean.push(id);
373
+ }
374
+ }
375
+ if (jobsToClean.length > 0) {
376
+ this.logger.info(`Cleaning up jobs=${jobsToClean.length}`);
377
+ await asyncPool(this.maxParallelCleanUps, jobsToClean, async (jobId) => {
378
+ await this.cleanUpProvingJobState(jobId);
170
379
  });
171
- const enqueuedAt = this.enqueuedAt.get(job.id);
172
- if (enqueuedAt) {
173
- this.instrumentation.recordJobWait(job.type, enqueuedAt);
380
+ }
381
+ }
382
+ async reEnqueueExpiredJobs() {
383
+ const inProgressEntries = Array.from(this.inProgress.entries());
384
+ for (const [id, metadata] of inProgressEntries) {
385
+ const item = this.jobsCache.get(id);
386
+ if (!item) {
387
+ this.logger.warn(`Proving job id=${id} not found. Removing it from the queue.`, { provingJobId: id });
388
+ this.inProgress.delete(id);
389
+ continue;
390
+ }
391
+ const now = this.msTimeSource();
392
+ const msSinceLastUpdate = now - metadata.lastUpdatedAt;
393
+ if (msSinceLastUpdate >= this.jobTimeoutMs) {
394
+ if (this.isJobStale(item)) {
395
+ // the job has timed out and it's also old, just cancel and move on
396
+ await this.cancelProvingJob(item.id);
397
+ }
398
+ else {
399
+ this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`, { provingJobId: id });
400
+ this.inProgress.delete(id);
401
+ this.enqueueJobInternal(item);
402
+ this.instrumentation.incTimedOutJobs(item.type);
403
+ }
174
404
  }
175
- return { job, time };
176
405
  }
177
406
  }
178
- }
179
- return undefined;
180
- }
181
- async reportProvingJobError(id, err, retry = false) {
182
- const info = this.inProgress.get(id);
183
- const item = this.jobsCache.get(id);
184
- const retries = this.retries.get(id) ?? 0;
185
- if (!item) {
186
- this.logger.warn(`Proving job id=${id} not found`);
187
- return;
188
- }
189
- if (!info) {
190
- this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
191
- }
192
- else {
193
- this.inProgress.delete(id);
194
- }
195
- if (retry && retries + 1 < this.maxRetries) {
196
- this.logger.info(`Retrying proving job id=${id} type=${ProvingRequestType[item.type]} retry=${retries + 1}`);
197
- this.retries.set(id, retries + 1);
198
- this.enqueueJobInternal(item);
199
- this.instrumentation.incRetriedJobs(item.type);
200
- return;
201
- }
202
- this.logger.debug(`Marking proving job id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1} as failed`);
203
- await this.database.setProvingJobError(id, err);
204
- const result = { status: 'rejected', reason: String(err) };
205
- this.resultsCache.set(id, result);
206
- this.promises.get(id).resolve(result);
207
- this.instrumentation.incRejectedJobs(item.type);
208
- if (info) {
209
- const duration = this.timeSource() - info.startedAt;
210
- this.instrumentation.recordJobDuration(item.type, duration * 1000);
211
- }
212
- }
213
- reportProvingJobProgress(id, startedAt, filter) {
214
- const job = this.jobsCache.get(id);
215
- if (!job) {
216
- this.logger.warn(`Proving job id=${id} does not exist`);
217
- return filter ? this.getProvingJob(filter) : Promise.resolve(undefined);
218
- }
219
- const metadata = this.inProgress.get(id);
220
- const now = this.timeSource();
221
- if (!metadata) {
222
- this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} not found in the in-progress cache, adding it`);
223
- // the queue will still contain the item at this point!
224
- // we need to be careful when popping off the queue to make sure we're not sending
225
- // a job that's already in progress
226
- this.inProgress.set(id, {
227
- id,
228
- startedAt,
229
- lastUpdatedAt: this.timeSource(),
230
- });
231
- return Promise.resolve(undefined);
232
- }
233
- else if (startedAt <= metadata.startedAt) {
234
- if (startedAt < metadata.startedAt) {
235
- this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} startedAt=${startedAt} older agent has taken job`);
407
+ enqueueJobInternal(job) {
408
+ if (!this.promises.has(job.id)) {
409
+ this.promises.set(job.id, promiseWithResolvers());
410
+ }
411
+ this.queues[job.type].put({
412
+ epochNumber: job.epochNumber,
413
+ id: job.id,
414
+ });
415
+ this.enqueuedAt.set(job.id, new Timer());
416
+ this.epochHeight = Math.max(this.epochHeight, job.epochNumber);
236
417
  }
237
- else {
238
- this.logger.debug(`Proving job id=${id} type=${ProvingRequestType[job.type]} heartbeat`);
418
+ isJobStale(job) {
419
+ return job.epochNumber < this.epochHeight - this.maxEpochsToKeepResultsFor;
239
420
  }
240
- metadata.startedAt = startedAt;
241
- metadata.lastUpdatedAt = now;
242
- return Promise.resolve(undefined);
243
- }
244
- else if (filter) {
245
- this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[job.type]} already being worked on by another agent. Sending new one`);
246
- return this.getProvingJob(filter);
247
- }
248
- else {
249
- return Promise.resolve(undefined);
250
- }
251
- }
252
- async reportProvingJobSuccess(id, value) {
253
- const info = this.inProgress.get(id);
254
- const item = this.jobsCache.get(id);
255
- const retries = this.retries.get(id) ?? 0;
256
- if (!item) {
257
- this.logger.warn(`Proving job id=${id} not found`);
258
- return;
259
- }
260
- if (!info) {
261
- this.logger.warn(`Proving job id=${id} type=${ProvingRequestType[item.type]} not in the in-progress set`);
262
- }
263
- else {
264
- this.inProgress.delete(id);
265
- }
266
- this.logger.debug(`Proving job complete id=${id} type=${ProvingRequestType[item.type]} totalAttempts=${retries + 1}`);
267
- await this.database.setProvingJobResult(id, value);
268
- const result = { status: 'fulfilled', value };
269
- this.resultsCache.set(id, result);
270
- this.promises.get(id).resolve(result);
271
- this.instrumentation.incResolvedJobs(item.type);
272
- }
273
- enqueueJobInternal(job) {
274
- if (!this.promises.has(job.id)) {
275
- this.promises.set(job.id, promiseWithResolvers());
276
- }
277
- this.queues[job.type].put(job);
278
- this.enqueuedAt.set(job.id, new Timer());
279
- this.logger.debug(`Enqueued new proving job id=${job.id}`);
280
- }
281
- }
421
+ },
422
+ (() => {
423
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
424
+ _cleanupPass_decorators = [trackSpan('ProvingBroker.cleanupPass')];
425
+ __esDecorate(_a, null, _cleanupPass_decorators, { kind: "method", name: "cleanupPass", static: false, private: false, access: { has: obj => "cleanupPass" in obj, get: obj => obj.cleanupPass }, metadata: _metadata }, null, _instanceExtraInitializers);
426
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
427
+ })(),
428
+ _a;
429
+ })();
430
+ export { ProvingBroker };
282
431
  /**
283
432
  * Compares two proving jobs and selects which one's more important
284
433
  * @param a - A proving job
@@ -286,12 +435,10 @@ export class ProvingBroker {
286
435
  * @returns A number indicating the relative priority of the two proving jobs
287
436
  */
288
437
  function provingJobComparator(a, b) {
289
- const aBlockNumber = a.blockNumber ?? 0;
290
- const bBlockNumber = b.blockNumber ?? 0;
291
- if (aBlockNumber < bBlockNumber) {
438
+ if (a.epochNumber < b.epochNumber) {
292
439
  return -1;
293
440
  }
294
- else if (aBlockNumber > bBlockNumber) {
441
+ else if (a.epochNumber > b.epochNumber) {
295
442
  return 1;
296
443
  }
297
444
  else {
@@ -349,4 +496,4 @@ const PROOF_TYPES_IN_PRIORITY_ORDER = [
349
496
  ProvingRequestType.EMPTY_BLOCK_ROOT_ROLLUP,
350
497
  ProvingRequestType.PRIVATE_KERNEL_EMPTY,
351
498
  ];
352
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmluZ19icm9rZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdmluZ19icm9rZXIvcHJvdmluZ19icm9rZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQVNMLGtCQUFrQixHQUNuQixNQUFNLHNCQUFzQixDQUFDO0FBQzlCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBNkIsY0FBYyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDNUcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBR2hELE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUc1QixPQUFPLEVBQXdCLDRCQUE0QixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFjekc7OztHQUdHO0FBQ0gsTUFBTSxPQUFPLGFBQWE7SUErQ3hCLFlBQ1UsUUFBK0IsRUFDdkMsTUFBdUIsRUFDdkIsRUFBRSxZQUFZLEdBQUcsS0FBTSxFQUFFLGlCQUFpQixHQUFHLEtBQU0sRUFBRSxVQUFVLEdBQUcsQ0FBQyxLQUErQixFQUFFLEVBQzVGLFNBQVMsaUJBQWlCLENBQUMsb0NBQW9DLENBQUM7UUFIaEUsYUFBUSxHQUFSLFFBQVEsQ0FBdUI7UUFHL0IsV0FBTSxHQUFOLE1BQU0sQ0FBMEQ7UUFsRGxFLFdBQU0sR0FBa0I7WUFDOUIsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsRUFBRSxJQUFJLG1CQUFtQixDQUFhLG9CQUFvQixDQUFDO1lBQ3pGLENBQUMsa0JBQWtCLENBQUMsVUFBVSxDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBYSxvQkFBb0IsQ0FBQztZQUMxRixDQUFDLGtCQUFrQixDQUFDLG9CQUFvQixDQUFDLEVBQUUsSUFBSSxtQkFBbUIsQ0FBYSxvQkFBb0IsQ0FBQztZ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
499
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmluZ19icm9rZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdmluZ19icm9rZXIvcHJvdmluZ19icm9rZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sRUFTTCxrQkFBa0IsR0FDbkIsTUFBTSxzQkFBc0IsQ0FBQztBQUM5QixPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDekQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sRUFBNkIsY0FBYyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFDNUcsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUQsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ2hELE9BQU8sRUFBcUQsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFdkcsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRzVCLE9BQU8sRUFBd0IsNEJBQTRCLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQWtCekc7OztHQUdHO0lBQ1UsYUFBYTs7OztzQkFBYixhQUFhO1lBK0R4QixZQUNVLFFBQStCLEVBQ3ZDLE1BQXVCLEVBQ3ZCLEVBQ0UsWUFBWSxHQUFHLEtBQU0sRUFDckIsaUJBQWlCLEdBQUcsS0FBTSxFQUMxQixVQUFVLEdBQUcsQ0FBQyxFQUNkLHlCQUF5QixHQUFHLENBQUMsRUFDN0IsbUJBQW1CLEdBQUcsRUFBRSxNQUNJLEVBQUUsRUFDeEIsU0FBUyxZQUFZLENBQUMsOEJBQThCLENBQUM7Z0JBVHJELGFBQVEsSUFoRVAsbURBQWEsRUFnRWQsUUFBUSxFQUF1QjtnQkFTL0IsV0FBTSxHQUFOLE1BQU0sQ0FBK0M7Z0JBeEV2RCxXQUFNLEdBQWtCO29CQUM5QixDQUFDLGtCQUFrQixDQUFDLFNBQVMsQ0FBQyxFQUFFLElBQUksbUJBQW1CLENB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