UNPKG

smc-hub

Version:

CoCalc: Backend webserver component

70 lines (60 loc) 2.03 kB
/* * This file is part of CoCalc: Copyright © 2020 Sagemath, Inc. * License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details */ // This manages deleting patches. The underlying problem is that there could be a large number of patches, which stalls the DB. // It's better to keep the number of row deletions small, to speed up the operation, only lock less rows for a shorter amount of time, etc. import debug from "debug"; const L = debug("hub:db:delete-patches"); import { PostgreSQL } from "./types"; import { delay } from "awaiting"; // max number of patches to delete at once – 10000 should take a few seconds const MAX_AT_ONCE = parseInt( process.env.SYNCSTRING_DELETE_MAX_AT_ONCE ?? "10000" ); // delay between deleting a chunk of patches const DELAY_S = parseInt(process.env.SYNCSTRING_DELETE_DELAY_CHUNK_S ?? "1"); interface DeletePatchesOpts { db: PostgreSQL; string_id: string; cb?: Function; } async function patchset_limit(opts: { db: PostgreSQL; string_id: string; }): Promise<string | undefined> { const { db, string_id } = opts; const q = await db.async_query({ query: "SELECT time FROM patches", where: { "string_id = $::CHAR(40)": string_id }, limit: 1, offset: MAX_AT_ONCE, }); if (q.rows.length == 0) { return undefined; } else { return q.rows[0].time; } } export async function delete_patches(opts: DeletePatchesOpts): Promise<void> { const { db, string_id, cb } = opts; while (true) { const limit = await patchset_limit({ db, string_id }); L(`deleting patches string_id='${string_id}' until limit='${limit}'`); const where = { "string_id = $::CHAR(40)": string_id }; if (limit != null) { where["time <= $::TIMESTAMP"] = limit; } await db.async_query({ query: "DELETE FROM patches", where, timeout_s: 300, // delete ops could take a bit }); if (limit != null) { await delay(DELAY_S * 1000); } else { break; } } if (typeof cb === "function") cb(); }