OUT-3964 | Tasks App - Task(s) Created Using Template Not Saving - #1385
Conversation
…mplate Applying a template fanned out every sub-template's task creation at once via Promise.all. For a template with many sub-templates (e.g. 90), the ~90 concurrent createTask calls exhausted the Prisma connection pool, so some subtasks failed to save and the subsequent task-detail query timed out (P2024 / "Timed out fetching a new connection from the connection pool"). Run the fan-out in bounded batches (subtaskTemplateBatchSize) so concurrency stays small regardless of pool size. Ordering is preserved (timestamp is still derived from index). Applied at both the internal and public API template-apply sites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR limits template subtask creation so large templates do not exhaust the database pool. The main changes are:
Confidence Score: 4/5This is close, but the rollback race should be fixed before merging.
src/app/api/tasks/tasksShared.service.ts Important Files Changed
|
createSubtasksFromTemplate rolled back on failure by soft-deleting `parentId`
— which is the *parent* (main) task, not the failed subtask. So any single
subtask-creation error (e.g. the connection-pool P2024) silently deleted the
task the user had just created and verified, and Realtime made it vanish from
their screen ("task disappeared on its own" in OUT-3964). The rollback was also
wrong (it orphaned already-created sibling subtasks) and unnecessary — createTask
already cleans up a half-created subtask via its own catch.
Now each subtemplate is applied best-effort: the whole per-subtemplate unit
(getAppliedTemplateDescription + create) runs inside one try/catch that skips
and logs on failure instead of throwing. Because the handler no longer rejects,
runInBatches never aborts, so every subtemplate is attempted and one failure no
longer skips later batches or returns an error after a partial write (fixes the
two P1 review findings). The parent task is never deleted or orphaned.
Refactored createSubtasksFromTemplate to object params and folded the applied-
description fetch inside it, so both the internal and public call sites share the
same failure isolation.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Deployment failed with the following error: Learn More: https://vercel.link/multiple-function-regions |
|
@greptile please review again |
Per product decision: don't apply a template partially or fail silently. If any subtask fails to create, roll back the parent task and throw, so the caller gets a clear error instead of a half-populated task with silently-missing subtasks. The concurrency batching from the earlier commit is retained and is what makes this safe: it prevents the connection-pool exhaustion (P2024) that was causing the failures — and would otherwise trigger this rollback and make the task "disappear". The rollback now also covers a failed getAppliedTemplateDescription (folded inside the try), so any failure rolls back consistently. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
please re review @greptile |
Problem
Creating a task from a template with many sub-templates left some subtasks unsaved, and opening the task detail threw:
Root cause
Applying a template fanned out every sub-template's task creation concurrently via
Promise.all. EachcreateSubtasksFromTemplate→createTaskis heavy (multiple queries + activity log + notifications trigger + webhook). For a large template (e.g. 90 sub-templates), ~90 concurrentcreateTaskcalls saturated the Prisma connection pool — so:getSubtaskCountson the detail page couldn't acquire a connection withinpool_timeout→P2024getSubtaskCountswas the victim, not the cause.Fix
Bound the fan-out concurrency so it can't monopolize the pool, independent of pool size:
src/utils/array.ts— addchunk+runInBatches(items, size, handler)(at mostsizerun at once, one batch after another)src/constants/tasks.ts—subtaskTemplateBatchSize = 5tasks.service.ts&public.service.ts— both template-apply sites userunInBatchesinstead ofPromise.allOrdering is preserved (the per-subtask timestamp is still derived from
index).Notes
subtaskTemplateBatchSizeis deliberately conservative; bump it in one place if more throughput is wanted.🤖 Generated with Claude Code