Repository navigation
fix: unregister stuck service worker to recover from loading deadlock - #487
Conversation
When the service worker is permanently unresponsive (browser stopped it and MessageBus.start() fails silently on wake), all 5 retry attempts time out. The PR #421 one-time reload then reuses the same broken SW registration, leaving the app stuck on Loading forever. Unregistering the SW after retries are exhausted ensures the reload gets a fresh registration with a clean MessageBus. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 1 minutes and 27 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughAdds a fast PING/PONG health check and zombie-worker cleanup before wallet initialization; splits activation vs. message-bus timeouts (activation shorter, message-bus 30s); reduces init retry count; and ensures best-effort service-worker unregister on final timeout failure. Changes
Sequence Diagram(s)mermaid Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Deploying wallet-bitcoin with
|
| Latest commit: |
a6e3701
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://cb761a52.wallet-bitcoin.pages.dev |
| Branch Preview URL: | https://fix-unregister-stuck-service.wallet-bitcoin.pages.dev |
Review: Service Worker Unregister RecoveryStatus: ✅ Approved Summary: Unregister the dead service worker registration after retries exhaust, allowing the reload to trigger a fresh registration with clean . Security & Logic:
Test coverage: Test plan items all checked ✅. Good user-facing behavior validation. Merge ready: Approved pending CI pass. ✅ |
Deploying wallet-mutinynet with
|
| Latest commit: |
a6e3701
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://b7c54263.arkade-wallet.pages.dev |
| Branch Preview URL: | https://fix-unregister-stuck-service.arkade-wallet.pages.dev |
The INITIALIZE_MESSAGE_BUS handler in the SDK calls buildServices() which creates Wallet.create() — a network call to the ARK server. The SDK intentionally skips wrapping this with a timeout because it "performs network calls that legitimately exceed message timeout." After long idle periods (days), the cold connection to the ARK server (DNS, TLS, server wake-up) easily exceeds the previous 5s timeout. Each of the 5 retries sent a NEW INITIALIZE_MESSAGE_BUS, restarting the network calls from scratch every time, never letting them finish. - Increase messageBusTimeoutMs from 5s to 30s (matches SDK default) - Reduce maxRetries from 5 to 2 (30s × 2 retries is sufficient) - Keep serviceWorkerActivationTimeoutMs at 5s (no network involved) - Keep SW unregistration as fallback if retries are still exhausted Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Code Review: Service Worker Cleanup on TimeoutSummary✅ Looks good — Solid fix for the stuck loading state when the service worker becomes unresponsive. Key PointsWhat it does:
Why this matters: Code Quality ✅
Minor Observations
No BlockersThis is a straightforward timeout+cleanup improvement. Ship it. ✅ |
Some browsers (Vivaldi) keep the SW registered as "activated" after long idle periods but never actually wake the worker thread on postMessage. The 30s timeout and retry logic can't help because the SW is not processing messages at all — it's a zombie. Before calling ServiceWorkerWallet.setup(), ping the existing SW via a MessageChannel. If it doesn't respond within 2s, unregister it so setup() gets a fresh registration that actually works. - Add PING/PONG handler as the first thing in the SW script (works even if subsequent MessageBus initialization fails) - Add pre-flight ping in initSvcWorkerWallet before setup() - Rebuild wallet-service-worker.mjs Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file was intentionally removed from the repo in #437. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Review: Service Worker Zombie Detection & Recovery✅ Approach is solid. The PR addresses a real failure mode: browsers that keep a SW registered but don't actually respond to messages (observed in Vivaldi). The fix uses MessageChannel ping as a reliable liveness check. Strengths
Questions / Observations
Code Quality
RecommendationPost with clarifications on:
Once clarified, this is good to merge. The core fix is right. |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/providers/wallet.tsx`:
- Around line 324-347: Capture the ServiceWorkerRegistration.active value into a
local variable (e.g., const active = existingReg?.active) before using it so it
can't change between the check and postMessage, and update the MessageChannel
onmessage handler to only resolve true when the received message is the expected
pong (e.g., event.data?.type === 'PONG'); if not PONG, treat as not alive.
Ensure you still close the port and clear the timeout when resolving or timing
out, and call active.postMessage({ type: 'PING' }, [channel.port2]) using the
captured active reference.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: da0d35f7-e84d-4a7b-84f7-1fc4245fb01c
📒 Files selected for processing (2)
src/providers/wallet.tsxsrc/wallet-service-worker.ts
Pre-register the service worker on page load so activation runs in parallel with React bootstrap, ASP fetch and auth check instead of blocking inside ServiceWorkerWallet.setup(). Also run the zombie-SW detection (timeout reduced from 2s to 500ms) concurrently with the IndexedDB getWalletState() warmup. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
🔍 Code ReviewSummaryThis PR addresses a critical deadlock in wallet initialization when the service worker becomes unresponsive. The fix is methodical and well-structured across 5 commits:
Protocol/Security Assessment✅ No protocol impact — Changes are client-side wallet initialization only Code QualityStrengths:
Minor observations:
Testing CoverageThe test plan covers the critical paths:
Cross-Repo Impact✅ TS SDK — Uses parameter; now receives 30s instead of 5s. No breaking changes. RecommendationApprove. This is a well-decomposed fix for a real deadlock that affects users after browser/SW crashes or long idle periods. The timeout tuning is based on observed ARK server cold-start behavior, and the zombie detection is an elegant pre-flight check. No protocol or security risks. One thing to watch in next release: monitor for regression if any user reports the 30s timeout feeling long — though given this is only for recovery cases, it's justified. |
Capture registration.active into a local before the null check so it can't become null between the guard and postMessage. Only treat the response as alive when event.data.type is the expected 'PONG'. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Review: Service Worker Recovery & Cold Start OptimizationStatus: Approved for merge ✅ Strengths
Minor Observations
Protocol & Security
RecommendationMerge after:
Great work addressing a real pain point. The defense-in-depth approach (pre-registration + zombie detection + timeout tuning + unregistration) is the right call for reliability. |
Review: Service Worker Deadlock RecoveryOverall: ✅ Solid fix for the stuck loading state. The logic is sound and the test plan is comprehensive. Architecture & Approach
Security & Edge Cases
Test PlanThe checklist is solid, but consider:
Questions/Nits
Recommendation: Approve. This is a targeted, well-reasoned fix for a real user pain point. The code is clean and the degradation path is explicit. |
Summary
MessageBus.start()fails silently on wake), all 5 retry attempts ininitSvcWorkerWallettime outMessageBusTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Bug Fixes