Skip to content

Commit 89a5e9f

Browse files
committed
Move gc to it’s own admin endpoint
1 parent 404931e commit 89a5e9f

File tree

2 files changed

+56
-15
lines changed

2 files changed

+56
-15
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { type DataFunctionArgs } from "@remix-run/node";
2+
import { PerformanceObserver } from "node:perf_hooks";
3+
import { runInNewContext } from "node:vm";
4+
import v8 from "v8";
5+
import { requireUser } from "~/services/session.server";
6+
7+
async function waitTillGcFinishes() {
8+
let resolver: (value: PerformanceEntry) => void;
9+
let rejector: (reason?: any) => void;
10+
11+
const promise = new Promise<PerformanceEntry>((resolve, reject) => {
12+
resolver = resolve;
13+
rejector = reject;
14+
});
15+
16+
const obs = new PerformanceObserver((list) => {
17+
const entry = list.getEntries()[0];
18+
19+
if (entry.name === "gc") {
20+
resolver(entry);
21+
}
22+
});
23+
24+
obs.observe({ entryTypes: ["gc"] });
25+
26+
v8.setFlagsFromString("--expose-gc");
27+
const gc = global.gc ?? runInNewContext("gc");
28+
29+
gc();
30+
31+
// disable expose-gc
32+
v8.setFlagsFromString("--noexpose-gc");
33+
34+
return promise;
35+
}
36+
37+
export async function loader({ request }: DataFunctionArgs) {
38+
const user = await requireUser(request);
39+
40+
if (!user.admin) {
41+
throw new Response("You must be an admin to perform this action", { status: 403 });
42+
}
43+
44+
const entry = await waitTillGcFinishes();
45+
46+
return new Response(JSON.stringify(entry), {
47+
status: 200,
48+
headers: {
49+
"Content-Type": "application/json",
50+
},
51+
});
52+
}

apps/webapp/app/routes/admin.api.v1.snapshot.ts

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
1-
import path from "path";
2-
import os from "os";
1+
import { type DataFunctionArgs } from "@remix-run/node";
32
import fs from "fs";
4-
import v8 from "v8";
3+
import os from "os";
4+
import path from "path";
55
import { PassThrough } from "stream";
6-
import { json, type DataFunctionArgs } from "@remix-run/node";
7-
import { prisma } from "~/db.server";
8-
import { authenticateApiRequest } from "~/services/apiAuth.server";
6+
import v8 from "v8";
97
import { requireUser } from "~/services/session.server";
10-
import { runInNewContext } from "node:vm";
118

129
// Format date as yyyy-MM-dd HH_mm_ss_SSS
1310
function formatDate(date: Date) {
@@ -33,14 +30,6 @@ export async function loader({ request }: DataFunctionArgs) {
3330
throw new Response("You must be an admin to perform this action", { status: 403 });
3431
}
3532

36-
v8.setFlagsFromString("--expose-gc");
37-
const gc = global.gc ?? runInNewContext("gc");
38-
39-
gc();
40-
41-
// disable expose-gc
42-
v8.setFlagsFromString("--noexpose-gc");
43-
4433
const tempDir = os.tmpdir();
4534
const filepath = path.join(
4635
tempDir,

0 commit comments

Comments
 (0)