Skip to content

Conversation

@waleedlatif1
Copy link
Collaborator

Summary

  • Add Redis event buffer that dual-writes execution events alongside SSE for reconnection
  • Add SSE reconnection endpoint (GET /api/workflows/[id]/executions/[executionId]/stream)
  • Client detects running entries after page refresh and reconnects to replay events from Redis
  • Server remains sole authority for execution IDs — client receives via X-Execution-Id header
  • Defers clearing old console entries until first reconnection event arrives (no visual jitter)
  • Graceful degradation: works without Redis (reconnection returns 404, entries marked stale)

Type of Change

  • Bug fix

Testing

Tested manually

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)

@vercel
Copy link

vercel bot commented Feb 11, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Feb 12, 2026 2:59am

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 11, 2026

Greptile Overview

Greptile Summary

Adds Redis-backed event buffering and SSE reconnection to restore running executions after page refresh. The implementation dual-writes execution events to Redis alongside SSE streaming, allowing clients to detect running console entries on mount and reconnect to replay missed events.

Key changes:

  • New event-buffer.ts with Redis sorted sets for event storage (1-hour TTL, 1000 event limit per execution)
  • New reconnection endpoint GET /api/workflows/[id]/executions/[executionId]/stream with polling for terminal status
  • Client-side reconnection logic in use-workflow-execution.ts detects running entries after hydration, cancels zombies, and replays events
  • Defers clearing old console entries until first reconnection event arrives to prevent visual jitter
  • Graceful degradation: works without Redis (reconnection returns 404, entries marked as unavailable)

Issues addressed:

  • Previous review flagged zadd bug and invalid from handling — both are now fixed
  • Server remains sole authority for execution IDs via X-Execution-Id header

Minor style concerns:

  • Reconnection cleanup logic uses dual flags (cleanupRan and reconnectionComplete) that could be simplified
  • cancelRunningEntries timing relative to reconnection setup could be clearer

Confidence Score: 4/5

  • Safe to merge with minor style improvements recommended
  • Critical bugs from previous review (zadd and from validation) are fixed. Core reconnection logic is sound with proper auth checks, graceful degradation, and duplicate execution handling. Two style comments suggest minor cleanup opportunities but don't affect correctness.
  • apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts — reconnection cleanup logic could be simplified (see comments on lines 2098 and 2245)

Important Files Changed

Filename Overview
apps/sim/lib/execution/event-buffer.ts new Redis-backed event buffer with proper zadd implementation, validates ID reservation logic correctly
apps/sim/app/api/workflows/[id]/executions/[executionId]/stream/route.ts new SSE reconnection endpoint with proper from parameter validation and auth checks, polls for new events until terminal status
apps/sim/app/api/workflows/[id]/execute/route.ts integrates event writer to dual-write execution events to Redis alongside SSE streaming, returns X-Execution-Id header
apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts adds reconnection logic in useEffect to detect running entries after page refresh, has minor style issues with state management but core logic is sound
apps/sim/hooks/use-execution-stream.ts adds reconnect method to hook for connecting to the stream endpoint with fromEventId query parameter

Sequence Diagram

sequenceDiagram
    participant User
    participant Browser
    participant ExecuteAPI as /api/workflows/[id]/execute
    participant EventBuffer as Redis Event Buffer
    participant StreamAPI as /api/workflows/[id]/executions/[executionId]/stream
    participant Console as Terminal Console Store

    Note over User,Console: Initial Execution
    User->>Browser: Start workflow execution
    Browser->>ExecuteAPI: POST with workflow input
    ExecuteAPI->>EventBuffer: createExecutionEventWriter(executionId)
    ExecuteAPI->>EventBuffer: setExecutionMeta(status: active)
    ExecuteAPI-->>Browser: SSE stream + X-Execution-Id header
    
    loop Execution Events
        ExecuteAPI->>EventBuffer: writer.write(event)
        ExecuteAPI->>Browser: SSE event
        Browser->>Console: addConsole(entry with isRunning: true)
    end
    
    ExecuteAPI->>EventBuffer: setExecutionMeta(status: complete)
    ExecuteAPI->>EventBuffer: writer.close()
    ExecuteAPI->>Browser: [DONE]
    Browser->>Console: Update entries (isRunning: false)

    Note over User,Console: Page Refresh / Navigation
    User->>Browser: Refresh page
    Browser->>Browser: Zustand rehydrates from IndexedDB
    Browser->>Console: Load persisted entries
    
    alt Running entries found
        Browser->>Browser: Detect isRunning entries in console
        Browser->>Console: Sort by startedAt, pick most recent
        Browser->>Console: cancelRunningEntries (mark old zombies as cancelled)
        Browser->>StreamAPI: GET /stream?from=0
        StreamAPI->>StreamAPI: authorizeWorkflowByWorkspacePermission
        StreamAPI->>EventBuffer: getExecutionMeta(executionId)
        
        alt Buffer exists
            StreamAPI->>EventBuffer: readExecutionEvents(executionId, fromEventId)
            EventBuffer-->>StreamAPI: Buffered events
            StreamAPI-->>Browser: SSE replay of events
            Browser->>Console: clearOnce() - clear old entries
            Browser->>Console: Add/update entries from replayed events
            
            loop Poll for new events (until terminal status)
                StreamAPI->>EventBuffer: readExecutionEvents(lastEventId)
                StreamAPI->>EventBuffer: getExecutionMeta()
                alt New events available
                    StreamAPI-->>Browser: SSE new events
                    Browser->>Console: Update console entries
                end
            end
            
            StreamAPI->>Browser: [DONE]
            Browser->>Console: Mark execution complete
        else Buffer expired (404)
            StreamAPI-->>Browser: 404 error
            Browser->>Console: Mark entries with warning (unavailable)
        end
    end
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 11, 2026

Additional Comments (1)

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts
comparing execution IDs from different runs could fail if sorted entries span multiple executions - entries from old executions may remain with isRunning=true

…rd<string, unknown>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@greptile
@cursor review

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

…oint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@cursor review
@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Feb 11, 2026

Additional Comments (1)

apps/sim/app/workspace/[workspaceId]/w/[workflowId]/hooks/use-workflow-execution.ts
Cancel endpoint /api/workflows/${activeWorkflowId}/executions/${storedExecutionId}/cancel doesn't exist in this PR, will return 404

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ock re-entry

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ted by navigation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@waleedlatif1
Copy link
Collaborator Author

@greptile
@cursor review

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

9 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@cursor review

@waleedlatif1
Copy link
Collaborator Author

@greptile

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

12 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

Copy link

@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 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

@waleedlatif1 waleedlatif1 merged commit 81dfeb0 into staging Feb 12, 2026
12 checks passed
@waleedlatif1 waleedlatif1 deleted the fix/refresh-resume branch February 12, 2026 03:31
waleedlatif1 added a commit that referenced this pull request Feb 12, 2026
)

* fix(terminal): reconnect to running executions after page refresh

* fix(terminal): use ExecutionEvent type instead of any in reconnection stream

* fix(execution): type event buffer with ExecutionEvent instead of Record<string, unknown>

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(execution): validate fromEventId query param in reconnection endpoint

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* Fix some bugs

* fix(variables): fix tag dropdown and cursor alignment in variables block (#3199)

* feat(confluence): added list space labels, delete label, delete page prop (#3201)

* updated route

* ack comments

* fix(execution): reset execution state in reconnection cleanup to unblock re-entry

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix(execution): restore running entries when reconnection is interrupted by navigation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* done

* remove cast in ioredis types

* ack PR comments

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Siddharth Ganesan <siddharthganesan@gmail.com>
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.

2 participants