Add atomic task deduplication with partial unique index

- Add partial unique index for active resource-scoped tasks
- Implement createTaskRunRecordAtomic for race-free task creation
- Update findOrEnqueueTask to use atomic insert first
- Add tests for concurrent task creation deduplication
This commit is contained in:
2026-03-15 14:40:38 -04:00
parent a7f7be50b4
commit ed4420b8db
5 changed files with 225 additions and 6 deletions

View File

@@ -668,6 +668,12 @@ export const taskRun = sqliteTable('task_run', {
taskWorkflowRunUnique: uniqueIndex('task_workflow_run_uidx').on(table.workflow_run_id)
}));
// Note: Partial unique index for active resource-scoped task deduplication is created via
// migration 0013_task_active_resource_unique.sql. SQLite does not support partial indexes
// in drizzle schema DSL, so the index is managed separately:
// CREATE UNIQUE INDEX task_active_resource_uidx ON task_run (user_id, task_type, resource_key)
// WHERE resource_key IS NOT NULL AND status IN ('queued', 'running');
export const taskStageEvent = sqliteTable('task_stage_event', {
id: integer('id').primaryKey({ autoIncrement: true }),
task_id: text('task_id').notNull().references(() => taskRun.id, { onDelete: 'cascade' }),