reifydb_core/key/
ringbuffer.rs1use reifydb_codec::key::{deserializer::KeyDeserializer, encoded::EncodedKey};
5use reifydb_macro::KeyCodec;
6use reifydb_value::value::Value;
7
8use super::KeyTag;
9use crate::{
10 interface::catalog::{id::RingBufferId, object::ObjectId, storage::StorageId},
11 key::{
12 any::{Field, KeyFields, RawEncoding, Width, encode_values},
13 bound::{TaggedKeyBoundRange, object_fields},
14 catalog::{KeyDeserializerCatalogExt, KeySerializerCatalogExt},
15 },
16};
17
18#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
19#[key(tag = RingBuffer)]
20pub struct RingBufferKey {
21 pub ringbuffer: RingBufferId,
22}
23
24impl RingBufferKey {
25 pub fn new(ringbuffer: RingBufferId) -> Self {
26 Self {
27 ringbuffer,
28 }
29 }
30
31 pub fn encoded(ringbuffer: impl Into<RingBufferId>) -> EncodedKey {
32 Self::new(ringbuffer.into()).encode()
33 }
34
35 pub fn full_scan() -> TaggedKeyBoundRange {
36 TaggedKeyBoundRange::kind(Self::TAG)
37 }
38}
39
40#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
41#[key(tag = RingBufferMetadata)]
42pub struct RingBufferMetadataKey {
43 pub storage: StorageId,
44 pub encoded_partition: Vec<u8>,
45}
46
47impl RingBufferMetadataKey {
48 pub fn new(storage: impl Into<StorageId>) -> Self {
49 Self {
50 storage: storage.into(),
51 encoded_partition: Vec::new(),
52 }
53 }
54
55 pub fn encoded(storage: impl Into<StorageId>) -> EncodedKey {
56 Self::new(storage).encode()
57 }
58
59 pub fn partition(storage: impl Into<StorageId>, partition_values: Vec<Value>) -> Self {
60 Self {
61 storage: storage.into(),
62 encoded_partition: encode_values(&partition_values).as_slice().to_vec(),
63 }
64 }
65
66 pub fn encoded_partition(storage: impl Into<StorageId>, partition_values: Vec<Value>) -> EncodedKey {
67 Self::partition(storage, partition_values).encode()
68 }
69
70 pub fn partition_values(&self) -> Option<Vec<Value>> {
71 let mut de = KeyDeserializer::from_bytes(&self.encoded_partition);
72 let mut partition_values = Vec::new();
73 while !de.is_empty() {
74 partition_values.push(de.read_value().ok()?);
75 }
76 Some(partition_values)
77 }
78
79 pub fn full_scan_for_storage(storage: impl Into<StorageId>) -> TaggedKeyBoundRange {
80 TaggedKeyBoundRange::prefix(Self::TAG, object_fields(ObjectId::from(storage.into())))
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use std::ops::RangeBounds;
87
88 use reifydb_codec::key::serializer::KeySerializer;
89
90 use super::*;
91 use crate::interface::catalog::id::ViewId;
92
93 #[test]
94 fn test_metadata_key_encode_decode_roundtrip() {
95 let key = RingBufferMetadataKey::encoded_partition(
96 RingBufferId(42),
97 vec![Value::Utf8("east".to_string())],
98 );
99 let mut de = KeyDeserializer::from_bytes(key.as_slice());
100 let _ = (de.read_u8(), de.read_object_id());
101 let value = de.read_value().unwrap();
102 assert_eq!(value, Value::Utf8("east".to_string()));
103 }
104
105 #[test]
106 fn test_metadata_key_encode_decode_multiple() {
107 let key = RingBufferMetadataKey::encoded_partition(
108 RingBufferId(7),
109 vec![Value::Utf8("us".to_string()), Value::Uint8(42)],
110 );
111 let mut de = KeyDeserializer::from_bytes(key.as_slice());
112 let _ = (de.read_u8(), de.read_object_id());
113 assert_eq!(de.read_value().unwrap(), Value::Utf8("us".to_string()));
114 assert_eq!(de.read_value().unwrap(), Value::Uint8(42));
115 }
116
117 #[test]
118 fn test_metadata_key_roundtrip_ringbuffer() {
119 let key = RingBufferMetadataKey::partition(
121 StorageId::RingBuffer(RingBufferId(42)),
122 vec![Value::Utf8("east".to_string())],
123 );
124 assert_eq!(RingBufferMetadataKey::decode(&key.encode()).unwrap(), key);
125 }
126
127 #[test]
128 fn test_metadata_key_roundtrip_view() {
129 let key = RingBufferMetadataKey::partition(
131 StorageId::View(ViewId(42)),
132 vec![Value::Utf8("east".to_string())],
133 );
134 assert_eq!(RingBufferMetadataKey::decode(&key.encode()).unwrap(), key);
135 }
136
137 #[test]
138 fn test_full_scan_for_storage_excludes_a_view_with_the_same_id() {
139 let range = RingBufferMetadataKey::full_scan_for_storage(RingBufferId(42)).encode();
141 let ringbuffer = RingBufferMetadataKey::encoded(RingBufferId(42));
142 let view = RingBufferMetadataKey::encoded(ViewId(42));
143 assert!(range.contains(&ringbuffer));
144 assert!(!range.contains(&view));
145 }
146
147 #[test]
148 fn test_ring_buffer_key_matches_legacy_byte_layout() {
149 for id in [RingBufferId(0), RingBufferId(1), RingBufferId(u64::MAX)] {
150 let mut legacy = KeySerializer::with_capacity(9);
151 legacy.extend_u8(KeyTag::RingBuffer as u8).extend_u64(id);
152 assert_eq!(legacy.to_encoded_key().as_slice(), RingBufferKey::encoded(id).as_slice());
153 }
154 }
155}