@clickup/pg-mig
Version:
PostgreSQL schema migration tool with microsharding and clustering support
111 lines • 4.01 kB
JavaScript
"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;
}
getSucceededMigrations() {
return this.succeededMigrations;
}
getErrorMigrations() {
return this.errorMigrations;
}
getWarningMigrations() {
return this.warningMigrations;
}
getCurDest() {
return this.curDest;
}
getCurMigration() {
return this.curMigration;
}
getCurLine() {
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, migration.file.vars, (proc) => {
this.curLine = proc.getLastOutLine();
});
if (res.getCode()) {
throw res.getOut().trimEnd();
}
if (migration.file.delay > 0) {
await new Promise((resolve) => setTimeout(resolve, migration.file.delay));
}
return { warning: res.getWarning() };
}
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