pub struct SubscriptionBuffer { /* private fields */ }Expand description
Egress buffer of one subscription. It applies the subscription’s [Backpressure] policy.
The buffer never blocks and never waits. It is a plain in-memory queue (or single slot), not
thread-safe by itself. BackpressureManager owns many of them, and the emitter wraps the manager in a
lock.
§Examples
use brokapi_core::{
Backpressure, Event, InstrumentId, InstrumentKey, NativeId, SubscriptionId,
};
use brokapi_runtime::{PushResult, SubscriptionBuffer};
let sber = InstrumentId::new(
InstrumentKey::new("SBER", "TQBR"),
NativeId::TickerClass { ticker: "SBER".into(), class_code: "TQBR".into() },
);
let mut buf = SubscriptionBuffer::new(SubscriptionId::new(1), sber, Backpressure::DropNewest { cap: 1 });
assert_eq!(buf.try_push(Event::Balances(vec![])), PushResult::Delivered);
// The buffer holds one event. The next one is thrown away and counted.
assert_eq!(buf.try_push(Event::Balances(vec![])), PushResult::DroppedNewest);
assert_eq!(buf.dropped(), 1);
assert_eq!(buf.drain().len(), 1);Implementations§
Source§impl SubscriptionBuffer
impl SubscriptionBuffer
Sourcepub fn new(
sub: SubscriptionId,
instrument: InstrumentId,
policy: Backpressure,
) -> Self
pub fn new( sub: SubscriptionId, instrument: InstrumentId, policy: Backpressure, ) -> Self
Creates an empty buffer for a subscription with the given policy.
A cap of 0 in Lossless or DropNewest makes a buffer that accepts nothing: the first
event already overflows (or is dropped).
Sourcepub fn instrument(&self) -> &InstrumentId
pub fn instrument(&self) -> &InstrumentId
The instrument of the subscription, as given to new.
Sourcepub fn is_overflowed(&self) -> bool
pub fn is_overflowed(&self) -> bool
Whether a Lossless buffer has overflowed and not been reset yet.
Sourcepub fn conflated(&self) -> u64
pub fn conflated(&self) -> u64
How many events a Conflate buffer replaced before they were taken.
Sourcepub fn try_push(&mut self, event: Event) -> PushResult
pub fn try_push(&mut self, event: Event) -> PushResult
Offers an event to the buffer without blocking.
Conflate: the event becomes the latest value of its kind (an order book, a quote, a portfolio and so on: one slot per kind). A value of the same kind that was still waiting is replaced and counted inconflated. Result:PushResult::Conflated.Lossless { cap }: stored while fewer thancapevents wait. The first event that finds the buffer full is not stored, the buffer is flagged overflowed and the result isPushResult::Overflow. After that every event getsOverflowand is not stored.DropNewest { cap }: stored while fewer thancapevents wait. Otherwise the new event is thrown away and counted indropped.
Why Lossless stops for good: it is used for events that must not have a hole (orders,
fills). Once one is lost, later events would hide the gap, so the consumer must be told and
re-read the state.
§Examples
use brokapi_core::{Backpressure, Event, InstrumentId, InstrumentKey, NativeId, SubscriptionId};
use brokapi_runtime::{PushResult, SubscriptionBuffer};
let sber = InstrumentId::new(
InstrumentKey::new("SBER", "TQBR"),
NativeId::TickerClass { ticker: "SBER".into(), class_code: "TQBR".into() },
);
let mut buf = SubscriptionBuffer::new(SubscriptionId::new(1), sber, Backpressure::Lossless { cap: 1 });
assert_eq!(buf.try_push(Event::Balances(vec![])), PushResult::Delivered);
assert_eq!(buf.try_push(Event::Balances(vec![])), PushResult::Overflow);
assert!(buf.is_overflowed());
// Even after the consumer takes the stored event, the buffer stays overflowed.
assert_eq!(buf.drain().len(), 1);
assert_eq!(buf.try_push(Event::Balances(vec![])), PushResult::Overflow);Sourcepub fn overflow_event(&self, lost_from: UnixNanos) -> Event
pub fn overflow_event(&self, lost_from: UnixNanos) -> Event
Builds the [Event::Overflow] notice for this subscription.
lost_from is the wall-clock time from which events may be missing. The buffer does not
send the notice itself, the owner does.
§Examples
use brokapi_core::{Backpressure, Event, InstrumentId, InstrumentKey, NativeId, SubscriptionId, UnixNanos};
use brokapi_runtime::SubscriptionBuffer;
let sber = InstrumentId::new(
InstrumentKey::new("SBER", "TQBR"),
NativeId::TickerClass { ticker: "SBER".into(), class_code: "TQBR".into() },
);
let buf = SubscriptionBuffer::new(SubscriptionId::new(7), sber, Backpressure::Lossless { cap: 1 });
let notice = buf.overflow_event(UnixNanos::from_nanos(5));
assert!(matches!(notice, Event::Overflow { sub, .. } if sub == SubscriptionId::new(7)));Sourcepub fn drain(&mut self) -> Vec<Event>
pub fn drain(&mut self) -> Vec<Event>
Takes everything out of the buffer: the latest conflated value first, then the queue in arrival order.
Draining does not clear the overflowed flag. Use BackpressureManager::clear_degraded for that.