diff --git a/app/features/admin/AdminService.server.ts b/app/features/admin/AdminService.server.ts new file mode 100644 index 000000000..1eff0d956 --- /dev/null +++ b/app/features/admin/AdminService.server.ts @@ -0,0 +1,36 @@ +import { sql } from "~/db/sql"; + +interface AdminService { + cleanUp: () => void; +} + +const removeOldLikesStm = sql.prepare(/*sql*/ ` + delete from + "GroupLike" + where + "GroupLike"."createdAt" < cast(strftime('%s', datetime('now', 'start of day', '-7 days')) as int) +`); + +const removeOldGroupStm = sql.prepare(/*sql*/ ` + delete from + "Group" + where "Group"."id" in ( + select "Group"."id" + from "Group" + left join "GroupMatch" on "Group"."id" = "GroupMatch"."alphaGroupId" or "Group"."id" = "GroupMatch"."bravoGroupId" + where "Group"."status" = 'INACTIVE' + and "GroupMatch"."id" is null + ) +`); + +const cleanUpStm = sql.prepare(/*sql*/ ` + vacuum +`); + +const cleanUp: AdminService["cleanUp"] = () => { + removeOldLikesStm.run(); + removeOldGroupStm.run(); + cleanUpStm.run(); +}; + +export { cleanUp }; diff --git a/app/routes/admin.tsx b/app/routes/admin.tsx index 2114ae723..af94c0e9d 100644 --- a/app/routes/admin.tsx +++ b/app/routes/admin.tsx @@ -31,6 +31,7 @@ import { makeTitle } from "~/utils/strings"; import { assertUnreachable } from "~/utils/types"; import { impersonateUrl, SEED_URL, STOP_IMPERSONATING_URL } from "~/utils/urls"; import { _action, actualNumber } from "~/utils/zod"; +import * as AdminService from "~/features/admin/AdminService.server"; export const meta: V2_MetaFunction = () => { return [{ title: makeTitle("Admin page") }]; @@ -45,6 +46,9 @@ const adminActionSchema = z.union([ z.object({ _action: _action("REFRESH"), }), + z.object({ + _action: _action("CLEAN_UP"), + }), z.object({ _action: _action("FORCE_PATRON"), user: z.preprocess(actualNumber, z.number().positive()), @@ -100,6 +104,12 @@ export const action: ActionFunction = async ({ request }) => { }); break; } + case "CLEAN_UP": { + validate(isAdmin(user), "Admin needed", 401); + + AdminService.cleanUp(); + break; + } case "ARTIST": { validate(isMod(user), "Mod needed", 401); @@ -165,6 +175,7 @@ export default function AdminPage() { {isAdmin(user) ? : null} {isAdmin(user) ? : null} {isAdmin(user) ? : null} + {isAdmin(user) ? : null} {process.env.NODE_ENV !== "production" && } @@ -370,6 +381,19 @@ function RefreshPlusTiers() { ); } +function CleanUp() { + const fetcher = useFetcher(); + + return ( + +

DB Clean up

+ + Clean up + +
+ ); +} + function Seed() { const fetcher = useFetcher();