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>,
|
verify: ManualPromise<boolean>,
|
||||||
result: T | null | undefined,
|
result: T | null | undefined,
|
||||||
rejection: Error | undefined,
|
rejection: Error | undefined,
|
||||||
|
resultPromise: Promise<T | null>,
|
||||||
} = {
|
} = {
|
||||||
primary: nextPrimary(),
|
primary: nextPrimary(),
|
||||||
trusted: nextTrusted(),
|
trusted: nextTrusted(),
|
||||||
verify: nextVerify(),
|
verify: nextVerify(),
|
||||||
result: undefined,
|
result: undefined,
|
||||||
rejection: undefined,
|
rejection: undefined,
|
||||||
|
resultPromise: av.fetchAndVerifyIfNeeded(lazyVerify),
|
||||||
}
|
}
|
||||||
|
|
||||||
const resultPromise = av.fetchAndVerifyIfNeeded(lazyVerify);
|
state.resultPromise.then((value: T | null) => { state.result = value; });
|
||||||
resultPromise.then((value) => { state.result = value; });
|
state.resultPromise.catch((value: Error) => { console.log('caught', value); state.rejection = value; });
|
||||||
resultPromise.catch((value) => { state.rejection = value; });
|
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -588,7 +589,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
|||||||
expect(av.trustedStatus).toBe('verifying');
|
expect(av.trustedStatus).toBe('verifying');
|
||||||
|
|
||||||
expect(rejection).toBeUndefined();
|
expect(rejection).toBeUndefined();
|
||||||
trusted.reject(new Error());
|
trusted.reject(new Error('rejection'));
|
||||||
await disjoint();
|
await disjoint();
|
||||||
|
|
||||||
expect(rejection).toBeDefined();
|
expect(rejection).toBeDefined();
|
||||||
@ -635,7 +636,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
|||||||
|
|
||||||
// suppress the warning about trusted rejecting after primary hit
|
// suppress the warning about trusted rejecting after primary hit
|
||||||
const cwSpy = jest.spyOn(console, 'warn').mockImplementationOnce(() => {}).mockReset(); // suppress the warning
|
const cwSpy = jest.spyOn(console, 'warn').mockImplementationOnce(() => {}).mockReset(); // suppress the warning
|
||||||
trusted.reject(new Error());
|
trusted.reject(new Error('rejection'));
|
||||||
await disjoint();
|
await disjoint();
|
||||||
|
|
||||||
expect(cwSpy).toHaveBeenCalledTimes(1);
|
expect(cwSpy).toHaveBeenCalledTimes(1);
|
||||||
@ -763,6 +764,60 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
|||||||
expect(trustedFunc).toHaveBeenCalledTimes(1);
|
expect(trustedFunc).toHaveBeenCalledTimes(1);
|
||||||
expect(verifyFunc).toHaveBeenCalledTimes(1);
|
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 () => {
|
test('a: primary with null, b: primary re-fetch null, a: trusted with value, b: dedup', async () => {
|
||||||
const {
|
const {
|
||||||
|
@ -297,9 +297,13 @@ export class AutoVerifier<T> {
|
|||||||
trustedResult = await origTrustedPromise;
|
trustedResult = await origTrustedPromise;
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
if (this.trustedPromise === origTrustedPromise) {
|
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;
|
throw e;
|
||||||
} else {
|
} else {
|
||||||
console.warn('trusted promise from another path rejected after unverify', e);
|
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();
|
await tryResolveTrustedPromise();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user