CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/database/postgres/delete-patches.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
// This manages deleting patches. The underlying problem is that there could be a large number of patches, which stalls the DB.
7
// 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.
8
9
import debug from "debug";
10
const L = debug("hub:db:delete-patches");
11
import { PostgreSQL } from "./types";
12
import { delay } from "awaiting";
13
14
// max number of patches to delete at once – 10000 should take a few seconds
15
const MAX_AT_ONCE = parseInt(
16
process.env.SYNCSTRING_DELETE_MAX_AT_ONCE ?? "10000"
17
);
18
// delay between deleting a chunk of patches
19
const DELAY_S = parseInt(process.env.SYNCSTRING_DELETE_DELAY_CHUNK_S ?? "1");
20
21
interface DeletePatchesOpts {
22
db: PostgreSQL;
23
string_id: string;
24
cb?: Function;
25
}
26
27
async function patchset_limit(opts: {
28
db: PostgreSQL;
29
string_id: string;
30
}): Promise<string | undefined> {
31
const { db, string_id } = opts;
32
const q = await db.async_query({
33
query: "SELECT time FROM patches",
34
where: { "string_id = $::CHAR(40)": string_id },
35
limit: 1,
36
offset: MAX_AT_ONCE,
37
});
38
if (q.rows.length == 0) {
39
return undefined;
40
} else {
41
return q.rows[0].time;
42
}
43
}
44
45
export async function delete_patches(opts: DeletePatchesOpts): Promise<void> {
46
const { db, string_id, cb } = opts;
47
48
while (true) {
49
const limit = await patchset_limit({ db, string_id });
50
51
L(`deleting patches string_id='${string_id}' until limit='${limit}'`);
52
const where = { "string_id = $::CHAR(40)": string_id };
53
if (limit != null) {
54
where["time <= $::TIMESTAMP"] = limit;
55
}
56
await db.async_query({
57
query: "DELETE FROM patches",
58
where,
59
timeout_s: 300, // delete ops could take a bit
60
});
61
if (limit != null) {
62
await delay(DELAY_S * 1000);
63
} else {
64
break;
65
}
66
}
67
68
if (typeof cb === "function") cb();
69
}
70
71