1use mz_repr::Timestamp;
13use timely::progress::Antichain;
14
15mod iceberg;
16mod kafka;
17
18fn overcompacted_error(
22 name: &str,
23 as_of: &Antichain<Timestamp>,
24 resume_upper: &Antichain<Timestamp>,
25 remedy: &str,
26) -> String {
27 let fmt = |f: &Antichain<Timestamp>| match f.as_option() {
28 Some(t) => t.to_string(),
29 None => "[]".to_string(),
30 };
31 let gap = match (as_of.as_option(), resume_upper.as_option()) {
32 (Some(as_of), Some(upper)) => {
33 let secs = u64::from(*as_of).saturating_sub(u64::from(*upper)) / 1000;
34 let (h, m, s) = (secs / 3600, secs % 3600 / 60, secs % 60);
35 format!(" (gap {h}h{m:02}m{s:02}s)")
36 }
37 _ => String::new(),
38 };
39 format!(
40 "sink {name} cannot resume: input compacted to {}, past last committed upper {}{gap}; \
41 data in that range is unrecoverable, {remedy}",
42 fmt(as_of),
43 fmt(resume_upper),
44 )
45}