Skip to content

Conversation

@midigofrank
Copy link
Collaborator

@midigofrank midigofrank commented Nov 19, 2025

Description

Fixes the "loading workflow screen of death" issue where users experienced infinite loading spinners when the WebSocket disconnected. This PR enables graceful degradation by preserving offline workflow state and allowing offline editing with automatic sync on reconnection.

Key Changes

1. Graceful Disconnection Handling (commit 219a065)

  • LoadingBoundary: Allow rendering with cached workflow data when disconnected
  • useWorkflowReadOnly: Add connection state check to enable read-only mode during disconnection
  • SessionProvider: Track reconnection state and reinitialize session properly
  • createSessionStore: Clean up existing provider before reinitializing
  • Display read-only banner with appropriate tooltips when disconnected

2. Offline Editing Support (commit d601b42)

  • Preserve Y.Doc across disconnections instead of destroying it
  • Separate initialization and cleanup effects in SessionProvider
  • Enable Monaco editor during offline periods (no longer read-only)
  • Changes made offline are automatically synced when connection is restored

3. Architecture Improvements (commit dca56c4)

  • Extract useProviderLifecycle hook for provider creation/reconnection management
  • Add useYDocPersistence hook for Y.Doc lifecycle management (created once, only destroyed on unmount)
  • Create ConnectionStatusContext to expose connection state to components
  • Improve separation of concerns in SessionProvider
  • Track sync state and last sync time for better connection visibility

How It Works

The implementation uses Y.js CRDTs (Conflict-free Replicated Data Types) which automatically handle offline editing:

  1. During connection: Y.Doc syncs changes via PhoenixChannelProvider
  2. On disconnect: Y.Doc persists in memory, provider is destroyed
  3. Offline editing: Changes accumulate in Y.Doc locally
  4. On reconnect: New provider is created, Y.Doc automatically syncs all offline changes
  5. Conflict resolution: Y.js CRDT algorithm merges changes from all users automatically

Closes #3972

Validation steps

Test 1: Offline Editing and Sync

  1. Open the collaborative editor on a workflow
  2. Make a change to job code (e.g., add a comment)
  3. Stop the Phoenix server: Ctrl+C in your server terminal
  4. You should see the workflow diagram remain visible (no loading spinner)
  5. Make additional changes to the job code while offline
  6. Restart the server: iex -S mix phx.server
  7. Wait for reconnection (watch browser console logs)
  8. Verify all offline changes were synced to the server
  9. Open the workflow in another browser/tab to confirm changes are persisted

Test 2: Concurrent Offline Editing (Conflict Resolution)

  1. Open the same workflow in two different browsers (Browser A and Browser B)
  2. Stop the Phoenix server
  3. In Browser A: Edit job 1's code
  4. In Browser B: Edit job 2's code (different job)
  5. Restart the server
  6. Verify both browsers reconnect and both changes are preserved
  7. Open a third browser - both changes should be visible

AI Usage

Please disclose how you've used AI in this work (it's cool, we just want to know!):

  • Code generation (copilot but not intellisense)
  • Learning or fact checking
  • Strategy / design
  • Optimisation / refactoring
  • Translation / spellchecking / doc gen
  • Other
  • I have not used AI

You can read more details in our Responsible AI Policy

Pre-submission checklist

  • I have performed a self-review of my code.
  • I have implemented and tested all related authorization policies. (e.g., :owner, :admin, :editor, :viewer)
  • I have updated the changelog.
  • I have ticked a box in "AI usage" in this PR

@midigofrank midigofrank self-assigned this Nov 19, 2025
@github-project-automation github-project-automation bot moved this to New Issues in v2 Nov 19, 2025
@codecov
Copy link

codecov bot commented Nov 19, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.83%. Comparing base (14819c9) to head (834965d).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4012      +/-   ##
==========================================
- Coverage   88.84%   88.83%   -0.02%     
==========================================
  Files         422      422              
  Lines       19118    19118              
==========================================
- Hits        16985    16983       -2     
- Misses       2133     2135       +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@midigofrank midigofrank marked this pull request as ready for review November 19, 2025 06:35
Copy link
Member

@taylordowns2000 taylordowns2000 left a comment

Choose a reason for hiding this comment

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

Hey @midigofrank , quick Qs before a full review:

  1. Why must the workflow be read only? Isn't the idea of this yDoc/collaborative editor that I can make changes and have those changes pushed to the web once my connection is restored?
  2. I still get the loading screen with low/intermittent connectivity on the IDE. Can that be handled in the same way?
image

@midigofrank
Copy link
Collaborator Author

Hey @taylordowns2000 ,

Re 1: Yes it's possible, it just requires a little more work. The current setup overwrites the changes in the store with the server changes. Maybe this should be the next step

Re 2: Great catch! Let me fix that

@midigofrank
Copy link
Collaborator Author

Hey @taylordowns2000 ,

Re 1: Yes it's possible, it just requires a little more work. The current setup overwrites the changes in the store with the server changes. Maybe this should be the next step

Re 2: Great catch! Let me fix that

@stuartc says that they should merge and not overwrite. Let me do a diagnosis on what it would take to make that possible

@midigofrank midigofrank force-pushed the 3972-loading-workflow-screen-of-death branch from bdcb847 to dca56c4 Compare November 21, 2025 05:32
When the WebSocket disconnects, users previously saw an infinite loading
spinner. Now the workflow remains visible in read-only mode with cached
data until the connection is restored.

Changes:
- LoadingBoundary: Allow rendering with cached workflow data when disconnected
- useWorkflowReadOnly: Add connection state check to enable read-only mode
- SessionProvider: Track reconnection state and reinitialize session properly
- createSessionStore: Clean up existing provider before reinitializing
- Add SessionContext to useWorkflowReadOnly tests for connection state

The implementation preserves Y.Doc state across reconnections while ensuring
SessionStore event handlers are properly attached to track connection changes.
All edit controls automatically disable when disconnected via the existing
read-only system.
Extract provider lifecycle and Y.Doc persistence logic into dedicated hooks
to improve code organization and reusability. Add ConnectionStatusContext to
centralize connection state management and make it accessible throughout the
component tree.

Changes:
- Extract useProviderLifecycle hook to manage provider creation/reconnection
- Add useYDocPersistence hook for Y.Doc lifecycle management
- Create ConnectionStatusContext for centralized connection status
- Update SessionProvider to use new hooks and wrap with ConnectionStatusProvider
- Track sync state and last sync time for better connection status visibility
- Fix test error messages to match actual guard function behavior
- Resolve merge conflict in ReadOnlyWarning test

This refactoring maintains the same functionality while improving code
maintainability and making connection state more accessible to components.
@midigofrank midigofrank force-pushed the 3972-loading-workflow-screen-of-death branch from 552c9a6 to 834965d Compare November 21, 2025 06:05
@midigofrank
Copy link
Collaborator Author

Hey @taylordowns2000 would you mind testing this out again.

@stuartc by the way, the mix.lock changes came about because I updated tidewave

Copy link
Member

@taylordowns2000 taylordowns2000 left a comment

Choose a reason for hiding this comment

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

does what it says on the tin. please until @stuartc gives a 👍 to merge.

@midigofrank , have you already created an issue for merging? (my review question 1) if not, please do so

@midigofrank
Copy link
Collaborator Author

@taylordowns2000 the latest commit merges the changes

Copy link
Member

@stuartc stuartc left a comment

Choose a reason for hiding this comment

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

A couple of things, I've thrown over a bunch of notes. There is some weird behaviour when switching to latest from a version, more easily noticed when you have two browsers open. It's like you're both on latest and also not :/

@github-project-automation github-project-automation bot moved this from New Issues to In review in v2 Nov 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

Collab-editor unusable with low/intermittent connectivity

4 participants