UNPKG

@clickup/pg-mig

Version:

PostgreSQL schema migration tool with microsharding and clustering support

111 lines 4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Worker = void 0; const async_rwlock_1 = require("async-rwlock"); const await_semaphore_1 = require("await-semaphore"); const promiseAllMap_1 = require("./helpers/promiseAllMap"); const rwLock = new async_rwlock_1.RWLock(); class Worker { constructor(chainsQueue, semaphores) { this.chainsQueue = chainsQueue; this.semaphores = semaphores; this._succeededMigrations = 0; this._errorMigrations = []; this._warningMigrations = []; this._curDest = null; this._curMigration = null; this._curLine = null; } get succeededMigrations() { return this._succeededMigrations; } get errorMigrations() { return this._errorMigrations; } get warningMigrations() { return this._warningMigrations; } get curDest() { return this._curDest; } get curMigration() { return this._curMigration; } get curLine() { return this._curLine; } async run(onChange) { while (this.chainsQueue.length > 0) { const chain = this.chainsQueue.shift(); for (const migration of chain.migrations) { this._curDest = chain.dest; this._curMigration = migration; this._curLine = null; onChange(); const interval = setInterval(() => onChange(), 200); // for long-running migrations try { const { warning } = await this.processMigration(chain.dest, migration); this._succeededMigrations++; if (warning) { this._warningMigrations.push({ dest: chain.dest, migration, payload: warning, }); } } catch (error) { this._errorMigrations.push({ dest: chain.dest, migration, payload: error, }); break; } finally { clearInterval(interval); onChange(); } } } this._curDest = null; this._curMigration = null; this._curLine = null; onChange(); } async processMigration(dest, migration) { this._curLine = "waiting to satisfy parallelism limits..."; const releases = await (0, promiseAllMap_1.promiseAllMap)([ migration.file.runAlone ? rwLock.writeLock().then(() => rwLock.unlock.bind(rwLock)) : rwLock.readLock().then(() => rwLock.unlock.bind(rwLock)), this.acquireSemaphore(migration.file.parallelismGlobal, migration.version), this.acquireSemaphore(migration.file.parallelismPerHost, dest.host + ":" + migration.version), ], async (p) => p); try { this._curLine = null; const res = await dest.runFile(migration.file.fileName, migration.newVersions, (proc) => { this._curLine = proc.lastOutLine; }); if (res.code) { throw res.out.trimEnd(); } if (migration.file.delay > 0) { await new Promise((resolve) => setTimeout(resolve, migration.file.delay)); } return { warning: res.warning }; } finally { releases.forEach((release) => release()); } } async acquireSemaphore(maxWorkers, key) { let semaphore = this.semaphores[key]; if (!semaphore) { semaphore = this.semaphores[key] = new await_semaphore_1.Semaphore(maxWorkers); } return semaphore.acquire(); } } exports.Worker = Worker; //# sourceMappingURL=Worker.js.map