Skip to content

fix(worker): two-level fan-out for description generation (fixes #488)#489

Merged
m43i merged 10 commits into
mainfrom
issue-488
Jun 23, 2026
Merged

fix(worker): two-level fan-out for description generation (fixes #488)#489
m43i merged 10 commits into
mainfrom
issue-488

Conversation

@bot-kiwi

@bot-kiwi bot-kiwi Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix the process-files workflow exceeding OpenWorkflow's hardcoded step limit (1000) on large projects by implementing a two-level fan-out pattern.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactoring (no functional changes)
  • Documentation update
  • CI/CD or infrastructure change

Changes Made

  • Created process-descriptions-group workflow that spawns multiple update-descriptions sub-workflows internally (bounded to 50 batches per group)
  • Modified process-files workflow to spawn process-descriptions-groups sub-workflows instead of directly spawning all update-descriptions sub-workflows
  • This reduces the parent workflow's step count from O(batches) to O(groups): a project with 3511 description batches now spawns ~71 groups instead of 3511 direct calls

Technical Details

The issue occurs because process-files was fanning out ALL child workflows from a single parent step:

  • One process-file sub-workflow per file
  • One update-descriptions sub-workflow per description batch

For large projects (e.g., 498 files, 68,421 entities + 43,882 relationships → ~3,511 update-descriptions batches), this exceeds the 1000 step limit.

The two-level fan-out adds an intermediate process-descriptions-groups workflow:

  1. Parent (process-files) spawns groups (each group = 1 step in parent)
  2. Each group spawns a slice of description batches (internal steps within the group)

Related Issues

Closes #488

Testing

  • I have tested these changes locally
  • I have added/updated tests as appropriate
  • All existing tests pass

Checklist

  • My code follows the project's coding standards
  • I have updated documentation as needed
  • I have run make generate if SQL queries were modified (backend)
  • I have updated barrel exports if components were added (frontend)

…limit

The process-files workflow fans out ALL update-descriptions sub-workflows
from a single parent step. For large projects with many entities/relationships,
this exceeds OpenWorkflow's hardcoded step limit (1000), causing the parent
workflow to crash before finalization.

This introduces a two-level fan-out pattern:
1. A new process-descriptions-groups workflow spawns multiple update-descriptions
   sub-workflows internally (bounded by DESCRIPTION_BATCHES_PER_GROUP=50)
2. The process-files workflow now spawns process-descriptions-groups sub-workflows
   instead of directly spawning all update-descriptions

With 50 batches per group, a project with 3511 description batches would spawn
71 groups (~71 steps in parent) instead of 3511 direct calls, staying well under
the 1000 step limit.

Data is safe during the crash - entities and relationships are fully processed,
only the status update is missing.
@bot-kiwi
bot-kiwi Bot requested a review from m43i as a code owner June 23, 2026 13:07
@bot-kiwi bot-kiwi Bot added backend bug Something isn't working labels Jun 23, 2026
The group workflow was doing its own internal grouping logic,
but each call already receives pre-sliced IDs (one group's worth).
It should simply batch them for update-descriptions calls.
@greptile-apps

greptile-apps Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes the OpenWorkflow step-limit overflow on large projects by introducing an intermediate process-descriptions-groups workflow that batches update-descriptions sub-workflow calls into groups of 50, reducing the parent process-files workflow's step count from O(description batches) to O(groups).

  • New process-descriptions-group workflow: receives a pre-sliced set of entity/relationship IDs, re-chunks them at DESCRIPTION_BATCH_SIZE, and spawns update-descriptions sub-workflows via Promise.allSettled, throwing on any batch failure.
  • Updated process-file.ts: replaces the direct update-descriptions fan-out with a loop over processDescriptionsGroupsSpec group workflows; uses Promise.allSettled with a failedGroups.length > 0 guard that correctly propagates any partial failure up the chain.
  • Worker registration: worker.ts adds the dynamic import and implementWorkflow call for the new group workflow so it is picked up by the OpenWorkflow runtime.

Confidence Score: 5/5

The change is safe to merge. The two-level fan-out is implemented correctly: both the group and parent workflows use Promise.allSettled with guards that propagate any failure, and the new workflow is properly registered with the OpenWorkflow runtime.

All four issues flagged in previous review rounds (duplicate step name, duplicate import, step.runWorkflow inside step.run, and Promise.all vs Promise.allSettled) have been addressed. The current implementation correctly handles partial failures at both levels of the fan-out, the double-chunking logic is equivalent to the original batching, and the step-count arithmetic (~574 steps for the described 498-file case) stays well within the 1000-step limit.

No files require special attention.

Important Files Changed

Filename Overview
apps/worker/workflows/process-descriptions-group-spec.ts New workflow spec defining the process-descriptions-groups intermediate workflow with retry policy and schema; exports DESCRIPTION_BATCHES_PER_GROUP = 50 constant used by both the parent and group workflow.
apps/worker/workflows/process-descriptions-group.ts New group workflow that re-chunks received entity/relationship IDs and spawns update-descriptions sub-workflows; uses Promise.allSettled and correctly throws on any batch failure.
apps/worker/workflows/process-file.ts Replaces direct update-descriptions fan-out with a two-level fan-out via processDescriptionsGroupsSpec; uses Promise.allSettled with correct failedGroups.length > 0 guard that propagates any partial failure.
apps/worker/worker.ts Adds dynamic import and ow.implementWorkflow registration for processDescriptionsGroups; no issues.

Reviews (9): Last reviewed commit: "fix: throw on any description group fail..." | Re-trigger Greptile

Comment thread apps/worker/workflows/process-file.ts Outdated
Comment thread apps/worker/workflows/process-file.ts
Comment thread apps/worker/workflows/process-file.ts Outdated
Comment thread apps/worker/workflows/process-file.ts Outdated
bot-kiwi added 6 commits June 23, 2026 15:16
…tency

Follow the same pattern as file fan-out: call step.runWorkflow directly
at the workflow level instead of wrapping in step.run. This matches the
established pattern in the codebase and addresses Greptile P1 feedback.
…group

Replace sequential for...of/await loops with Promise.all to avoid
multiplying description-phase latency by up to 50x for large projects.
Addresses Greptile 3/5 feedback — previously all batches in a group
ran serially, making the two-level fan-out counterproductive.
The new processDescriptionsGroups workflow must be registered with
OpenWorkflow via ow.implementWorkflow() to execute. Without it, all
spawned group tasks queue indefinitely. Addresses Greptile 2/5 finding.
Consistent with the established pattern elsewhere in the codebase.
Promise.allSettled waits for all sub-workflows before returning,
avoiding premature rejection on a single batch failure.
Comment thread apps/worker/workflows/process-descriptions-group.ts Outdated
…Groups

Promise.allSettled swallows rejections silently. Add explicit failure
detection after allSettled to surface batch failures instead of
silently proceeding with incomplete graph data. Consistent with
the error-handling pattern used elsewhere in the codebase.
Comment thread apps/worker/workflows/process-file.ts
Replace the every(...rejected) guard with some(...rejected) so that
if even one group fails, the error propagates and the graph is not
marked "ready" with incomplete descriptions. Regressed from the
original Promise.all behaviour which would surface any single batch
failure upstream.
@greptile-apps

greptile-apps Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Want your agent to iterate on Greptile's feedback? Try greploops.

@m43i
m43i added this pull request to the merge queue Jun 23, 2026
Merged via the queue into main with commit 3f3f93e Jun 23, 2026
3 checks passed
@m43i
m43i deleted the issue-488 branch June 23, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: process-files workflow exceeds OpenWorkflow step limit (1000) on large projects

1 participant