import { z } from "zod"; import prisma from "~/server/utils/prisma"; // Query parameter validation schema const jobsQuerySchema = z.object({ page: z .string() .transform((val) => parseInt(val) || 1) .optional(), limit: z .string() .transform((val) => parseInt(val) || 10) .optional(), }); export default defineEventHandler(async (event) => { try { // Parse and validate query parameters const queryParams = getQuery(event) || {}; const params = jobsQuerySchema.parse(queryParams); // Build where clause for filtering failed jobs const where = { status: "failed", }; // Get total count for pagination const total = await prisma.notification_queue.count({ where }); // Calculate pagination metadata const totalPages = Math.ceil(total / params.limit); // Fetch failed jobs with relations const jobs = await prisma.notification_queue.findMany({ where, select: { id: true, status: true, scheduled_for: true, attempts: true, max_attempts: true, last_attempt_at: true, error_message: true, created_at: true, notifications: { select: { id: true, title: true, type: true, }, }, }, orderBy: { last_attempt_at: "desc", }, skip: (params.page - 1) * params.limit, take: params.limit, }); // Format jobs for response const formattedJobs = jobs.map((job) => { return { id: job.id, type: job.notifications?.type || "unknown", description: job.notifications?.title || "Failed Notification", status: job.status, attempts: job.attempts, maxAttempts: job.max_attempts, errorType: job.error_message ? getErrorType(job.error_message) : "Unknown Error", errorMessage: job.error_message || "No error message provided", failedAt: job.last_attempt_at ? new Date(job.last_attempt_at).toISOString() : null, nextRetry: "Manual retry required", }; }); return { success: true, data: { jobs: formattedJobs, pagination: { page: params.page, totalPages, totalItems: total, hasMore: params.page < totalPages, }, }, }; } catch (error) { console.error("Error fetching failed jobs:", error); if (error.statusCode) { throw error; } throw createError({ statusCode: 500, statusMessage: "Failed to fetch failed jobs", data: { error: error.message, }, }); } finally { } }); // Helper function to extract error type from error message function getErrorType(errorMessage) { if (!errorMessage) return "Unknown Error"; if (errorMessage.includes("timeout")) return "Timeout Error"; if (errorMessage.includes("connect")) return "Connection Error"; if (errorMessage.includes("authentication")) return "Authentication Error"; if (errorMessage.includes("rate limit")) return "Rate Limit Error"; if (errorMessage.includes("validation")) return "Validation Error"; if (errorMessage.includes("template")) return "Template Error"; return "Processing Error"; }