Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
File size: 3,446 Bytes
a8a9533 b488195 486ffa7 b488195 1b76365 b488195 d4471e3 a8a9533 b488195 486ffa7 b488195 d4471e3 b488195 1b76365 b488195 1b76365 b488195 486ffa7 b488195 1b76365 b488195 1b76365 b488195 1b76365 b488195 54c5dd9 b488195 54c5dd9 486ffa7 b488195 486ffa7 b488195 54c5dd9 486ffa7 54c5dd9 b488195 d4471e3 b488195 d4471e3 b488195 d4471e3 b488195 486ffa7 b488195 d4471e3 b488195 d4471e3 b488195 486ffa7 b488195 1b76365 b488195 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
import { Database } from "$lib/server/database";
import { migrations } from "./routines";
import { acquireLock, releaseLock, isDBLocked, refreshLock } from "./lock";
import { isHuggingChat } from "$lib/utils/isHuggingChat";
import { logger } from "$lib/server/logger";
const LOCK_KEY = "migrations";
export async function checkAndRunMigrations() {
// make sure all GUIDs are unique
if (new Set(migrations.map((m) => m._id.toString())).size !== migrations.length) {
throw new Error("Duplicate migration GUIDs found.");
}
// check if all migrations have already been run
const migrationResults = await (await Database.getInstance())
.getCollections()
.migrationResults.find()
.toArray();
logger.info("[MIGRATIONS] Begin check...");
// connect to the database
const connectedClient = await (await Database.getInstance()).getClient().connect();
const lockId = await acquireLock(LOCK_KEY);
if (!lockId) {
// another instance already has the lock, so we exit early
logger.info(
"[MIGRATIONS] Another instance already has the lock. Waiting for DB to be unlocked."
);
// Todo: is this necessary? Can we just return?
// block until the lock is released
while (await isDBLocked(LOCK_KEY)) {
await new Promise((resolve) => setTimeout(resolve, 1000));
}
return;
}
// once here, we have the lock
// make sure to refresh it regularly while it's running
const refreshInterval = setInterval(async () => {
await refreshLock(LOCK_KEY, lockId);
}, 1000 * 10);
// iterate over all migrations
for (const migration of migrations) {
// check if the migration has already been applied
const shouldRun =
migration.runEveryTime ||
!migrationResults.find((m) => m._id.toString() === migration._id.toString());
// check if the migration has already been applied
if (!shouldRun) {
logger.info(`[MIGRATIONS] "${migration.name}" already applied. Skipping...`);
} else {
// check the modifiers to see if some cases match
if (
(migration.runForHuggingChat === "only" && !isHuggingChat) ||
(migration.runForHuggingChat === "never" && isHuggingChat)
) {
logger.info(
`[MIGRATIONS] "${migration.name}" should not be applied for this run. Skipping...`
);
continue;
}
// otherwise all is good and we can run the migration
logger.info(
`[MIGRATIONS] "${migration.name}" ${
migration.runEveryTime ? "should run every time" : "not applied yet"
}. Applying...`
);
await (await Database.getInstance()).getCollections().migrationResults.updateOne(
{ _id: migration._id },
{
$set: {
name: migration.name,
status: "ongoing",
},
},
{ upsert: true }
);
const session = connectedClient.startSession();
let result = false;
try {
await session.withTransaction(async () => {
result = await migration.up(await Database.getInstance());
});
} catch (e) {
logger.info(`[MIGRATIONS] "${migration.name}" failed!`);
logger.error(e);
} finally {
await session.endSession();
}
await (await Database.getInstance()).getCollections().migrationResults.updateOne(
{ _id: migration._id },
{
$set: {
name: migration.name,
status: result ? "success" : "failure",
},
},
{ upsert: true }
);
}
}
logger.info("[MIGRATIONS] All migrations applied. Releasing lock");
clearInterval(refreshInterval);
await releaseLock(LOCK_KEY, lockId);
}
|