RpcBufferedBroadcastController<T> class
A broadcast stream controller that retains events while it has no listener and replays them, in arrival order, to the first subscriber.
A plain StreamController.broadcast() silently drops events delivered while
it has no listener. Transports start consuming the connection as soon as it
is up, but the RPC pipeline subscribes to stream slightly later — so the
first inbound frames (e.g. a client-stream's leading chunk on a cold
connection) would be lost. This controller queues them and flushes on the
first listen, then forwards live events straight through.
Buffering applies ONLY while there is no listener: broadcast streams have no per-listener backpressure, so once listened, events pass straight through. Detach and re-attach are handled the same way — events delivered between listeners are queued and flushed when the next one arrives.
Leak-safety:
- the pending queue is cleared on close;
- it never grows past maxPendingEvents events, NOR past maxPendingBytes when a sizeOf is supplied. Hitting either bound while still unlistened — a producer feeding a controller nobody consumes, i.e. an abandoned transport — drops further events and fires onOverflow once.
BOTH dimensions are required. A bound on events says nothing about
bytes, and the neighbouring RpcSecurityPolicy.maxMessageLengthBytes bounds
ONE message at 16 MiB by default — so a count-only bound of 4096 admits up to
64 GiB of payload while appearing to keep memory bounded.
Implements StreamSink, the writable half of a StreamController, so it can
stand in for one as a sink while exposing stream as a controller does. It
deliberately does NOT implement the whole of StreamController, whose
settable onListen this type uses internally to flush the buffer: exposing
it would let a caller override the flush and break the invariant.
- Implemented types
-
- StreamSink<
T>
- StreamSink<
Constructors
- RpcBufferedBroadcastController({int maxPendingEvents = 4096, int maxPendingBytes = 16 * 1024 * 1024, int sizeOf(T event)?, void onOverflow()?, bool sync = false})
- Creates a buffered broadcast controller.
Properties
-
done
→ Future<
void> -
Completes when this sink is closed.
no setteroverride
- hashCode → int
-
The hash code for this object.
no setterinherited
- hasListener → bool
-
Whether at least one subscriber is currently attached.
no setter
- isClosed → bool
-
Whether this controller has been closed.
no setter
- maxPendingBytes → int
-
Upper bound on the total size of those events, when sizeOf is given.
final
- maxPendingEvents → int
-
Upper bound on events buffered while no listener is attached.
final
- onOverflow → void Function()?
-
Called once when either bound is first exceeded (diagnostics).
final
- pendingCount → int
-
Number of events currently buffered awaiting a listener (diagnostics).
no setter
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- sizeOf → int Function(T event)?
-
Weighs a pending event, in bytes. Null disables the byte bound.
final
-
stream
→ Stream<
T> -
The broadcast stream consumers listen to.
no setter
Methods
-
add(
T event) → void -
Adds a data event: delivered immediately when listened, else queued.
override
-
addError(
Object error, [StackTrace? stackTrace]) → void -
Adds an error event, preserving order relative to add.
override
-
addStream(
Stream< T> source, {bool? cancelOnError}) → Future<void> -
Pipes
sourceinto this sink (events and errors), completing when the source is done. Same buffering semantics as add/addError.override -
close(
) → Future< void> -
Clears the buffer and closes the underlying controller.
override
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited