Skip to content

Commit 0646bf4

Browse files
committed
database/delete-projects: expand scope
1 parent 4126e2c commit 0646bf4

File tree

3 files changed

+88
-17
lines changed

3 files changed

+88
-17
lines changed

src/packages/database/postgres/bulk-delete.test.ts

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
* License: AGPLv3 s.t. "Commons Clause" – see LICENSE.md for details
44
*/
55

6+
// see packages/database/pool/pool.ts for where this name is also hard coded:
7+
process.env.PGDATABASE = "smc_ephemeral_testing_database";
8+
69
import getPool, { initEphemeralDatabase } from "@cocalc/database/pool";
710
import { uuid } from "@cocalc/util/misc";
811
import { bulk_delete } from "./bulk-delete";

src/packages/database/postgres/bulk-delete.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
// see packages/database/pool/pool.ts for where this name is also hard coded:
2-
process.env.PGDATABASE = "smc_ephemeral_testing_database";
3-
41
import { escapeIdentifier } from "pg";
52

63
import getPool from "@cocalc/database/pool";
74
import { SCHEMA } from "@cocalc/util/schema";
85

6+
type Field =
7+
| "project_id"
8+
| "account_id"
9+
| "target_project_id"
10+
| "source_project_id";
11+
912
interface Opts {
1013
table: string; // e.g. project_log, etc.
11-
field: "project_id" | "account_id"; // for now, we only support a few
14+
field: Field; // for now, we only support a few
1215
id?: string; // default "id", the ID field in the table, which identifies each row uniquely
1316
value: string; // a UUID
1417
limit?: number; // default 1024

src/packages/database/postgres/delete-projects.ts

+78-13
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@ Code related to permanently deleting projects.
99

1010
import getLogger from "@cocalc/backend/logger";
1111
import getPool from "@cocalc/database/pool";
12-
import { callback2 } from "@cocalc/util/async-utils";
13-
import { PostgreSQL } from "./types";
14-
import { minutes_ago } from "@cocalc/util/misc";
1512
import { getServerSettings } from "@cocalc/database/settings";
13+
import { callback2 } from "@cocalc/util/async-utils";
1614
import { KUCALC_ON_PREMISES } from "@cocalc/util/db-schema/site-defaults";
15+
import { minutes_ago } from "@cocalc/util/misc";
16+
import { bulk_delete } from "./bulk-delete";
17+
import { PostgreSQL } from "./types";
1718

1819
const log = getLogger("db:delete-projects");
1920

@@ -84,6 +85,8 @@ FROM projects as p
8485
ON p.project_id = s.project_id
8586
WHERE p.deleted = true
8687
AND p.state ->> 'state' != 'deleted'
88+
ORDER BY
89+
p.project_id, s.string_id
8790
`;
8891

8992
/*
@@ -102,6 +105,8 @@ export async function cleanup_old_projects_data(
102105
) {
103106
const settings = await getServerSettings();
104107
const on_prem = settings.kucalc === KUCALC_ON_PREMISES;
108+
const L0 = log.extend("cleanup_old_projects_data");
109+
const L = L0.debug;
105110

106111
log.debug("cleanup_old_projects_data", { delay_ms, max_run_m, on_prem });
107112
const start_ts = new Date();
@@ -115,31 +120,91 @@ export async function cleanup_old_projects_data(
115120
for (const row of rows) {
116121
const { project_id, string_id } = row;
117122
if (start_ts < minutes_ago(max_run_m)) {
118-
log.debug(
119-
`cleanup_old_projects_data: too much time elapsed, breaking after ${num} syncstrings`,
120-
);
123+
L(`too much time elapsed, breaking after ${num} syncstrings`);
121124
break;
122125
}
123126

124-
log.debug(
125-
`cleanup_old_projects_data: deleting syncstring ${project_id}/${string_id}`,
126-
);
127+
L(`deleting syncstring ${project_id}/${string_id}`);
127128
num += 1;
128129
await callback2(db.delete_syncstring, { string_id });
129130

130131
// wait for the given amount of delay_ms millio seconds
131132
await new Promise((done) => setTimeout(done, delay_ms));
132133

134+
// Q_CLEANUP_SYNCSTRINGS orders by project_id, hence we trigger project specific actions when the id changes
133135
if (pid != project_id) {
134136
pid = project_id;
137+
const L2 = L0.extend(project_id).debug;
138+
135139
if (on_prem) {
136-
log.debug(
137-
`cleanup_old_projects_data: deleting project data in ${project_id}`,
138-
);
140+
L2(`cleanup_old_projects_data for project_id=${project_id}`);
139141
// TODO: this only works on-prem, and requires the project files to be mounted
140142

141-
log.debug(`deleting all shared files in project ${project_id}`);
143+
L2(`deleting all shared files in project ${project_id}`);
142144
// TODO: do it directly like above, and also get rid of all those shares in the database
145+
146+
const delPublicPaths = await bulk_delete({
147+
table: "public_paths",
148+
field: "project_id",
149+
value: project_id,
150+
});
151+
L2(`deleted public_paths ${delPublicPaths.rowsDeleted} entries`);
152+
153+
const delProjectLog = await bulk_delete({
154+
table: "project_log",
155+
field: "project_id",
156+
value: project_id,
157+
});
158+
L2(`deleted project_log ${delProjectLog.rowsDeleted} entries`);
159+
160+
const delFileUse = await bulk_delete({
161+
table: "file_use",
162+
field: "project_id",
163+
value: project_id,
164+
});
165+
L2(`deleted file_use ${delFileUse.rowsDeleted} entries`);
166+
167+
const delAccessLog = await bulk_delete({
168+
table: "file_access_log",
169+
field: "project_id",
170+
value: project_id,
171+
});
172+
L2(`deleted file_access_log ${delAccessLog.rowsDeleted} entries`);
173+
174+
const delJupyterApiLog = await bulk_delete({
175+
table: "jupyter_api_log",
176+
field: "project_id",
177+
value: project_id,
178+
});
179+
L2(`deleted jupyter_api_log ${delJupyterApiLog.rowsDeleted} entries`);
180+
181+
for (const field of [
182+
"target_project_id",
183+
"source_project_id",
184+
] as const) {
185+
const delCopyPaths = await bulk_delete({
186+
table: "copy_paths",
187+
field,
188+
value: project_id,
189+
});
190+
L2(`deleted copy_paths/${field} ${delCopyPaths.rowsDeleted} entries`);
191+
}
192+
193+
const delListings = await bulk_delete({
194+
table: "listings",
195+
field: "project_id",
196+
id: "project_id", // TODO listings has a more complex ID, is this a problem?
197+
value: project_id,
198+
});
199+
L2(`deleted ${delListings.rowsDeleted} listings`);
200+
201+
const delInviteTokens = await bulk_delete({
202+
table: "project_invite_tokens",
203+
field: "project_id",
204+
value: project_id,
205+
id: "token",
206+
});
207+
L2(`deleted ${delInviteTokens.rowsDeleted} entries`);
143208
}
144209

145210
// now, that we're done with that project, mark it as state.state ->> 'deleted'

0 commit comments

Comments
 (0)