Skip to content

fix(supabase_flutter): simplify lifecycle reconnection with serial Future chain#1340

Merged
grdsdev merged 6 commits into
supabase:mainfrom
brunovsiqueira:fix/realtime-lifecycle-queue
Apr 2, 2026
Merged

fix(supabase_flutter): simplify lifecycle reconnection with serial Future chain#1340
grdsdev merged 6 commits into
supabase:mainfrom
brunovsiqueira:fix/realtime-lifecycle-queue

Conversation

@brunovsiqueira
Copy link
Copy Markdown
Contributor

@brunovsiqueira brunovsiqueira commented Mar 27, 2026

Summary

Follow-up to #1321. Replaces the complex lifecycle state tracking (_disconnectFuture, _realtimeReconnectOperation, cancel flag) with a serial Future chain + target-state pattern, as suggested by @icnahom in the review.

  • Serial queue: _pendingLifecycleOperation ensures disconnect/connect never overlap
  • Stale-skip: _targetLifecycleState cancels outdated operations (e.g. abort reconnect if app backgrounded again)
  • Idempotency guards on both connect and disconnect paths
  • 3 state variables → 2, ~80 lines → ~30 lines

Test plan

  • Existing lifecycle tests pass
  • Added: rapid paused → resumed → paused → resumed flapping ends connected
  • Added: paused → resumed → paused before connect completes ends disconnected
  • Full supabase_flutter test suite passes
  • dart format and dart analyze clean

@icnahom
Copy link
Copy Markdown
Contributor

icnahom commented Apr 2, 2026

ICYMI, I have created a PR in your fork. It removes inheritance from WidgetsBindingObserver to avoid bloating the exposed API surface, and updates the tests to simulate lifecycle changes using TestWidgetsFlutterBinding. Worth noting, we now have more states to transition through because paused -> resumed is not allowed.

brunovsiqueira and others added 5 commits April 2, 2026 09:19
…uture chain

Replace complex lifecycle reconnection logic (_disconnectFuture,
_realtimeReconnectOperation, cancel flag) with a serial Future chain
and target-state pattern.

Operations are serialized via _pendingLifecycleOperation so disconnect
and connect never overlap. _targetLifecycleState tracks the most recent
lifecycle request, allowing stale operations to be skipped and
reconnects to be cancelled if the app goes back to background.

Add idempotency guards on both connect (isConnected) and disconnect
(isConnected || isConnecting) paths.

Add tests for rapid lifecycle flapping and cancellation edge cases.
…tsBindingObserver and adding AppLifecycleListener
@brunovsiqueira brunovsiqueira force-pushed the fix/realtime-lifecycle-queue branch from 836ed6f to e763d1b Compare April 2, 2026 08:19
Two issues fixed:

1. Missing mockAppLink() in setUp — on web, Supabase.initialize() calls
   _appLinks.getInitialLink() via a platform channel. Without the mock,
   that call hangs forever, timing out the test. Native tests were
   unaffected because _handleInitialUri() has a kIsWeb guard.

2. The completeReadyCompleters() helper was async void, so its body ran
   as a deferred microtask and cleared the list. Replace with
   settleLifecycle() that loops until all lifecycle operations settle.
@brunovsiqueira brunovsiqueira force-pushed the fix/realtime-lifecycle-queue branch from e763d1b to 7d702d0 Compare April 2, 2026 08:29
@grdsdev grdsdev requested a review from Vinzent03 April 2, 2026 09:26
@brunovsiqueira
Copy link
Copy Markdown
Contributor Author

@icnahom I merged your PR into it, fixed some tests, and PR is ready for review :)

Thank you!

Copy link
Copy Markdown
Contributor

@grdsdev grdsdev left a comment

Choose a reason for hiding this comment

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

Great work @brunovsiqueira .

I think we could also use such a pattern in the token refresh logic in GoTrueClient, I think there's room for improvements there too.

@grdsdev grdsdev merged commit 7121ac2 into supabase:main Apr 2, 2026
9 checks passed
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.

3 participants