From f2d7a6cf4c908e72d0c4dfc879fd49ba35dd9aba Mon Sep 17 00:00:00 2001 From: admin Date: Wed, 13 May 2026 10:02:30 +0300 Subject: [PATCH] fix: track applied migrations to prevent duplicate seeds on restart --- backend/src/db/migrate.ts | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/backend/src/db/migrate.ts b/backend/src/db/migrate.ts index c513509..8650e1c 100644 --- a/backend/src/db/migrate.ts +++ b/backend/src/db/migrate.ts @@ -16,18 +16,40 @@ export async function runMigrations(): Promise { return; } + // Создаём таблицу учёта миграций если её нет + await pool.query(` + CREATE TABLE IF NOT EXISTS _migrations ( + filename TEXT PRIMARY KEY, + applied_at TIMESTAMPTZ DEFAULT now() + ) + `); + const files = fs .readdirSync(MIGRATIONS_DIR) .filter((f) => f.endsWith('.sql')) .sort(); for (const file of files) { + // Проверяем — уже применялась? + const { rowCount } = await pool.query( + 'SELECT 1 FROM _migrations WHERE filename = $1', + [file] + ); + if (rowCount && rowCount > 0) { + console.log(`[migrate] ✓ ${file} (уже применена)`); + continue; + } + const fullPath = path.join(MIGRATIONS_DIR, file); const sql = fs.readFileSync(fullPath, 'utf-8'); console.log(`[migrate] → ${file}`); try { + await pool.query('BEGIN'); await pool.query(sql); + await pool.query('INSERT INTO _migrations (filename) VALUES ($1)', [file]); + await pool.query('COMMIT'); } catch (err) { + await pool.query('ROLLBACK'); console.error(`[migrate] Ошибка в ${file}:`, err); throw err; }