-
Notifications
You must be signed in to change notification settings - Fork 265
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
114 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
111 changes: 111 additions & 0 deletions
111
yarn-project/prover-client/src/proving_broker/caching_broker_facade.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { type ProvingJobProducer, ProvingRequestType, makePublicInputsAndRecursiveProof } from '@aztec/circuit-types'; | ||
import { RECURSIVE_PROOF_LENGTH, VerificationKeyData, makeRecursiveProof } from '@aztec/circuits.js'; | ||
import { makeBaseParityInputs, makeParityPublicInputs } from '@aztec/circuits.js/testing'; | ||
import { AbortError } from '@aztec/foundation/error'; | ||
import { promiseWithResolvers } from '@aztec/foundation/promise'; | ||
|
||
import { jest } from '@jest/globals'; | ||
import { type MockProxy, mock } from 'jest-mock-extended'; | ||
|
||
import { CachingBrokerFacade } from './caching_broker_facade.js'; | ||
import { InlineProofStore } from './proof_store.js'; | ||
import { InMemoryProverCache } from './prover_cache/memory.js'; | ||
|
||
describe('CachingBrokerFacade', () => { | ||
let facade: CachingBrokerFacade; | ||
let cache: InMemoryProverCache; | ||
let proofStore: InlineProofStore; | ||
let broker: MockProxy<ProvingJobProducer>; | ||
|
||
beforeAll(() => { | ||
jest.useFakeTimers(); | ||
}); | ||
|
||
beforeEach(() => { | ||
broker = mock<ProvingJobProducer>({ | ||
enqueueProvingJob: jest.fn<any>(), | ||
getProvingJobStatus: jest.fn<any>(), | ||
removeAndCancelProvingJob: jest.fn<any>(), | ||
waitForJobToSettle: jest.fn<any>(), | ||
}); | ||
cache = new InMemoryProverCache(); | ||
proofStore = new InlineProofStore(); | ||
facade = new CachingBrokerFacade(broker, cache, proofStore); | ||
}); | ||
|
||
it('marks job as in progress', async () => { | ||
const controller = new AbortController(); | ||
void facade.getBaseParityProof(makeBaseParityInputs(), controller.signal); | ||
|
||
await jest.advanceTimersToNextTimerAsync(); | ||
|
||
expect(broker.enqueueProvingJob).toHaveBeenCalled(); | ||
const job = broker.enqueueProvingJob.mock.calls[0][0]; | ||
|
||
await expect(cache.getProvingJobStatus(job.id)).resolves.toEqual({ status: 'in-queue' }); | ||
controller.abort(); | ||
}); | ||
|
||
it('removes the cached value if a job fails to enqueue', async () => { | ||
const { promise, reject } = promiseWithResolvers<any>(); | ||
broker.enqueueProvingJob.mockResolvedValue(promise); | ||
|
||
void facade.getBaseParityProof(makeBaseParityInputs()).catch(() => {}); | ||
await jest.advanceTimersToNextTimerAsync(); | ||
|
||
const job = broker.enqueueProvingJob.mock.calls[0][0]; | ||
await expect(cache.getProvingJobStatus(job.id)).resolves.toEqual({ status: 'in-queue' }); | ||
|
||
reject(new Error('Failed to enqueue job')); | ||
|
||
await jest.advanceTimersToNextTimerAsync(); | ||
await expect(cache.getProvingJobStatus(job.id)).resolves.toEqual({ status: 'not-found' }); | ||
}); | ||
|
||
it('awaits existing job if in progress', async () => { | ||
const { promise, reject } = promiseWithResolvers<any>(); | ||
broker.enqueueProvingJob.mockResolvedValue(promise); | ||
|
||
const inputs = makeBaseParityInputs(); | ||
void facade.getBaseParityProof(inputs).catch(() => {}); | ||
await jest.advanceTimersToNextTimerAsync(); | ||
expect(broker.enqueueProvingJob).toHaveBeenCalledTimes(1); | ||
|
||
void facade.getBaseParityProof(inputs).catch(() => {}); | ||
await jest.advanceTimersToNextTimerAsync(); | ||
expect(broker.enqueueProvingJob).toHaveBeenCalledTimes(1); | ||
|
||
reject(new AbortError('Job was cancelled')); | ||
}); | ||
|
||
it('reuses already cached results', async () => { | ||
const { promise, resolve } = promiseWithResolvers<any>(); | ||
broker.enqueueProvingJob.mockResolvedValue(Promise.resolve()); | ||
broker.waitForJobToSettle.mockResolvedValue(promise); | ||
|
||
const inputs = makeBaseParityInputs(); | ||
void facade.getBaseParityProof(inputs); | ||
await jest.advanceTimersToNextTimerAsync(); | ||
|
||
expect(broker.enqueueProvingJob).toHaveBeenCalledTimes(1); | ||
const job = broker.enqueueProvingJob.mock.calls[0][0]; | ||
|
||
const result = makePublicInputsAndRecursiveProof( | ||
makeParityPublicInputs(), | ||
makeRecursiveProof(RECURSIVE_PROOF_LENGTH), | ||
VerificationKeyData.makeFakeHonk(), | ||
); | ||
|
||
const outputUri = await proofStore.saveProofOutput(job.id, ProvingRequestType.BASE_PARITY, result); | ||
resolve({ | ||
status: 'fulfilled', | ||
value: outputUri, | ||
}); | ||
|
||
await jest.advanceTimersToNextTimerAsync(); | ||
await expect(cache.getProvingJobStatus(job.id)).resolves.toEqual({ status: 'fulfilled', value: outputUri }); | ||
|
||
await expect(facade.getBaseParityProof(inputs)).resolves.toEqual(result); | ||
expect(broker.enqueueProvingJob).toHaveBeenCalledTimes(1); // job was only ever enqueued once | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters