use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
pub struct SsTableStats {
pub generation: u64,
pub bytes: u64,
#[serde(default)]
pub rows: Option<u64>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct MemtableStats {
pub generation: u64,
pub rows: u64,
pub bytes: u64,
pub batches: u64,
pub indexes: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct TableShardStats {
pub shard_id: String,
pub status: String,
pub writer_epoch: u64,
pub manifest_version: u64,
pub current_generation: u64,
pub replay_after_wal_entry_position: u64,
pub wal_entry_position_last_seen: u64,
pub sstables: Vec<SsTableStats>,
pub compacting: bool,
#[serde(default)]
pub memtables: Option<Vec<MemtableStats>>,
}
impl TableShardStats {
pub(crate) fn newest_sstable_generation(&self) -> Option<u64> {
self.sstables.iter().map(|g| g.generation).max()
}
pub(crate) fn outstanding_sstables(&self, target: u64) -> usize {
self.sstables
.iter()
.filter(|g| g.generation <= target)
.count()
}
}
#[derive(Debug, Clone, Deserialize)]
pub struct RTEStats {
pub table_shards: Vec<TableShardStats>,
}
#[derive(Debug, Deserialize)]
pub(crate) struct GetRTEStatsResponse {
#[serde(default)]
pub rte_stats: Option<RTEStats>,
}
#[cfg(test)]
mod tests {
use super::*;
fn table_shard(shard: &str, sstables: &[u64], compacting: bool) -> TableShardStats {
TableShardStats {
shard_id: shard.into(),
status: "Active".into(),
writer_epoch: 1,
manifest_version: 1,
current_generation: sstables.iter().max().copied().unwrap_or(0) + 1,
replay_after_wal_entry_position: 0,
wal_entry_position_last_seen: 0,
sstables: sstables
.iter()
.map(|g| SsTableStats {
generation: *g,
bytes: 1,
rows: None,
})
.collect(),
compacting,
memtables: None,
}
}
#[test]
fn newer_sstables_do_not_extend_the_target() {
let start = table_shard("b0", &[7, 8], false);
let target = start
.newest_sstable_generation()
.expect("the SSTable tier is non-empty");
assert_eq!(target, 8);
let later = table_shard("b0", &[9, 10], false);
assert_eq!(
later.outstanding_sstables(target),
0,
"sstables above the target are somebody else's problem"
);
assert_eq!(
table_shard("b0", &[8, 9], false).outstanding_sstables(target),
1
);
}
#[test]
fn progress_is_measured_in_sstables() {
let target = 3;
let counts: Vec<usize> = [&[1u64, 2, 3][..], &[2, 3][..], &[3][..], &[][..]]
.iter()
.map(|gens| table_shard("b0", gens, false).outstanding_sstables(target))
.collect();
assert_eq!(counts, vec![3, 2, 1, 0]);
}
#[test]
fn an_empty_sstable_tier_has_no_target() {
assert!(
table_shard("b0", &[], false)
.newest_sstable_generation()
.is_none()
);
}
}