use std::sync::Arc;
use crate::error::Result;
use crate::query::EventKey;
use crate::series::{ColumnDef, TimeSeries};
use super::buffer::EventBuffer;
use super::event::{LiveEvent, LiveSchema};
use super::{LiveStats, OrderingMode};
pub struct SubSeries {
pub(crate) name: String,
pub(crate) schema: Arc<LiveSchema>,
pub(crate) ordering: OrderingMode,
pub(crate) grace_ms: Option<i64>,
pub(crate) max_events: Option<usize>,
pub(crate) max_age_ms: Option<i64>,
pub(crate) buffer: EventBuffer,
pub(crate) ingested: u64,
pub(crate) evicted: u64,
pub(crate) rejected: u64,
pub(crate) chunked: bool,
}
impl std::fmt::Debug for SubSeries {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SubSeries")
.field("name", &self.name)
.field("len", &self.buffer.len())
.finish_non_exhaustive()
}
}
impl SubSeries {
pub(crate) fn new(
name: String,
schema: Arc<LiveSchema>,
ordering: OrderingMode,
grace_ms: Option<i64>,
max_events: Option<usize>,
max_age_ms: Option<i64>,
chunked: bool,
) -> Self {
Self {
name,
buffer: EventBuffer::new(Arc::clone(&schema)),
schema,
ordering,
grace_ms,
max_events,
max_age_ms,
ingested: 0,
evicted: 0,
rejected: 0,
chunked,
}
}
pub(crate) fn retention_count(&self) -> usize {
let len = self.buffer.len();
let mut n = self.max_events.map_or(0, |m| len.saturating_sub(m));
if let (Some(age), Some(latest)) = (self.max_age_ms, self.buffer.back_begin()) {
n = n.max(self.buffer.count_before(latest - age));
}
n
}
pub fn name(&self) -> &str {
&self.name
}
pub fn schema(&self) -> &[ColumnDef] {
&self.schema.columns
}
pub fn ordering(&self) -> OrderingMode {
self.ordering
}
pub fn grace_window_ms(&self) -> Option<i64> {
self.grace_ms
}
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn is_empty(&self) -> bool {
self.buffer.len() == 0
}
pub fn at(&self, index: i64) -> Option<LiveEvent> {
self.buffer.at(index)
}
pub fn first(&self) -> Option<LiveEvent> {
self.buffer.at(0)
}
pub fn last(&self) -> Option<LiveEvent> {
self.buffer.at(-1)
}
pub fn events(&self) -> impl ExactSizeIterator<Item = LiveEvent> + '_ {
self.buffer.iter()
}
pub fn bisect(&self, key: impl Into<EventKey>) -> usize {
self.buffer.bisect(&key.into())
}
pub fn includes_key(&self, key: impl Into<EventKey>) -> bool {
self.buffer.includes_key(&key.into())
}
pub fn at_or_before(&self, key: impl Into<EventKey>) -> Option<LiveEvent> {
self.buffer.at_or_before(&key.into())
}
pub fn at_or_after(&self, key: impl Into<EventKey>) -> Option<LiveEvent> {
self.buffer.at_or_after(&key.into())
}
pub fn find(&self, mut test: impl FnMut(&LiveEvent) -> bool) -> Option<LiveEvent> {
self.buffer.iter().find(|e| test(e))
}
pub fn some(&self, mut test: impl FnMut(&LiveEvent) -> bool) -> bool {
self.buffer.iter().any(|e| test(&e))
}
pub fn every(&self, mut test: impl FnMut(&LiveEvent) -> bool) -> bool {
self.buffer.iter().all(|e| test(&e))
}
pub fn time_range(&self) -> i64 {
self.buffer.time_range()
}
pub fn event_rate(&self) -> f64 {
self.buffer.event_rate()
}
pub fn stats(&self) -> LiveStats {
LiveStats {
ingested: self.ingested,
evicted: self.evicted,
rejected: self.rejected,
length: self.buffer.len(),
earliest: self.buffer.front_begin(),
latest: self.buffer.back_begin(),
}
}
pub fn to_time_series(&self) -> Result<TimeSeries> {
self.buffer
.snapshot("LiveSeries::to_time_series", &self.name)
}
}