ab primary null/dedup, trusted rejects
This commit is contained in:
parent
1d53aa46fa
commit
eaf24a574f
@ -199,17 +199,18 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
verify: ManualPromise<boolean>,
|
||||
result: T | null | undefined,
|
||||
rejection: Error | undefined,
|
||||
resultPromise: Promise<T | null>,
|
||||
} = {
|
||||
primary: nextPrimary(),
|
||||
trusted: nextTrusted(),
|
||||
verify: nextVerify(),
|
||||
result: undefined,
|
||||
rejection: undefined,
|
||||
resultPromise: av.fetchAndVerifyIfNeeded(lazyVerify),
|
||||
}
|
||||
|
||||
const resultPromise = av.fetchAndVerifyIfNeeded(lazyVerify);
|
||||
resultPromise.then((value) => { state.result = value; });
|
||||
resultPromise.catch((value) => { state.rejection = value; });
|
||||
state.resultPromise.then((value: T | null) => { state.result = value; });
|
||||
state.resultPromise.catch((value: Error) => { console.log('caught', value); state.rejection = value; });
|
||||
|
||||
return state;
|
||||
}
|
||||
@ -588,7 +589,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
expect(rejection).toBeUndefined();
|
||||
trusted.reject(new Error());
|
||||
trusted.reject(new Error('rejection'));
|
||||
await disjoint();
|
||||
|
||||
expect(rejection).toBeDefined();
|
||||
@ -635,7 +636,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
|
||||
// suppress the warning about trusted rejecting after primary hit
|
||||
const cwSpy = jest.spyOn(console, 'warn').mockImplementationOnce(() => {}).mockReset(); // suppress the warning
|
||||
trusted.reject(new Error());
|
||||
trusted.reject(new Error('rejection'));
|
||||
await disjoint();
|
||||
|
||||
expect(cwSpy).toHaveBeenCalledTimes(1);
|
||||
@ -764,6 +765,60 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
expect(verifyFunc).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('ab, a: primary with null, b: primary dedup, ab: trusted rejects', async () => {
|
||||
const {
|
||||
nextPrimary, nextTrusted,
|
||||
primaryFunc, trustedFunc, verifyFunc
|
||||
} = getManualsAndMocks();
|
||||
|
||||
const av = new AutoVerifier(primaryFunc, trustedFunc, verifyFunc);
|
||||
|
||||
const primary = nextPrimary();
|
||||
const trusted = nextTrusted();
|
||||
|
||||
const resultPromise1 = av.fetchAndVerifyIfNeeded();
|
||||
let rejection1: Error | undefined = undefined;
|
||||
resultPromise1.catch(value => { rejection1 = value });
|
||||
|
||||
expect(av.primaryPromise).toBe(primary.promise);
|
||||
expect(av.trustedPromise).toBe(trusted.promise);
|
||||
expect(av.trustedStatus).toBe('fetching');
|
||||
expect(primaryFunc).toHaveBeenCalled();
|
||||
expect(trustedFunc).toHaveBeenCalled();
|
||||
|
||||
const resultPromise2 = av.fetchAndVerifyIfNeeded();
|
||||
let rejection2: Error | undefined = undefined;
|
||||
resultPromise2.catch(value => { rejection2 = value });
|
||||
|
||||
expect(av.primaryPromise).toBe(primary.promise); // doesn't change
|
||||
expect(av.trustedPromise).toBe(trusted.promise); // doesn't change
|
||||
expect(av.trustedStatus).toBe('fetching');
|
||||
|
||||
primary.resolve(null);
|
||||
await disjoint();
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
trusted.reject(new Error('rejection'));
|
||||
await disjoint();
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(null);
|
||||
expect(av.trustedStatus).toBe('none');
|
||||
expect(rejection1).toBeDefined();
|
||||
expect(rejection2).toBeDefined();
|
||||
expect(rejection1).toBe(rejection2);
|
||||
|
||||
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(verifyFunc).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
test('a: primary with null, b: primary re-fetch null, a: trusted with value, b: dedup', async () => {
|
||||
const {
|
||||
nextPrimary, nextTrusted, nextVerify,
|
||||
|
@ -297,9 +297,13 @@ export class AutoVerifier<T> {
|
||||
trustedResult = await origTrustedPromise;
|
||||
} catch (e: unknown) {
|
||||
if (this.trustedPromise === origTrustedPromise) {
|
||||
// TODO: decide if can unverify here rather than in the "catch-all"
|
||||
// maybe this will let us get rid of the catch all?
|
||||
throw e;
|
||||
} else {
|
||||
console.warn('trusted promise from another path rejected after unverify', e);
|
||||
// TODO: only retry if there is another trusted promise available...
|
||||
// OR always reject?
|
||||
await tryResolveTrustedPromise();
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user