Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
In case multiple instances of server are trying to run migration at startup, knex lock mechanism can lead to one of the instance migration to fail and therefore fail to deploy. In order to avoid failed migration because of lock, we wait and retry migrations ## Checklist before requesting a review (skip if just adding/editing APIs & templates) - [x] I added tests, otherwise the reason is: - [ ] I added observability, otherwise the reason is: - [ ] I added analytics, otherwise the reason is:
- Loading branch information
Showing
3 changed files
with
66 additions
and
1 deletion.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
interface RetryConfig { | ||
maxAttempts: number; | ||
delayMs: number | ((attempt: number) => number); | ||
} | ||
|
||
export async function retry<T>(fn: () => T, config: RetryConfig): Promise<T> { | ||
const { maxAttempts, delayMs } = config; | ||
for (let attempt = 1; attempt <= maxAttempts; attempt++) { | ||
try { | ||
return fn(); | ||
} catch (error) { | ||
if (attempt < maxAttempts) { | ||
const delay = typeof delayMs === 'number' ? delayMs : delayMs(attempt); | ||
await new Promise((resolve) => setTimeout(resolve, delay)); | ||
} else { | ||
throw error; | ||
} | ||
} | ||
} | ||
throw new Error('unreachable'); | ||
} |
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,40 @@ | ||
import { expect, describe, it } from 'vitest'; | ||
import { retry } from './retry'; | ||
|
||
describe('retry', () => { | ||
it('should retry', async () => { | ||
let count = 0; | ||
const result = await retry( | ||
() => { | ||
count++; | ||
if (count < 3) { | ||
throw new Error('my error'); | ||
} | ||
return count; | ||
}, | ||
{ | ||
maxAttempts: 3, | ||
delayMs: () => 0 | ||
} | ||
); | ||
expect(result).toEqual(3); | ||
}); | ||
|
||
it('should throw error after max attempts', async () => { | ||
let count = 0; | ||
try { | ||
await retry( | ||
() => { | ||
count++; | ||
throw new Error('my error'); | ||
}, | ||
{ | ||
maxAttempts: 3, | ||
delayMs: () => 0 | ||
} | ||
); | ||
} catch (error: any) { | ||
expect(error.message).toEqual('my error'); | ||
} | ||
}); | ||
}); |