Skip to content

chore: enable avoid-passing-async-when-sync-expected lint#1455

Merged
spydon merged 4 commits into
mainfrom
chore/avoid-passing-async-when-sync-expected
Jun 22, 2026
Merged

chore: enable avoid-passing-async-when-sync-expected lint#1455
spydon merged 4 commits into
mainfrom
chore/avoid-passing-async-when-sync-expected

Conversation

@spydon

@spydon spydon commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Stacked on top of #1454. Review/merge that one first; the base will retarget to main automatically once it lands.

What

Enables the DCM rule avoid-passing-async-when-sync-expected (removing it from the ratchet list in supabase_lints) and resolves the 13 resulting violations.

Why

When an async callback is passed where a synchronous one is expected, the returned Future is discarded, so if it throws the error is silently lost. This is the same class of problem as the unawaited_futures/discarded_futures lints in #1454, just at call sites that take a callback. Enabling it closes the remaining async-safety gap.

How

Each of the 13 sites was made synchronous, and the inner async work was either wrapped in unawaited(...) (genuine fire-and-forget) or extracted into a dedicated method, preserving existing behavior and error handling. Highlights:

  • realtime_channel.dart: extracted the joinPush.receive('ok', ...) body into _handleJoinOk(...) (the InvalidJWTToken setAuth handling is preserved verbatim).
  • realtime_client.dart: extracted reconnect into _reconnect(), heartbeat timer callback made sync with unawaited(sendHeartbeat()).
  • supabase_client.dart: onAuthStateChangeSync listener made sync with unawaited(_handleTokenChanged(...)).
  • supabase_stream_builder.dart: onDone: controller.closeonDone: () => unawaited(controller.close()) in the asyncMap/asyncExpand reimplementations.
  • Remaining sites are in test mock servers and a widget-test stub.

No public API signatures were changed.

Verification

  • dcm analyze: 0 avoid-passing-async-when-sync-expected across all packages.
  • dart analyze: clean, no new unawaited_futures/discarded_futures.
  • Tests: realtime_client (channel/socket/mock), supabase (mock/utilities), and supabase_flutter suites all pass.

@spydon
spydon requested a review from a team as a code owner June 22, 2026 16:03
Base automatically changed from chore/await-futures-lint to main June 22, 2026 17:16
spydon added 4 commits June 22, 2026 19:19
Enable the DCM avoid-passing-async-when-sync-expected rule so that async
callbacks are not passed where a synchronous one is expected, which would
discard the returned future and silently lose its errors.

Resolve all violations by making the callbacks synchronous and either
wrapping the genuinely fire-and-forget work in unawaited() or extracting
it into a dedicated method.
Use the mockServer.first + held-future pattern already used by the
httpSend tests instead of the Completer plus unawaited(...then...) dance.

The 'via ws conn when subscribed' test previously did its assertions
inside the subscribe callback, which never fired against the raw mock
server, so it asserted nothing. It now upgrades the websocket, replies to
the channel join, and verifies the broadcast is actually pushed over the
socket.
The extracted join handler only indexes the response by key, so Map
expresses the contract without resorting to dynamic. Map rather than
Map<String, dynamic> because the test helpers trigger replies with
loosely typed maps.
… dynamic>

Typing Push.trigger's response parameter fixes the source of the loosely
typed reply maps (the trigger('ok', {}) literals now infer
Map<String, dynamic>), so _handleJoinOk can take a typed map instead of a
raw one.
@spydon
spydon force-pushed the chore/avoid-passing-async-when-sync-expected branch from c5f8178 to 1115971 Compare June 22, 2026 17:20
@spydon
spydon merged commit 4c51f49 into main Jun 22, 2026
42 checks passed
@spydon
spydon deleted the chore/avoid-passing-async-when-sync-expected branch June 22, 2026 21:44
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.

2 participants