Skip to content

fix: iframe retry connection#2968

Merged
Kitenite merged 5 commits intomainfrom
fix/iframe-refresh
Oct 7, 2025
Merged

fix: iframe retry connection#2968
Kitenite merged 5 commits intomainfrom
fix/iframe-refresh

Conversation

@Kitenite
Copy link
Copy Markdown
Contributor

@Kitenite Kitenite commented Oct 7, 2025

Description

Related Issues

Type of Change

  • Bug fix
  • New feature
  • Documentation
  • Refactor
  • Other (please describe):

Testing

Screenshots (if applicable)

Additional Notes


Important

Fixes iframe refresh bug by introducing hooks for managing connection retries and timeouts, improving iframe handling logic.

  • Behavior:
    • Introduces useFrameReload and useSandboxTimeout hooks to manage iframe connection retries and timeouts.
    • FrameComponent in view.tsx now uses these hooks to handle connection failures and successes, improving iframe refresh logic.
    • Removes manual timeout and retry logic from index.tsx and view.tsx.
  • Hooks:
    • useFrameReload: Manages reload timing and connection state, with debounced connection failure handling.
    • useSandboxTimeout: Handles sandbox connection timeout, triggering retries and displaying toast notifications.
  • Misc:
    • Refactors FrameComponent to use new hooks, simplifying connection logic.
    • Adjusts FrameView in index.tsx to integrate with new hooks.

This description was created by Ellipsis for 72ee150. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • New Features

    • Adaptive retry and timeout for project preview connections, improving resilience.
    • In-app notification when connections are slow, with automatic retry.
  • Bug Fixes

    • Reduced instances of stuck or endlessly loading previews.
    • Faster, more reliable manual reloads of the preview frame.
  • Refactor

    • Streamlined loading-state handling and visual outline logic for consistent behavior without altering layout or content.

@vercel
Copy link
Copy Markdown

vercel bot commented Oct 7, 2025

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

Project Deployment Preview Comments Updated (UTC)
web Ready Ready Preview Comment Oct 7, 2025 2:11am
1 Skipped Deployment
Project Deployment Preview Comments Updated (UTC)
docs Skipped Skipped Oct 7, 2025 2:11am

@supabase
Copy link
Copy Markdown

supabase bot commented Oct 7, 2025

This pull request has been ignored for the connected project wowaemfasoptxrdjhilu because there are no changes detected in apps/backend/supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Oct 7, 2025

Caution

Review failed

The pull request is closed.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

Introduces two hooks for frame reloads and sandbox connection timeout, refactors Frame view to use a single Penpal connection attempt with explicit success/failure callbacks and a configurable timeout, and rewires the index component to use the new hooks and props. Debounce/toast usages are shifted from the index into dedicated hooks.

Changes

Cohort / File(s) Summary
Frame wiring and state orchestration
apps/web/client/src/app/project/[id]/_components/canvas/frame/index.tsx
Replaced in-component debounce/timeout logic with useFrameReload and useSandboxTimeout. Passed new handlers and penpalTimeoutMs to FrameComponent. Simplified UI readiness/outline conditions. Removed direct toast and lodash debounce.
Reload and connection management hook
apps/web/client/src/app/project/[id]/_components/canvas/frame/use-frame-reload.ts
Added useFrameReload providing progressive reload scheduling, immediate reload, debounced failure handling, success tracking, and dynamic Penpal timeout computation. Resets/cleans timers appropriately.
Sandbox connection timeout hook
apps/web/client/src/app/project/[id]/_components/canvas/frame/use-sandbox-timeout.ts
Added useSandboxTimeout(frame, onTimeout) to watch engine “connecting” state, trigger a 30s timeout, toast/log on slow connection, set hasTimedOut, and invoke onTimeout. Cleans up timers and resets state when not connecting.
Frame view connection flow
apps/web/client/src/app/project/[id]/_components/canvas/frame/view.tsx
Updated FrameViewProps: added reloadIframe, onConnectionFailed, onConnectionSuccess, penpalTimeoutMs?. Replaced retry loop with single Penpal attempt raced against a timeout; call success/failure callbacks accordingly. Adjusted errors and reload invocation.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Index as Frame Index (index.tsx)
  participant View as Frame View (view.tsx)
  participant IFrame as Iframe
  participant Penpal as Penpal Bridge
  participant Reload as useFrameReload
  participant Sandbox as useSandboxTimeout
  participant Engine as Editor Engine

  User->>Index: Open project / show frame
  Index->>Reload: init hook
  Index->>Sandbox: init hook with frame, onTimeout
  Index->>View: mount with {reloadIframe, onConnectionSuccess/Failed, penpalTimeoutMs}

  Note over View,Penpal: Attempt single Penpal connection<br/>with timeout (penpalTimeoutMs)
  View->>IFrame: obtain contentWindow
  View->>Penpal: connect()
  View-->>View: race(connect, timeout)

  alt Connected
    View->>Index: onConnectionSuccess()
    Index->>Reload: handleConnectionSuccess()
  else Timeout or Failure
    View->>Index: onConnectionFailed()
    Index->>Reload: handleConnectionFailed() (debounced)
    Reload-->>Reload: schedule progressive reload
    Reload->>Index: reloadKey updated
    Index->>View: rerender with new key
  end

  rect rgba(230,240,255,0.5)
  Note over Sandbox,Engine: Monitor sandbox "connecting"
  Sandbox->>Engine: check isConnecting
  Engine-->>Sandbox: state
  alt Still connecting after 30s
    Sandbox-->>Index: onTimeout()
    Index->>Reload: schedule reload
  else Not connecting
    Sandbox-->>Sandbox: reset hasTimedOut
  end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I nudge the frame with a whiskered poke,
Timers tick-tock as new hooks woke—
Penpal whispers, “Are you there?”
If not, I hop and try with care.
Sandboxes yawn, I toast the delay,
Then reload-sunrise starts the day. 🐇✨

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/iframe-refresh

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c7c2eb and 72ee150.

📒 Files selected for processing (4)
  • apps/web/client/src/app/project/[id]/_components/canvas/frame/index.tsx (2 hunks)
  • apps/web/client/src/app/project/[id]/_components/canvas/frame/use-frame-reload.ts (1 hunks)
  • apps/web/client/src/app/project/[id]/_components/canvas/frame/use-sandbox-timeout.ts (1 hunks)
  • apps/web/client/src/app/project/[id]/_components/canvas/frame/view.tsx (4 hunks)

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@vercel vercel bot temporarily deployed to Preview – docs October 7, 2025 02:07 Inactive
}, reloadDelay);
};

const handleConnectionFailed = debounce(() => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The debounced 'handleConnectionFailed' is created on every render. Wrap the debounce call in useMemo or useCallback and cancel it on unmount to maintain stable debounce state.

@Kitenite Kitenite changed the title fix: iframe refresh fix: iframe retry connection Oct 7, 2025
@Kitenite Kitenite merged commit 73bb072 into main Oct 7, 2025
5 of 6 checks passed
@Kitenite Kitenite deleted the fix/iframe-refresh branch October 7, 2025 02:08
console.error('No iframe found');
throw new Error('No iframe found');
console.error(`${PENPAL_PARENT_CHANNEL} (${frame.id}) - No iframe found`);
onConnectionFailed;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

onConnectionFailed is referenced without invoking it; change to onConnectionFailed() to execute the callback.

Suggested change
onConnectionFailed;
onConnectionFailed();

console.log(`${PENPAL_PARENT_CHANNEL} (${frame.id}) - Penpal connection set `);

// Notify parent of successful connection
onConnectionSuccess;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

onConnectionSuccess is referenced without being invoked; modify to onConnectionSuccess() to properly execute the callback.

Suggested change
onConnectionSuccess;
onConnectionSuccess();

console.error('No iframe found');
throw new Error('No iframe found');
console.error(`${PENPAL_PARENT_CHANNEL} (${frame.id}) - No iframe found`);
onConnectionFailed;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The function reference onConnectionFailed is not being invoked. This needs to be changed to onConnectionFailed() to properly execute the callback function. This issue appears in multiple places throughout the file and should be fixed in all occurrences to ensure proper error handling.

Suggested change
onConnectionFailed;
onConnectionFailed();

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

This comment came from an experimental review—please leave feedback if it was helpful/unhelpful. Learn more about experimental comments here.

console.log(`${PENPAL_PARENT_CHANNEL} (${frame.id}) - Penpal connection set `);

// Notify parent of successful connection
onConnectionSuccess;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The function reference onConnectionSuccess is not being invoked. This needs to be changed to onConnectionSuccess() to properly execute the callback function. The same issue appears with onConnectionFailed in several places throughout this file.

Suggested change
onConnectionSuccess;
onConnectionSuccess();

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

This comment came from an experimental review—please leave feedback if it was helpful/unhelpful. Learn more about experimental comments here.

`${PENPAL_PARENT_CHANNEL} (${frame.id}) - Connection failed: child is null`,
);
retrySetupPenpalConnection(error);
onConnectionFailed;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The function reference onConnectionFailed is not being executed here. This should be changed to onConnectionFailed() to properly invoke the callback function. This issue appears in multiple places throughout the file where the callback is referenced but not called.

Suggested change
onConnectionFailed;
onConnectionFailed();

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

This comment came from an experimental review—please leave feedback if it was helpful/unhelpful. Learn more about experimental comments here.

error,
);
retrySetupPenpalConnection(error);
onConnectionFailed;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The function reference onConnectionFailed is not being executed here. This should be changed to onConnectionFailed() to properly invoke the function when a connection failure occurs. This issue appears in multiple places throughout the file where the callback is referenced but not called.

Suggested change
onConnectionFailed;
onConnectionFailed();

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

This comment came from an experimental review—please leave feedback if it was helpful/unhelpful. Learn more about experimental comments here.

Comment on lines +122 to +126
const timeoutPromise = new Promise<never>((_, reject) => {
setTimeout(() => {
reject(new Error(`Penpal connection timeout after ${penpalTimeoutMs}ms`));
}, penpalTimeoutMs);
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The timeout promise could trigger even after a successful connection. Consider adding a cleanup mechanism to prevent this race condition:

let timeoutId: NodeJS.Timeout;
const timeoutPromise = new Promise<never>((_, reject) => {
  timeoutId = setTimeout(() => {
    reject(new Error(`Penpal connection timeout after ${penpalTimeoutMs}ms`));
  }, penpalTimeoutMs);
});

// Then in the connection.promise.then handler:
clearTimeout(timeoutId);

Alternatively, an AbortController could provide a cleaner solution for canceling the timeout when the connection succeeds.

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

This comment came from an experimental review—please leave feedback if it was helpful/unhelpful. Learn more about experimental comments here.

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