-
Notifications
You must be signed in to change notification settings - Fork 369
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Avoid the possibility to do simultaneous calls to the token endpoint (#…
…664) * First attempt to avoid simultaneous calls * Rework fix to not use a new class and static methods * Add comments to matcher * Fix locking * Replace while with retry * Move singlePromise and promiseRetry to promise-utils * Add tests for promise utils * Add concurrency test * Add locking retry tests * Remove unused variable * Add client ID to the singlePromise key * Rollback changes to index.html * Update test for hitting the cache for subsequent requests that occur before the response * Fix review comments * Fix implicit any errors
- v2.1.3
- v2.1.2
- v2.1.1
- v2.1.0
- v2.0.8
- v2.0.7
- v2.0.6
- v2.0.5
- v2.0.4
- v2.0.3
- v2.0.2
- v2.0.1
- v2.0.0
- v2.0.0-beta.1
- v2.0.0-beta.0
- v1.22.6
- v1.22.5
- v1.22.4
- v1.22.3
- v1.22.2
- v1.22.1
- v1.22.0
- v1.21.1
- v1.21.0
- v1.20.1
- v1.20.0
- v1.19.4
- v1.19.3
- v1.19.2
- v1.19.1
- v1.19.0
- v1.18.0
- v1.17.1
- v1.17.0
- v1.16.1
- v1.16.0
- v1.15.0
- v1.14.0
- v1.13.6
- v1.13.5
1 parent
4b674b2
commit 8b28bd3
Showing
5 changed files
with
281 additions
and
46 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
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
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,76 @@ | ||
/** | ||
* @jest-environment node | ||
*/ | ||
import { retryPromise, singlePromise } from '../src/promise-utils'; | ||
|
||
describe('Promise Utils', () => { | ||
describe('singlePromise', () => { | ||
it('reuses the same promise when the key matches', async () => { | ||
const cb = jest.fn().mockResolvedValue({}); | ||
|
||
await Promise.all([ | ||
singlePromise(cb as any, 'test-key'), | ||
singlePromise(cb as any, 'test-key') | ||
]); | ||
|
||
expect(cb).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('does not reuse the same promise when the key is different', async () => { | ||
const cb = jest.fn().mockResolvedValue({}); | ||
|
||
await Promise.all([ | ||
singlePromise(cb as any, 'test-key'), | ||
singlePromise(cb as any, 'test-key2') | ||
]); | ||
|
||
expect(cb).toHaveBeenCalledTimes(2); | ||
}); | ||
|
||
it('does not reuse the same promise when the key matches but the first promise resolves before calling the second', async () => { | ||
const cb = jest.fn().mockResolvedValue({}); | ||
|
||
await singlePromise(cb as any, 'test-key'); | ||
await singlePromise(cb as any, 'test-key'); | ||
|
||
expect(cb).toHaveBeenCalledTimes(2); | ||
}); | ||
}); | ||
|
||
describe('retryPromise', () => { | ||
it('does not retry promise when it resolves to true', async () => { | ||
const cb = jest.fn().mockResolvedValue(true); | ||
|
||
const value = await retryPromise(cb as any); | ||
|
||
expect(value).toBe(true); | ||
expect(cb).toHaveBeenCalledTimes(1); | ||
}); | ||
|
||
it('retries promise until it resolves to true', async () => { | ||
let i = 1; | ||
const cb = jest.fn().mockImplementation(() => { | ||
if (i === 3) { | ||
return Promise.resolve(true); | ||
} | ||
|
||
i++; | ||
return Promise.resolve(false); | ||
}); | ||
|
||
const value = await retryPromise(cb as any); | ||
|
||
expect(value).toBe(true); | ||
expect(cb).toHaveBeenCalledTimes(3); | ||
}); | ||
|
||
it('resolves to false when all retries resolve to false', async () => { | ||
const cb = jest.fn().mockResolvedValue(false); | ||
|
||
const value = await retryPromise(cb as any, 5); | ||
|
||
expect(value).toBe(false); | ||
expect(cb).toHaveBeenCalledTimes(5); | ||
}); | ||
}); | ||
}); |
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
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,26 @@ | ||
const singlePromiseMap: Record<string, Promise<any>> = {}; | ||
|
||
export const singlePromise = <T>(cb: () => Promise<T>, key: string) => { | ||
let promise = singlePromiseMap[key]; | ||
if (!promise) { | ||
promise = cb().finally(() => { | ||
delete singlePromiseMap[key]; | ||
promise = null; | ||
}); | ||
singlePromiseMap[key] = promise; | ||
} | ||
return promise; | ||
}; | ||
|
||
export const retryPromise = async ( | ||
cb: () => Promise<boolean>, | ||
maxNumberOfRetries = 3 | ||
) => { | ||
for (let i = 0; i < maxNumberOfRetries; i++) { | ||
if (await cb()) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
}; |