Fixed ghost channel subscription
This commit is contained in:
parent
029e671367
commit
3950f3ee94
|
|
@ -329,12 +329,22 @@ class StreamRecoveryWrapper<T> {
|
|||
_startRealtimeSubscription();
|
||||
}
|
||||
|
||||
/// Clean up all resources.
|
||||
/// Clean up all resources and notify the status callback that this
|
||||
/// channel is no longer active, preventing ghost entries in the
|
||||
/// [RealtimeController]'s recovering-channels set.
|
||||
void dispose() {
|
||||
if (_disposed) return;
|
||||
_disposed = true;
|
||||
_pollingTimer?.cancel();
|
||||
_recoveryTimer?.cancel();
|
||||
_realtimeSub?.cancel();
|
||||
// Ensure the channel is removed from the recovering set when the
|
||||
// wrapper is torn down (e.g. provider disposed during navigation).
|
||||
// Without this, disposed wrappers that were mid-recovery leave
|
||||
// orphaned entries that keep the reconnection indicator spinning.
|
||||
if (_connectionStatus != StreamConnectionStatus.connected) {
|
||||
_onStatusChanged?.call(channelName, StreamConnectionStatus.connected);
|
||||
}
|
||||
_controller?.close();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ final tasksProvider = StreamProvider<List<Task>>((ref) {
|
|||
// ── Realtime stream ───────────────────────────────────────────────────────
|
||||
// Processes every realtime event through the same isolate. Debounced so
|
||||
// rapid consecutive events (e.g. bulk inserts) don't cause repeated renders.
|
||||
wrapper.stream
|
||||
final wrapperSub = wrapper.stream
|
||||
.asyncMap((result) async {
|
||||
final payload = _buildTaskPayload(
|
||||
tasks: result.data,
|
||||
|
|
@ -286,10 +286,12 @@ final tasksProvider = StreamProvider<List<Task>>((ref) {
|
|||
},
|
||||
onError: (Object e) {
|
||||
debugPrint('[tasksProvider] stream error: $e');
|
||||
controller.addError(e);
|
||||
// Don't forward errors — the wrapper handles recovery internally.
|
||||
},
|
||||
);
|
||||
|
||||
ref.onDispose(wrapperSub.cancel);
|
||||
|
||||
return controller.stream;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -256,7 +256,7 @@ final ticketsProvider = StreamProvider<List<Ticket>>((ref) {
|
|||
// ── Realtime stream ───────────────────────────────────────────────────────
|
||||
// Processes every realtime event through the same isolate. Debounced so
|
||||
// rapid consecutive events (e.g. bulk inserts) don't cause repeated renders.
|
||||
wrapper.stream
|
||||
final wrapperSub = wrapper.stream
|
||||
.asyncMap((result) async {
|
||||
final payload = _buildTicketPayload(
|
||||
tickets: result.data,
|
||||
|
|
@ -280,10 +280,12 @@ final ticketsProvider = StreamProvider<List<Ticket>>((ref) {
|
|||
},
|
||||
onError: (Object e) {
|
||||
debugPrint('[ticketsProvider] stream error: $e');
|
||||
controller.addError(e);
|
||||
// Don't forward errors — the wrapper handles recovery internally.
|
||||
},
|
||||
);
|
||||
|
||||
ref.onDispose(wrapperSub.cancel);
|
||||
|
||||
return controller.stream;
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user