Skip to content

Commit a71d949

Browse files
devin-ai-integration[bot]hariom@cal.comhariombalhara
authored
feat: add cron job to cleanup old queued form responses (calcom#22035)
* feat: add cron job to cleanup old queued form responses - Add cleanup cron job for App_RoutingForms_QueuedFormResponse table - Delete records with null actualResponseId older than 1 hour - Schedule to run twice daily (every 12 hours) via vercel.json - Follow existing cron job patterns for authentication and structure Co-Authored-By: hariom@cal.com <hariom@cal.com> * fix: correct date comparison logic to delete older records - Change from lte to gte in createdAt comparison - Now properly deletes records older than 1 hour Co-Authored-By: hariom@cal.com <hariom@cal.com> * refactor: move cleanup logic to routing forms lib and import in API endpoint - Create cleanupExpiredQueuedFormResponses function in routing forms lib - Update API endpoint to import and use the new cleanup function - Follow established patterns for code organization in Cal.com - Maintain same functionality and authentication logic Co-Authored-By: hariom@cal.com <hariom@cal.com> * refactor: move entire cron logic to routing-forms cron folder - Create routing-forms/cron/queuedFormResponseCleanup.ts with complete handler - Move authentication, HTTP handling, and database operations to routing-forms - Update API endpoint to simply import and call the cron handler - Remove old lib cleanup function - Follow user's preferred organizational pattern Co-Authored-By: hariom@cal.com <hariom@cal.com> * fix: correct date comparison logic to delete records older than 1 hour - Change from gte (greater than or equal) to lt (less than) cutoffTime - Now properly deletes records where createdAt < cutoffTime (older than 1 hour) - Previous logic was deleting newer records instead of older ones Co-Authored-By: hariom@cal.com <hariom@cal.com> * fixes * refactor: reorganize queuedFormResponse into domain-driven structure - Move repository and service files to routingForm/queuedFormResponse subdirectory - Clean up unused methods and tests for better maintainability - Fix import paths and type definitions - Ensure all tests pass and maintain backward compatibility * fix: align QueuedFormResponse interface types with Prisma schema - Update actualResponseId type from string to number to match Prisma Int type - Make updatedAt nullable (Date | null) to match Prisma DateTime? type - Fix import path for QueuedFormResponseRepository interface Co-Authored-By: hariom@cal.com <hariombalhara@gmail.com> * refactor: reorganize queuedFormResponse into domain-driven structure - Move repository and service files to routingForm/queuedFormResponse subdirectory - Clean up unused methods and tests for better maintainability - Fix import paths and type definitions - Ensure all tests pass and maintain backward compatibility * test: add comprehensive where clause validation tests and missing test coverage * chore: update cron schedule to weekly for 7-day retention period * revert: restore 12-hour cron schedule for better batch management * Add integration tests * refactor: apply test data builder pattern to queuedFormResponse integration tests --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: hariom@cal.com <hariom@cal.com> Co-authored-by: Hariom <hariombalhara@gmail.com>
1 parent e55cee4 commit a71d949

8 files changed

Lines changed: 819 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { defaultResponderForAppDir } from "app/api/defaultResponderForAppDir";
2+
3+
import { handleQueuedFormResponseCleanup } from "@calcom/app-store/routing-forms/cron/queuedFormResponseCleanup";
4+
5+
export const POST = defaultResponderForAppDir(handleQueuedFormResponseCleanup);

apps/web/vercel.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
"path": "/api/cron/calendar-cache-cleanup",
55
"schedule": "0 5 * * *"
66
},
7+
{
8+
"path": "/api/cron/queuedFormResponseCleanup",
9+
"schedule": "0 */12 * * *"
10+
},
711
{
812
"path": "/api/tasks/cron",
913
"schedule": "* * * * *"
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import type { NextRequest } from "next/server";
2+
import { NextResponse } from "next/server";
3+
4+
import logger from "@calcom/lib/logger";
5+
import { PrismaQueuedFormResponseRepository } from "@calcom/lib/server/repository/routingForm/queuedFormResponse/PrismaQueuedFormResponseRepository";
6+
import { QueuedFormResponseService } from "@calcom/lib/server/service/routingForm/queuedFormResponse/QueuedFormResponseService";
7+
import prisma from "@calcom/prisma";
8+
9+
function validateRequest(request: NextRequest) {
10+
const apiKey = request.headers.get("authorization") || request.nextUrl.searchParams.get("apiKey");
11+
12+
if (![process.env.CRON_API_KEY, `Bearer ${process.env.CRON_SECRET}`].includes(`${apiKey}`)) {
13+
return NextResponse.json({ message: "Not authenticated" }, { status: 401 });
14+
}
15+
16+
return null;
17+
}
18+
19+
export async function handleQueuedFormResponseCleanup(request: NextRequest) {
20+
const authError = validateRequest(request);
21+
if (authError) {
22+
return authError;
23+
}
24+
25+
try {
26+
const queuedFormResponseRepo = new PrismaQueuedFormResponseRepository(prisma);
27+
const queuedFormResponseService = new QueuedFormResponseService({
28+
logger,
29+
queuedFormResponseRepo,
30+
});
31+
32+
const result = await queuedFormResponseService.cleanupExpiredResponses({
33+
batchSize: 1000,
34+
});
35+
36+
return NextResponse.json({
37+
status: "success",
38+
data: result,
39+
});
40+
} catch (error) {
41+
console.error("Error during queued form response cleanup:", error);
42+
return NextResponse.json(
43+
{ status: "error", message: "Failed to cleanup queued form responses" },
44+
{ status: 500 }
45+
);
46+
}
47+
}

0 commit comments

Comments
 (0)