/// S3 key layout for shipped WAL segments. /// /// Format: `{cluster_id}/{topic}/{partition}/{base_offset:020}-{end_offset:020}.sqseg` /// /// The 020 zero-padding ensures lexicographic ordering matches offset ordering. pub fn segment_key( cluster_id: &str, topic: &str, partition: u32, base_offset: u64, end_offset: u64, ) -> String { format!( "{}/{}/{}/{:020}-{:020}.sqseg", cluster_id, topic, partition, base_offset, end_offset ) } /// Parse a segment key back into its components. /// Returns (cluster_id, topic, partition, base_offset, end_offset). pub fn parse_segment_key(key: &str) -> Option<(String, String, u32, u64, u64)> { let parts: Vec<&str> = key.split('/').collect(); if parts.len() != 4 { return None; } let cluster_id = parts[0].to_string(); let topic = parts[1].to_string(); let partition: u32 = parts[2].parse().ok()?; let filename = parts[3].strip_suffix(".sqseg")?; let offsets: Vec<&str> = filename.split('-').collect(); if offsets.len() != 2 { return None; } let base_offset: u64 = offsets[0].parse().ok()?; let end_offset: u64 = offsets[1].parse().ok()?; Some((cluster_id, topic, partition, base_offset, end_offset)) } /// S3 key prefix for listing segments of a topic-partition. pub fn topic_partition_prefix(cluster_id: &str, topic: &str, partition: u32) -> String { format!("{}/{}/{}/", cluster_id, topic, partition) } #[cfg(test)] mod tests { use super::*; #[test] fn test_segment_key_format() { let key = segment_key("cluster-1", "orders", 0, 0, 999); assert_eq!( key, "cluster-1/orders/0/00000000000000000000-00000000000000000999.sqseg" ); } #[test] fn test_segment_key_lexicographic_order() { let k1 = segment_key("c", "t", 0, 0, 999); let k2 = segment_key("c", "t", 0, 1000, 1999); let k3 = segment_key("c", "t", 0, 2000, 2999); assert!(k1 < k2); assert!(k2 < k3); } #[test] fn test_parse_segment_key() { let key = segment_key("cluster-1", "orders", 2, 1000, 1999); let parsed = parse_segment_key(&key).unwrap(); assert_eq!(parsed.0, "cluster-1"); assert_eq!(parsed.1, "orders"); assert_eq!(parsed.2, 2); assert_eq!(parsed.3, 1000); assert_eq!(parsed.4, 1999); } #[test] fn test_parse_invalid_key() { assert!(parse_segment_key("invalid").is_none()); assert!(parse_segment_key("a/b/c").is_none()); assert!(parse_segment_key("a/b/c/d.txt").is_none()); } #[test] fn test_topic_partition_prefix() { let prefix = topic_partition_prefix("cluster-1", "orders", 0); assert_eq!(prefix, "cluster-1/orders/0/"); } }