multi-request dedups with value
This commit is contained in:
parent
1278ccd343
commit
54195fdf14
@ -194,6 +194,37 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
}
|
||||
}
|
||||
|
||||
function fetchAndVerifyIfNeededManually<T>(
|
||||
av: AutoVerifier<T>,
|
||||
nextPrimary: () => ManualPromise<T | null>,
|
||||
nextTrusted: () => ManualPromise<T | null>,
|
||||
nextEnsureTrustedFuncReady: () => ManualPromise<void>,
|
||||
nextVerify: () => ManualPromise<boolean>,
|
||||
lazyVerify: boolean = false,
|
||||
) {
|
||||
const state: {
|
||||
primary: ManualPromise<T | null>,
|
||||
trusted: ManualPromise<T | null>,
|
||||
ensureTrustedFuncReady: ManualPromise<void>,
|
||||
verify: ManualPromise<boolean>,
|
||||
result: T | null | undefined,
|
||||
rejection: Error | undefined,
|
||||
} = {
|
||||
primary: nextPrimary(),
|
||||
trusted: nextTrusted(),
|
||||
ensureTrustedFuncReady: nextEnsureTrustedFuncReady(),
|
||||
verify: nextVerify(),
|
||||
result: undefined,
|
||||
rejection: undefined,
|
||||
}
|
||||
|
||||
const resultPromise = av.fetchAndVerifyIfNeeded(lazyVerify);
|
||||
resultPromise.then((value) => { state.result = value; });
|
||||
resultPromise.catch((value) => { state.rejection = value; });
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
async function disjoint() {
|
||||
await Util.sleep(0);
|
||||
}
|
||||
@ -709,7 +740,73 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
expect(verifyFunc).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
// Make sure to do try/catch errors/rejections, verification failures, unverifies in the middle
|
||||
// Multiple tryResolveTrustedPromises
|
||||
// Multiple fetchAndVerifyIfNeeded at the same time
|
||||
test('ab, a: primary with value, b: primary dedup, ab: trusted dedup with value', async () => {
|
||||
const {
|
||||
nextPrimary, nextTrusted, nextEnsureTrustedFuncReady, nextVerify,
|
||||
primaryFunc, trustedFunc, ensureTrustedFuncReadyFunc, verifyFunc
|
||||
} = getManualsAndMocks();
|
||||
|
||||
const av = new AutoVerifier(primaryFunc, trustedFunc, ensureTrustedFuncReadyFunc, verifyFunc);
|
||||
|
||||
const a = fetchAndVerifyIfNeededManually(av, nextPrimary, nextTrusted, nextEnsureTrustedFuncReady, nextVerify);
|
||||
|
||||
expect(av.primaryPromise).toBe(a.primary.promise);
|
||||
expect(av.trustedPromise).toBe(a.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('fetching');
|
||||
expect(primaryFunc).toHaveBeenCalled();
|
||||
expect(trustedFunc).toHaveBeenCalled();
|
||||
|
||||
const b = fetchAndVerifyIfNeededManually(av, nextPrimary, nextTrusted, nextEnsureTrustedFuncReady, nextVerify);
|
||||
|
||||
expect(av.primaryPromise).toBe(a.primary.promise); // doesn't change from a
|
||||
expect(av.trustedPromise).toBe(a.trusted.promise); // doesn't change from a
|
||||
expect(av.trustedStatus).toBe('fetching');
|
||||
|
||||
expect(a.result).toBeUndefined();
|
||||
expect(b.result).toBeUndefined();
|
||||
a.primary.resolve(new BasicWE(2));
|
||||
await disjoint();
|
||||
|
||||
expect(a.result).toEqual(new BasicWE(2));
|
||||
expect(b.result).toEqual(new BasicWE(2));
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(a.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
a.ensureTrustedFuncReady.resolve();
|
||||
await disjoint();
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(a.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
expect(verifyFunc).toHaveBeenCalledTimes(0);
|
||||
a.trusted.resolve(new BasicWE(2));
|
||||
await disjoint();
|
||||
|
||||
expect(verifyFunc).toHaveBeenCalledWith(new BasicWE(2), new BasicWE(2));
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(a.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
a.verify.resolve(true);
|
||||
await disjoint();
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(a.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verified');
|
||||
|
||||
await disjoint(); // sanity check
|
||||
|
||||
// Even though there were two fetchAnd... calls, they were deduped such that each func was only called once
|
||||
expect(primaryFunc).toHaveBeenCalledTimes(1);
|
||||
expect(trustedFunc).toHaveBeenCalledTimes(1);
|
||||
expect(ensureTrustedFuncReadyFunc).toHaveBeenCalledTimes(1);
|
||||
expect(verifyFunc).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
// Make sure to do try/catch errors/rejections, verification failures, unverifies in the middle
|
||||
// Multiple tryResolveTrustedPromises - multiple fetchAndVerifyIfNeeded at the same time
|
||||
// Trusted resolves *BEFORE* ensureTrustedFuncReady
|
||||
// Fetching after verified doesn't re-fetch trusted
|
||||
});
|
||||
|
@ -249,6 +249,8 @@ export class AutoVerifier<T> {
|
||||
// no one has started verifying the trusted yet
|
||||
|
||||
this.trustedStatus = 'verifying';
|
||||
// TODO: I want to remove the ensureTrustedFuncReady func in favor
|
||||
// of just including it yourself in the trustedFunc
|
||||
/* istanbul ignore next */
|
||||
if (debug) LOG.debug(fetchId + ': verifying... (awaiting trustedPromise)');
|
||||
await this.ensureTrustedFuncReady();
|
||||
|
Loading…
Reference in New Issue
Block a user