Skip to content

Restore workflow on cloud reconnection#653

Open
mjh1 wants to merge 2 commits intomainfrom
mh/restore-workflow
Open

Restore workflow on cloud reconnection#653
mjh1 wants to merge 2 commits intomainfrom
mh/restore-workflow

Conversation

@mjh1
Copy link
Contributor

@mjh1 mjh1 commented Mar 10, 2026

Summary by CodeRabbit

  • New Features
    • Automatic cloud workflow backup now preserves your work while connected to the cloud
    • Restore prompt appears when reconnecting to the cloud after a disconnect, allowing you to recover your previous session

You can test by manually disconnecting from cloud and reconnecting
Screenshot 2026-03-11 at 12 31 04
Screenshot 2026-03-11 at 12 31 09

Signed-off-by: Max Holland <max@livepeer.org>
@coderabbitai
Copy link

coderabbitai bot commented Mar 10, 2026

📝 Walkthrough

Walkthrough

A new React hook useCloudWorkflowBackup is introduced to auto-save cloud workflow state to localStorage and prompt users to restore their previous session when reconnecting after a cloud disconnect. The hook is integrated into StreamPage to backup workflow state automatically while connected and trigger restore dialogs on reconnection.

Changes

Cohort / File(s) Summary
Cloud Workflow Backup Hook
frontend/src/hooks/useCloudWorkflowBackup.ts
New hook implementing debounced backup to localStorage, disconnect tracking, and reconnection restore prompts via toast notifications. Handles restore flow with 30s toast duration and state persistence with timestamp and pipelineId.
StreamPage Integration
frontend/src/pages/StreamPage.tsx
Integrated cloud workflow backup hook with isCloudConnected calculation, handleCloudRestore callback to preload workflows on restore requests, and state pass-through for settings, prompts, pipelines, and related workflow data.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant StreamPage
    participant Hook as useCloudWorkflowBackup
    participant Storage as localStorage
    participant Toast as Toast UI

    Note over User,Toast: Connected State - Backup Flow
    User->>StreamPage: Updates workflow state
    StreamPage->>Hook: Workflow state changes
    Hook->>Hook: Debounce (500ms window)
    Hook->>Hook: Build ScopeWorkflow
    Hook->>Storage: Write backup with timestamp & pipelineId
    
    Note over User,Toast: Disconnect Flow
    User->>StreamPage: Cloud connection lost
    StreamPage->>Hook: isCloudConnected = false
    Hook->>Storage: Mark disconnect flag
    
    Note over User,Toast: Reconnect Flow - Restore Prompt
    User->>StreamPage: Cloud reconnected
    StreamPage->>Hook: isCloudConnected = true
    Hook->>Storage: Check disconnect flag
    Hook->>Storage: Read backup data
    Hook->>Toast: Show restore prompt (30s duration)
    
    Note over User,Toast: User Actions
    alt User Clicks Restore
        User->>Toast: Click restore
        Toast->>Hook: Trigger onRestoreRequest
        Hook->>StreamPage: Pass backed-up ScopeWorkflow
        StreamPage->>StreamPage: Load workflow import dialog
        Hook->>Storage: Clear backup & disconnect flag
    else User Dismisses or Timeout
        Toast-->>Hook: Toast closes
        Hook->>Storage: Clear backup & disconnect flag
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested reviewers

  • leszko

Poem

🐰 Hoppy hops through clouds so white,
Saving workflows left and right,
When connections bounce away,
Whispers restore to save the day!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main feature added: restoring a workflow when the cloud connection is re-established after a disconnect.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mh/restore-workflow

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 10, 2026

🚀 fal.ai Preview Deployment

App ID daydream/scope-pr-653--preview
WebSocket wss://fal.run/daydream/scope-pr-653--preview/ws
Commit 2ae4322

Testing

Connect to this preview deployment by running this on your branch:

uv run build && SCOPE_CLOUD_APP_ID="daydream/scope-pr-653--preview/ws" uv run daydream-scope

🧪 E2E tests will run automatically against this deployment.

@github-actions
Copy link
Contributor

github-actions bot commented Mar 10, 2026

✅ E2E Tests passed

Status passed
fal App daydream/scope-pr-653--preview
Run View logs

Test Artifacts

Check the workflow run for screenshots.

Signed-off-by: Max Holland <max@livepeer.org>
@mjh1 mjh1 marked this pull request as ready for review March 11, 2026 12:29
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
frontend/src/pages/StreamPage.tsx (1)

1999-2014: Inline promptState object causes effect to re-run on every render.

The promptState object is created inline, generating a new reference on each render. Since it's a dependency of the auto-save effect in useCloudWorkflowBackup, this resets the debounce timer unnecessarily on every render, even when the actual values haven't changed.

While the backup will still eventually fire (2 seconds after the last render), this is inefficient and could delay backups during active UI interaction.

♻️ Memoize promptState to avoid unnecessary effect re-runs
+  const promptState = useMemo(
+    () => ({
+      promptItems,
+      interpolationMethod,
+      transitionSteps,
+      temporalInterpolationMethod,
+    }),
+    [promptItems, interpolationMethod, transitionSteps, temporalInterpolationMethod]
+  );
+
   useCloudWorkflowBackup({
     settings,
     timelinePrompts,
-    promptState: {
-      promptItems,
-      interpolationMethod,
-      transitionSteps,
-      temporalInterpolationMethod,
-    },
+    promptState,
     pipelineInfoMap: pipelines,
     loraFiles,
     plugins,
     scopeVersion: scopeVersion ?? "unknown",
     isCloudConnected,
     onRestoreRequest: handleCloudRestore,
   });

You'll also need to add useMemo to the imports at the top of the file:

-import { useState, useEffect, useRef, useCallback } from "react";
+import { useState, useEffect, useRef, useCallback, useMemo } from "react";
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/pages/StreamPage.tsx` around lines 1999 - 2014, The inline
promptState object passed into useCloudWorkflowBackup causes a new reference
each render and retriggers the effect; fix this by importing useMemo and
memoizing promptState (containing promptItems, interpolationMethod,
transitionSteps, temporalInterpolationMethod) with useMemo so the object
identity only changes when its actual values change, then pass the memoized
promptState into useCloudWorkflowBackup.
frontend/src/hooks/useCloudWorkflowBackup.ts (1)

168-189: Consider documenting the callback stability requirement.

The onRestoreRequest callback is in the effect's dependency array. While the current integration in StreamPage correctly memoizes this callback with useCallback, future consumers should be aware that passing an unstable callback could cause the effect to re-run unexpectedly during reconnection scenarios.

Consider adding a JSDoc note to the onRestoreRequest prop in the interface:

 interface UseCloudWorkflowBackupOptions {
   // ...
-  /** Opens the workflow import dialog with the backup workflow preloaded. */
+  /** Opens the workflow import dialog with the backup workflow preloaded.
+   * Should be memoized (e.g., via useCallback) to avoid effect re-runs. */
   onRestoreRequest: (workflow: ScopeWorkflow) => void;
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/hooks/useCloudWorkflowBackup.ts` around lines 168 - 189, The
effect in useCloudWorkflowBackup depends on onRestoreRequest and can re-run if
callers pass an unstable function; update the API docs by adding a JSDoc on the
onRestoreRequest prop (in the interface used by useCloudWorkflowBackup/its
consumer, e.g., StreamPage) that states the callback must be stable (memoized
with React.useCallback) to avoid unintended effect re-runs during reconnection
and restore toast logic, and include a brief example/mention of useCallback for
future integrators.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/src/hooks/useCloudWorkflowBackup.ts`:
- Around line 168-189: The effect in useCloudWorkflowBackup depends on
onRestoreRequest and can re-run if callers pass an unstable function; update the
API docs by adding a JSDoc on the onRestoreRequest prop (in the interface used
by useCloudWorkflowBackup/its consumer, e.g., StreamPage) that states the
callback must be stable (memoized with React.useCallback) to avoid unintended
effect re-runs during reconnection and restore toast logic, and include a brief
example/mention of useCallback for future integrators.

In `@frontend/src/pages/StreamPage.tsx`:
- Around line 1999-2014: The inline promptState object passed into
useCloudWorkflowBackup causes a new reference each render and retriggers the
effect; fix this by importing useMemo and memoizing promptState (containing
promptItems, interpolationMethod, transitionSteps, temporalInterpolationMethod)
with useMemo so the object identity only changes when its actual values change,
then pass the memoized promptState into useCloudWorkflowBackup.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a8b84dc-72fb-4382-97d8-fd168b8ce45b

📥 Commits

Reviewing files that changed from the base of the PR and between 5d1800b and 2ae4322.

📒 Files selected for processing (2)
  • frontend/src/hooks/useCloudWorkflowBackup.ts
  • frontend/src/pages/StreamPage.tsx

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