crabka_replicator/
offset_sync_store.rs1use std::collections::BTreeMap;
6
7use crate::mm2::OffsetSync;
8
9#[derive(Default)]
12pub struct OffsetSyncStore {
13 syncs: BTreeMap<(String, i32), BTreeMap<i64, i64>>,
15}
16
17impl OffsetSyncStore {
18 pub fn ingest(&mut self, s: OffsetSync) {
21 self.syncs
22 .entry((s.topic, s.partition))
23 .or_default()
24 .insert(s.upstream, s.downstream);
25 }
26
27 #[must_use]
33 pub fn translate(&self, topic: &str, partition: i32, committed: i64) -> Option<i64> {
34 let m = self.syncs.get(&(topic.to_string(), partition))?;
35 let (&up, &down) = m.range(..=committed).next_back()?;
36 Some(down + (committed - up))
37 }
38}
39
40#[cfg(test)]
41mod tests {
42 use assert2::assert;
43
44 use super::*;
45 use crate::mm2::OffsetSync;
46
47 #[test]
48 fn translates_at_or_before_nearest_sync() {
49 let mut s = OffsetSyncStore::default();
50 s.ingest(OffsetSync {
51 topic: "orders".into(),
52 partition: 0,
53 upstream: 100,
54 downstream: 70,
55 });
56 s.ingest(OffsetSync {
57 topic: "orders".into(),
58 partition: 0,
59 upstream: 200,
60 downstream: 165,
61 });
62 assert!(s.translate("orders", 0, 250) == Some(215)); assert!(s.translate("orders", 0, 150) == Some(120)); assert!(s.translate("orders", 0, 50) == None); assert!(s.translate("orders", 9, 100) == None); }
67}