generated from amazon-archives/__template_MIT-0
-
Notifications
You must be signed in to change notification settings - Fork 38
Closed
Labels
bugSomething isn't workingSomething isn't working
Milestone
Description
問題
webapp/src/jobs/migration-runner.ts はリトライなしで prisma db push を実行している。Aurora Serverless v2が0 ACU(または最小ACU)からスケーリングする際、データベースが到達可能になるまで最大30秒かかる。この間に prisma db push がエラーコード P1001("Can't reach database server")で失敗し、CDK Triggerの失敗を経てデプロイ全体が中断する。
問題の背景:
- migration runnerはCDK Triggerにより
cdk deploy中に自動実行される - Aurora Serverless v2のコールドスタート遅延は想定される挙動であり、永続的な障害ではない
- 一時的な接続エラーでデプロイ全体の再実行が必要になるべきではない
現在のコード
// webapp/src/jobs/migration-runner.ts
const exitCode = await new Promise((resolve, _) => {
execFile(
path.resolve('./node_modules/prisma/build/index.js'),
['db', 'push', '--skip-generate'].concat(options),
(error, stdout, stderr) => {
console.log(stdout);
if (error != null) {
console.log(`prisma db push exited with error ${error.message}`);
resolve(error.code ?? 1);
} else {
resolve(0);
}
},
);
});
if (exitCode != 0) throw Error(`db push failed with exit code ${exitCode}`);リトライがなく、1回の接続失敗で即座にエラーとなる。
修正案
指数バックオフによるリトライ(最大5回、初期遅延3秒)を追加し、一時的な接続エラーのみリトライする:
async function runPrismaDbPush(options: string[], maxRetries = 5, baseDelay = 3000): Promise<void> {
for (let attempt = 1; attempt <= maxRetries; attempt++) {
const { exitCode, stdout, stderr } = await new Promise<{
exitCode: number;
stdout: string;
stderr: string;
}>((resolve) => {
execFile(
path.resolve('./node_modules/prisma/build/index.js'),
['db', 'push', '--skip-generate'].concat(options),
{},
(error, stdout, stderr) => {
resolve({
exitCode: typeof error?.code === 'number' ? error.code : error ? 1 : 0,
stdout,
stderr,
});
},
);
});
console.log('prisma db push output', { attempt, stdout, stderr });
if (exitCode === 0) return;
const isRetryable =
stderr.includes('P1001') ||
stderr.includes("Can't reach database") ||
stderr.includes('Connection refused');
if (!isRetryable || attempt === maxRetries) {
throw new Error(`db push failed after ${attempt} attempts: ${stderr}`);
}
const delay = baseDelay * Math.pow(2, attempt - 1) + Math.random() * 1000;
console.log('db_push_retry', { attempt, maxRetries, delayMs: Math.round(delay) });
await new Promise((r) => setTimeout(r, delay));
}
}最悪ケースのリトライ所要時間は約100秒(3 + 6 + 12 + 24 + 48 + ジッター)で、Lambdaの5分タイムアウト内に十分収まる。
リトライ対象の判定
| エラー種別 | リトライ | 例 |
|---|---|---|
P1001(データベースに到達不可) |
✅ する | Auroraコールドスタート |
Connection refused |
✅ する | データベース未起動 |
| スキーマ不整合・バリデーションエラー | ❌ しない | 永続的エラー、即座に失敗 |
検証方法
- Aurora Serverless v2が最小ACUからスケーリング中に
cdk deployが成功すること - リトライログ(試行回数・遅延時間)が出力されること
- 永続的エラー(スキーマ不整合等)ではリトライせず即座に失敗すること
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working