feat: Flutter SDK update for version 23.2.0#308
feat: Flutter SDK update for version 23.2.0#308ArnabChatterjee20k wants to merge 13 commits intomainfrom
Conversation
Greptile SummaryThis PR bumps the Flutter SDK to version 23.2.0 and refactors the realtime subscription protocol from URL-encoded query parameters to WebSocket messages via a new Two concerns flagged in prior review rounds remain unaddressed in Confidence Score: 4/5Safe to merge for single-subscription use cases; multi-subscription reconnect correctness bugs from prior review remain open. Two P1 findings from previous review rounds (connected-handler slot collision, _pendingSubscribeSlots race) are still present and unaddressed. No new critical issues found beyond a P2 README vagueness nit. lib/src/realtime_mixin.dart — connected-handler slot+1 collision and _pendingSubscribeSlots race condition remain unresolved. Important Files Changed
Reviews (3): Last reviewed commit: "Commit from GitHub Actions (Format and p..." | Re-trigger Greptile |
| @@ -1,3 +1,4 @@ | |||
| import '../models.dart' as models; | |||
| for (var index = 0; index < subscriptions.length; index++) { | ||
| final slot = index < _pendingSubscribeSlots.length | ||
| ? _pendingSubscribeSlots[index] | ||
| : null; | ||
| final item = subscriptions[index] as Map<String, dynamic>?; | ||
| final subscriptionId = item?['subscriptionId']?.toString(); | ||
| if (slot == null || | ||
| subscriptionId == null || | ||
| subscriptionId.isEmpty) { | ||
| continue; | ||
| } | ||
| _slotToSubscriptionId[slot] = subscriptionId; | ||
| _subscriptionIdToSlot[subscriptionId] = slot; | ||
| } |
There was a problem hiding this comment.
_pendingSubscribeSlots race between multiple in-flight subscribe messages
_pendingSubscribeSlots is cleared and rebuilt every time _sendSubscribeMessage is called. Because responses arrive in order but the list is mutated before earlier responses land, a slot can be mapped to the wrong subscriptionId.
Concrete scenario:
- Subscribe slot A →
_sendSubscribeMessage→_pendingSubscribeSlots = [A] - Subscribe slot D arrives while (1) is in-flight →
_sendSubscribeMessage→_pendingSubscribeSlots = [A, D] - Slot A is closed →
_sendSubscribeMessage→_pendingSubscribeSlots = [D] - Response to (1) arrives:
subscriptions[0].subscriptionId = "s_A"— but_pendingSubscribeSlots[0]is nowD, so_slotToSubscriptionId[D] = "s_A". Events for channel A will be incorrectly dispatched to slot D's callback until the response to (3) overwrites the entry.
Consider versioning each batch (e.g., a monotonic sequence tag included in the subscribe message and echoed in the response), so stale responses can be discarded.
Made-with: Cursor
| rawSubscriptions.forEach((slotStr, subscriptionId) { | ||
| final slot = int.tryParse(slotStr.toString()); | ||
| if (slot != null) { | ||
| _slotToSubscriptionId[slot] = subscriptionId.toString(); | ||
| _subscriptionIdToSlot[subscriptionId.toString()] = slot; | ||
| final directSlotExists = _subscriptions.containsKey(slot); | ||
| final shiftedSlot = slot + 1; | ||
| final shiftedSlotExists = | ||
| _subscriptions.containsKey(shiftedSlot); | ||
| final targetSlot = directSlotExists | ||
| ? slot | ||
| : shiftedSlotExists | ||
| ? shiftedSlot | ||
| : slot; | ||
| _slotToSubscriptionId[targetSlot] = subscriptionId.toString(); | ||
| _subscriptionIdToSlot[subscriptionId.toString()] = targetSlot; | ||
| } | ||
| }); |
There was a problem hiding this comment.
Slot+1 shifting collides on multi-subscription reconnect
When the server sends a 0-based connected subscriptions map and there are ≥2 client subscriptions (client slots start at 1), both server slot N and server slot N+1 resolve to the same client slot N+1, overwriting the first mapping and leaving the higher-indexed slot with no subscriptionId.
Concrete example — client has slots 1 and 2, server returns {"0":"s_a","1":"s_b"}:
- Server
"0"→ direct slot 0 missing → shifted slot 1 found →_slotToSubscriptionId[1] = "s_a" - Server
"1"→ direct slot 1 found →_slotToSubscriptionId[1] = "s_b"(overwrites"s_a") - Result: slot 2 has no
subscriptionId; all events for that subscription are silently dropped.
Consider using _pendingSubscribeSlots (populated by _sendSubscribeMessage) as the authoritative index → slot mapping for connected payloads too, the same way the response case does at lines 148–161.
This PR contains updates to the Flutter SDK for version 23.2.0.