feat: enhance job resilience with new database schema and recovery mechanisms

- Added new fields to the mirror_jobs table for job resilience, including job_type, batch_id, total_items, completed_items, item_ids, completed_item_ids, in_progress, started_at, completed_at, and last_checkpoint.
- Implemented database migration scripts to update the mirror_jobs table schema.
- Introduced processWithResilience utility for handling item processing with checkpointing and recovery capabilities.
- Updated API routes for mirroring organizations and repositories to utilize the new resilience features.
- Created recovery system to detect and resume interrupted jobs on application startup.
- Added middleware to initialize the recovery system when the server starts.
This commit is contained in:
Arunavo Ray
2025-05-22 14:33:03 +05:30
parent f4bc28e6c2
commit abe3113755
13 changed files with 893 additions and 66 deletions

View File

@@ -189,6 +189,18 @@ export const mirrorJobs = sqliteTable("mirror_jobs", {
timestamp: integer("timestamp", { mode: "timestamp" })
.notNull()
.default(new Date()),
// New fields for job resilience
jobType: text("job_type").notNull().default("mirror"),
batchId: text("batch_id"),
totalItems: integer("total_items"),
completedItems: integer("completed_items").default(0),
itemIds: text("item_ids", { mode: "json" }).$type<string[]>(),
completedItemIds: text("completed_item_ids", { mode: "json" }).$type<string[]>().default([]),
inProgress: integer("in_progress", { mode: "boolean" }).notNull().default(false),
startedAt: integer("started_at", { mode: "timestamp" }),
completedAt: integer("completed_at", { mode: "timestamp" }),
lastCheckpoint: integer("last_checkpoint", { mode: "timestamp" }),
});
export const organizations = sqliteTable("organizations", {

View File

@@ -111,6 +111,18 @@ export const mirrorJobSchema = z.object({
status: repoStatusEnum.default("imported"),
message: z.string(),
timestamp: z.date().default(() => new Date()),
// New fields for job resilience
jobType: z.enum(["mirror", "sync", "retry"]).default("mirror"),
batchId: z.string().uuid().optional(), // Group related jobs together
totalItems: z.number().optional(), // Total number of items to process
completedItems: z.number().optional(), // Number of items completed
itemIds: z.array(z.string()).optional(), // IDs of items to process
completedItemIds: z.array(z.string()).optional(), // IDs of completed items
inProgress: z.boolean().default(false), // Whether the job is currently running
startedAt: z.date().optional(), // When the job started
completedAt: z.date().optional(), // When the job completed
lastCheckpoint: z.date().optional(), // Last time progress was saved
});
export type MirrorJob = z.infer<typeof mirrorJobSchema>;