common deduped request rejection test
This commit is contained in:
parent
0df23134a1
commit
3c22db0a2c
@ -933,7 +933,7 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
expect(av.trustedPromise).toBe(trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
av.unverify(); // effectively during the verify function call
|
||||
av.unverify(); // during the verify function call
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(null);
|
||||
@ -956,6 +956,75 @@ describe('fetchAndVerifyIfNeeded tests', () => {
|
||||
expect(verifyFunc).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
test('ab: a: primary with null, b: primary dedup, ab: reject trusted fetch and unverify, second trusted with value', async () => {
|
||||
const {
|
||||
nextPrimary, nextTrusted, nextVerify,
|
||||
primaryFunc, trustedFunc, verifyFunc
|
||||
} = getManualsAndMocks();
|
||||
|
||||
const av = new AutoVerifier(primaryFunc, trustedFunc, verifyFunc);
|
||||
|
||||
const a = fetchAndVerifyIfNeededManually(av, nextPrimary, nextTrusted, nextVerify);
|
||||
const b = fetchAndVerifyIfNeededManually(av, nextPrimary, nextTrusted, 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();
|
||||
|
||||
a.primary.resolve(null);
|
||||
await disjoint();
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(a.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
a.trusted.reject(new Error('rejected'));
|
||||
av.unverify()
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(null);
|
||||
expect(av.trustedStatus).toBe('none');
|
||||
|
||||
await disjoint();
|
||||
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(b.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
expect(verifyFunc).toHaveBeenCalledTimes(0);
|
||||
b.trusted.resolve(new BasicWE(2));
|
||||
await disjoint();
|
||||
|
||||
expect(verifyFunc).toHaveBeenCalledWith(null, new BasicWE(2));
|
||||
expect(av.primaryPromise).toBe(null);
|
||||
expect(av.trustedPromise).toBe(b.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verifying');
|
||||
|
||||
expect(a.result).toBeUndefined();
|
||||
expect(b.result).toBeUndefined();
|
||||
a.verify.resolve(true);
|
||||
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(b.trusted.promise);
|
||||
expect(av.trustedStatus).toBe('verified');
|
||||
|
||||
await disjoint();
|
||||
|
||||
expect(primaryFunc).toHaveBeenCalledTimes(1);
|
||||
expect(trustedFunc).toHaveBeenCalledTimes(2);
|
||||
expect(verifyFunc).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
// TODO: Why not have fetcher and a simple dedup wrapper to remove some complexity from this function?
|
||||
// This would likely make it possible to get rid of the "else" block in tryResolveTrustedPromise
|
||||
// Make sure it would work properly for retry functionality
|
||||
// can't because of primary promise early resolution
|
||||
|
||||
// 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
|
||||
|
@ -231,7 +231,22 @@ export class AutoVerifier<T> {
|
||||
|
||||
// note: Promises that have already resolved will return the same value when awaited again :)
|
||||
const origTrustedPromise: Promise<T | null> | null = this.trustedPromise;
|
||||
const trustedResult = await origTrustedPromise;
|
||||
let trustedResult = undefined;
|
||||
try {
|
||||
trustedResult = await origTrustedPromise;
|
||||
} catch (e: unknown) {
|
||||
if (this.trustedPromise == origTrustedPromise) {
|
||||
throw e;
|
||||
} else {
|
||||
console.warn('trusted promise rejected after unverify', e);
|
||||
if (this.trustedPromise === null) {
|
||||
this.trustedStatus = 'fetching';
|
||||
this.trustedPromise = this.trustedFunc();
|
||||
}
|
||||
await tryResolveTrustedPromise();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.trustedPromise !== origTrustedPromise) {
|
||||
// we've been invalidated while we were waiting for the trusted result!
|
||||
@ -281,7 +296,18 @@ export class AutoVerifier<T> {
|
||||
|
||||
// note: Promises that have already resolved will return the same value when awaited again :)
|
||||
const origTrustedPromise: Promise<T | null> | null = this.trustedPromise;
|
||||
const trustedResult = await origTrustedPromise;
|
||||
let trustedResult = undefined;
|
||||
try {
|
||||
trustedResult = await origTrustedPromise;
|
||||
} catch (e: unknown) {
|
||||
if (this.trustedPromise == origTrustedPromise) {
|
||||
throw e;
|
||||
} else {
|
||||
console.warn('trusted promise from another path rejected after unverify', e);
|
||||
await tryResolveTrustedPromise();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.trustedPromise !== origTrustedPromise) {
|
||||
// we've been invalidated while we were waiting for the trusted result!
|
||||
@ -321,9 +347,9 @@ export class AutoVerifier<T> {
|
||||
await tryResolveTrustedPromise();
|
||||
} catch (e: unknown) {
|
||||
if (!resolved) {
|
||||
this.trustedPromise = null; // suppress warnings
|
||||
this.primaryPromise = null; // suppress warnings
|
||||
this.verifyPromise = null; // suppress warnings
|
||||
this.trustedPromise = null; // suppress warnings about uncaught rejections
|
||||
this.primaryPromise = null; // suppress warnings about uncaught rejections
|
||||
this.verifyPromise = null; // suppress warnings about uncaught rejections
|
||||
this.unverify();
|
||||
// eslint-disable-next-line prefer-promise-reject-errors
|
||||
reject(e as Error);
|
||||
|
Loading…
Reference in New Issue
Block a user