Skip to content

fix(tables): workflow-column run fixes + bounded run-N-rows#4754

Merged
TheodoreSpeaks merged 8 commits into
stagingfrom
fix/table-trigger-dependency
May 27, 2026
Merged

fix(tables): workflow-column run fixes + bounded run-N-rows#4754
TheodoreSpeaks merged 8 commits into
stagingfrom
fix/table-trigger-dependency

Conversation

@TheodoreSpeaks
Copy link
Copy Markdown
Collaborator

Summary

  • autoRun=false no longer flashes a run count. The add-group mutation now forwards group.autoRun as the dispatch flag, so an autoRun: false column stops opening a no-op dispatch that briefly showed "N running."
  • Cell-scoped re-run. Right-clicking a workflow cell now re-runs only that cell's group (cascading to dependents) — "Re-run cell" — instead of every group on the row. Plain cells still get "Re-run all cells."
  • Bounded "run N rows." New extensible per-dispatch cap ({ type: 'rows', max }) surfaced as "Run 10 / 1,000 empty rows" in the workflow-group header. The dispatcher stops after N eligible rows; the overlay/optimistic stamping skip capped runs. Adds limit + processed_count columns on table_run_dispatches (migration 0214).
  • Fixed stranded "Queued" cells. When a row's cascade lock is held, a manually-run autoRun: false group used to stick on Queued forever. The cascade owner now treats the queued marker (orphan pre-stamp) as a manual run and picks it up, and drains late markers before releasing the lock. No re-enqueue / polling.

Type of Change

  • Bug fix
  • New feature (run-N-rows)

Testing

Tested manually. tsc --noEmit clean; check:api-validation:strict passes; 161 table tests pass (incl. new workflow-columns.test.ts covering the queued-marker handoff). Merged latest staging before shipping.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

TheodoreSpeaks and others added 6 commits May 21, 2026 19:27
- Pass group.autoRun as the add-group dispatch flag so an autoRun=false
  column no longer opens a no-op dispatch that flashes the run-count badge.
- Scope the context-menu re-run to the right-clicked workflow cell's group
  (cascading to dependents) instead of every group on the row.
- Add an extensible per-dispatch row cap (DispatchLimit { type:'rows', max })
  surfaced as "Run 10 / 1,000 empty rows" in the group header; dispatcher
  stops after N eligible rows. New limit/processed_count columns on
  table_run_dispatches.
- Fix stranded "Queued" cells: the cascade owner now treats a queued marker
  (orphan pre-stamp) as a manual run so autoRun=false requested groups are
  picked up, and drains late markers before releasing the row lock.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…dependency

# Conflicts:
#	apps/sim/app/workspace/[workspaceId]/tables/[tableId]/table.tsx
Re-numbers the table_run_dispatches limit/processed_count columns from the
collided 0212 to 0214 after merging staging (which added its own 0212/0213).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped May 27, 2026 8:26am

Request Review

@cursor
Copy link
Copy Markdown

cursor Bot commented May 27, 2026

PR Summary

Medium Risk
Touches dispatcher state, cascade locking, and run eligibility—core table execution paths—with a DB migration; behavior is well-tested but regressions could affect large runs or concurrent rows.

Overview
Adds a bounded run path for workflow columns: optional { type: 'rows', max } on the run-column API and dispatch records (DB migration 0214 with limit + processed_count). The dispatcher stops after N eligible rows, clamps running counts, and does not count failed enqueues toward the cap. Capped runs skip eager bulk clear and client optimistic stamping; the active-dispatch overlay ignores capped dispatches so queued UI comes from real cell SSE.

UI: Workflow group headers expose “Run 10 / 1,000 empty rows”; right-click on a workflow cell scopes Run/Re-run to that group (labels “Run cell” / “Re-run cell”) and classifies status per group.

Reliability: Queued markers (pending without executionId) are treated as explicit manual runs in pickNextEligibleGroupForRow; the cell worker re-acquires the cascade lock to drain late markers. Adding a workflow group forwards autoRun so autoRun: false does not open a no-op dispatch that flashes “N running.”

Reviewed by Cursor Bugbot for commit ffa8bd3. Bugbot is set up for automated code reviews on this repo. Configure here.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 27, 2026

Greptile Summary

This PR fixes several workflow-column bugs and adds bounded "run N rows" capability. The autoRun=false flash is fixed by forwarding group.autoRun as the top-level dispatch flag on group creation (the contract already accepted this field — it just wasn't being sent). Stranded "Queued" cells are resolved by an outer re-drive loop in executeWorkflowGroupCellJob that detects queued markers landing in the window between cascade exit and lock release, treating them as manual runs via isManualRun: isRequested.

  • Bounded row dispatch — new DispatchLimit { type: 'rows', max } field on table_run_dispatches (migration 0214); dispatcherStep caps processing to max eligible rows, resets the counter on batch-enqueue failure, and completes the dispatch early; the client overlay and optimistic stamping skip capped dispatches.
  • Cell-scoped context menu — right-clicking a workflow-output cell now scopes Run/Re-run to that group only, with updated labels ("Re-run cell" vs "Re-run all cells") and classifyExecStatusMix narrowed to the single group.
  • Row-cap presetsLIMITED_RUN_PRESETS = [10, 1000] extracted as a shared constant used by both the inline dropdown and ColumnOptionsMenu, addressing the previous duplication concern.

Confidence Score: 5/5

Safe to merge — all changed paths are additive (new DB columns with defaults, new optional request field, new constant) and the bug fixes are narrowly scoped to the dispatcher step and cascade lock handoff.

The two concerns raised in the previous review round (budget counter advancing on failed batches, and the terminal SSE missing the limit field) are both addressed. The dispatchedRows = 0 reset in the catch block correctly prevents cap consumption on transient failures. The completeDispatch helper now spreads dispatch.limit into the SSE event. The outer cascade re-drive loop is guarded by an explicit hasQueuedMarker check, preventing infinite re-triggering of auto-eligible groups. Schema migration is non-breaking (both columns have defaults). Test coverage for the queued-marker handoff is included.

No files require special attention.

Important Files Changed

Filename Overview
apps/sim/lib/table/dispatcher.ts Adds DispatchLimit + processedCount fields, row-cap filtering per window, safe budget reset on batch-enqueue failure, and completeDispatch helper; logic is correct and previous review concerns are addressed.
apps/sim/background/workflow-column-execution.ts Outer while-loop added to re-drive queued-marker groups after cascade exits, guarded by hasQueuedMarker check to prevent infinite re-triggering of auto-eligible groups.
apps/sim/lib/table/workflow-columns.ts pickNextEligibleGroupForRow now propagates isRequested flag so autoRun:false queued-marker groups are treated as manual runs; limit parameter threaded through runWorkflowColumn.
apps/sim/hooks/queries/tables.ts limit forwarded through useRunColumn; optimistic stamping skipped for capped runs; autoRun: group.autoRun now forwarded in useAddWorkflowGroup to fix the no-op dispatch flash.
apps/sim/lib/api/contracts/tables.ts runLimitSchema added with proper integer bounds (1–1,000,000); RunLimit type exported; activeDispatchSchema extended with optional limit field.
apps/sim/app/workspace/[workspaceId]/tables/[tableId]/components/table-grid/table-grid.tsx contextMenuGroupId introduced to scope Run/Re-run to the clicked cell's group; classifyExecStatusMix narrowed to single group when applicable; workflowCellScoped passed to ContextMenu.
packages/db/schema.ts limit (jsonb, nullable) and processed_count (integer, default 0, not null) added to tableRunDispatches with appropriate documentation.

Sequence Diagram

sequenceDiagram
    participant UI as Client UI
    participant API as /columns/run API
    participant WC as workflow-columns.ts
    participant D as dispatcher.ts
    participant BG as workflow-column-execution.ts
    participant DB as Database

    UI->>API: "POST runColumn { groupIds, limit: { type:'rows', max:10 } }"
    API->>WC: "runWorkflowColumn({ limit })"
    WC->>DB: "insertDispatch({ limit, processedCount:0 })"
    WC-->>UI: "{ dispatchId }"

    Note over D: dispatcherStep loop

    loop Per window
        D->>DB: fetch chunk of rows
        D->>D: buildPendingRuns → filter to allowed rowIds (≤ remaining)
        D->>DB: stampQueuedForBatch(windowRuns)
        D->>BG: batchEnqueueAndWait(windowRuns)
        alt Batch succeeds
            D->>DB: incrementProcessedCount(+dispatchedRows)
            alt budgetExhausted
                D->>DB: markDispatchComplete
                D->>UI: SSE dispatch complete (limit included)
            else budget remains
                D->>DB: advanceCursor
                D->>UI: SSE dispatch dispatching
            end
        else Batch fails
            D->>D: "reset dispatchedRows=0, budgetExhausted=false"
            D->>DB: flip pre-stamps → error
            D->>UI: SSE cell error per row
        end
    end

    Note over BG: Per-cell cascade + queued-marker handoff

    BG->>DB: withCascadeLock → runRowCascadeLoop
    loop Cascade groups
        BG->>DB: runWorkflowAndWriteTerminal
        BG->>DB: pickNextEligibleGroupForRow(excludeCurrentGroup)
    end
    BG->>DB: release lock
    BG->>DB: getRowById (fresh)
    BG->>BG: pickNextEligibleGroupForRow (no exclude)
    alt queued marker found (pending + no executionId)
        BG->>DB: re-acquire lock with new executionId
        BG->>DB: run queued-marker group
    else no marker
        BG->>BG: break
    end
Loading

Reviews (2): Last reviewed commit: "chore(lint): format generated tool-schem..." | Re-trigger Greptile

Comment thread apps/sim/lib/table/dispatcher.ts
Comment thread apps/sim/lib/table/dispatcher.ts
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a7bc6ea. Configure here.

Comment thread apps/sim/background/workflow-column-execution.ts
- Don't consume the row cap when batchEnqueueAndWait fails; a transient
  failure no longer completes a capped dispatch with zero rows started.
- Outer cascade-drain loop only re-drives a genuine queued marker, not any
  eligible group, so an empty-output group can't re-run forever.
- completeDispatch forwards limit on the terminal SSE event.
- Extract shared LIMITED_RUN_PRESETS for the Run-N-rows menu items.
@TheodoreSpeaks
Copy link
Copy Markdown
Collaborator Author

@greptile review

@TheodoreSpeaks TheodoreSpeaks merged commit 92fd17c into staging May 27, 2026
14 checks passed
@TheodoreSpeaks TheodoreSpeaks deleted the fix/table-trigger-dependency branch May 27, 2026 08:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant