Skip to content

Commit acb89e2

Browse files
eabdelmoneimclaude
andcommitted
feat: add DELETE /admin/backfill endpoint to clear backfill table
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 6e74291 commit acb89e2

3 files changed

Lines changed: 73 additions & 8 deletions

File tree

src/server/routes/admin/backfill.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,20 @@ import { StatusCodes } from "http-status-codes";
44
import { TransactionDB } from "../../../shared/db/transactions/db";
55
import { standardResponseSchema } from "../../schemas/shared-api-schemas";
66

7-
const requestBodySchema = Type.Object({
7+
const loadRequestBodySchema = Type.Object({
88
entries: Type.Array(
99
Type.Object({
1010
queueId: Type.String({ description: "Queue ID (UUID)" }),
1111
transactionHash: Type.String({ description: "Transaction hash (0x...)" }),
1212
}),
13-
{ description: "Array of queueId to transactionHash mappings", maxItems: 10000 },
13+
{
14+
description: "Array of queueId to transactionHash mappings",
15+
maxItems: 10000,
16+
},
1417
),
1518
});
1619

17-
const responseBodySchema = Type.Object({
20+
const loadResponseBodySchema = Type.Object({
1821
result: Type.Object({
1922
inserted: Type.Integer({ description: "Number of entries inserted" }),
2023
skipped: Type.Integer({
@@ -23,10 +26,16 @@ const responseBodySchema = Type.Object({
2326
}),
2427
});
2528

29+
const clearResponseBodySchema = Type.Object({
30+
result: Type.Object({
31+
deleted: Type.Integer({ description: "Number of entries deleted" }),
32+
}),
33+
});
34+
2635
export async function loadBackfillRoute(fastify: FastifyInstance) {
2736
fastify.route<{
28-
Body: Static<typeof requestBodySchema>;
29-
Reply: Static<typeof responseBodySchema>;
37+
Body: Static<typeof loadRequestBodySchema>;
38+
Reply: Static<typeof loadResponseBodySchema>;
3039
}>({
3140
method: "POST",
3241
url: "/admin/backfill",
@@ -36,10 +45,10 @@ export async function loadBackfillRoute(fastify: FastifyInstance) {
3645
"Load queueId to transactionHash mappings into the backfill table. Uses SETNX to never overwrite existing entries.",
3746
tags: ["Admin"],
3847
operationId: "loadBackfill",
39-
body: requestBodySchema,
48+
body: loadRequestBodySchema,
4049
response: {
4150
...standardResponseSchema,
42-
[StatusCodes.OK]: responseBodySchema,
51+
[StatusCodes.OK]: loadResponseBodySchema,
4352
},
4453
hide: true,
4554
},
@@ -55,3 +64,31 @@ export async function loadBackfillRoute(fastify: FastifyInstance) {
5564
},
5665
});
5766
}
67+
68+
export async function clearBackfillRoute(fastify: FastifyInstance) {
69+
fastify.route<{
70+
Reply: Static<typeof clearResponseBodySchema>;
71+
}>({
72+
method: "DELETE",
73+
url: "/admin/backfill",
74+
schema: {
75+
summary: "Clear backfill table",
76+
description:
77+
"Delete all entries from the backfill table. This action cannot be undone.",
78+
tags: ["Admin"],
79+
operationId: "clearBackfill",
80+
response: {
81+
...standardResponseSchema,
82+
[StatusCodes.OK]: clearResponseBodySchema,
83+
},
84+
hide: true,
85+
},
86+
handler: async (_request, reply) => {
87+
const deleted = await TransactionDB.clearBackfill();
88+
89+
reply.status(StatusCodes.OK).send({
90+
result: { deleted },
91+
});
92+
},
93+
});
94+
}

src/server/routes/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { FastifyInstance } from "fastify";
2-
import { loadBackfillRoute } from "./admin/backfill";
2+
import { clearBackfillRoute, loadBackfillRoute } from "./admin/backfill";
33
import { getNonceDetailsRoute } from "./admin/nonces";
44
import { getTransactionDetails } from "./admin/transaction";
55
import { createAccessToken } from "./auth/access-tokens/create";
@@ -299,4 +299,5 @@ export async function withRoutes(fastify: FastifyInstance) {
299299
await fastify.register(getTransactionDetails);
300300
await fastify.register(getNonceDetailsRoute);
301301
await fastify.register(loadBackfillRoute);
302+
await fastify.register(clearBackfillRoute);
302303
}

src/shared/db/transactions/db.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,33 @@ export class TransactionDB {
258258

259259
return { inserted, skipped };
260260
};
261+
262+
/**
263+
* Clears all backfill entries.
264+
* @returns number - The number of entries deleted.
265+
*/
266+
static clearBackfill = async (): Promise<number> => {
267+
let totalDeleted = 0;
268+
let cursor = "0";
269+
270+
do {
271+
const [nextCursor, keys] = await redis.scan(
272+
cursor,
273+
"MATCH",
274+
"backfill:*",
275+
"COUNT",
276+
1000,
277+
);
278+
cursor = nextCursor;
279+
280+
if (keys.length > 0) {
281+
const deleted = await redis.unlink(...keys);
282+
totalDeleted += deleted;
283+
}
284+
} while (cursor !== "0");
285+
286+
return totalDeleted;
287+
};
261288
}
262289

263290
const toSeconds = (timestamp: Date) => timestamp.getTime() / 1000;

0 commit comments

Comments
 (0)