1use std::time::{SystemTime, UNIX_EPOCH};
14
15use thiserror::Error;
16
17use crate::registry::CollectionId;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
21pub enum CompressionProfile {
22 None,
24 Dictionary,
26 #[default]
28 Balanced,
29 Compact,
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Default)]
35pub struct CollectionConfig {
36 pub compression: CompressionProfile,
38}
39
40#[derive(Debug, Clone, PartialEq, Eq)]
42pub struct Collection {
43 name: String,
44 id: CollectionId,
45 created_at: u64,
46 compression: CompressionProfile,
47 doc_count: u64,
48}
49
50impl Collection {
51 #[must_use]
53 pub fn new(name: String, id: CollectionId, config: CollectionConfig) -> Self {
54 Self {
55 name,
56 id,
57 created_at: current_unix_seconds(),
58 compression: config.compression,
59 doc_count: 0,
60 }
61 }
62
63 #[must_use]
65 pub fn name(&self) -> &str {
66 &self.name
67 }
68
69 #[must_use]
71 pub fn id(&self) -> CollectionId {
72 self.id
73 }
74
75 #[must_use]
77 pub fn created_at(&self) -> u64 {
78 self.created_at
79 }
80
81 #[must_use]
83 pub fn compression(&self) -> CompressionProfile {
84 self.compression
85 }
86
87 #[must_use]
89 pub fn doc_count(&self) -> u64 {
90 self.doc_count
91 }
92
93 pub fn increment_doc_count(&mut self) {
95 self.doc_count = self.doc_count.saturating_add(1);
96 }
97
98 pub fn decrement_doc_count(&mut self) {
100 self.doc_count = self.doc_count.saturating_sub(1);
101 }
102}
103
104#[derive(Debug, Error, PartialEq, Eq)]
106pub enum CollectionError {
107 #[error("collection '{0}' already exists")]
109 AlreadyExists(String),
110}
111
112fn current_unix_seconds() -> u64 {
113 SystemTime::now()
114 .duration_since(UNIX_EPOCH)
115 .map_or(0, |duration| duration.as_secs())
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn collection_doc_count_tracks_mutations() {
124 let mut collection = Collection::new(
125 "users".to_string(),
126 7,
127 CollectionConfig {
128 compression: CompressionProfile::Dictionary,
129 },
130 );
131
132 assert_eq!(collection.doc_count(), 0);
133 collection.increment_doc_count();
134 collection.increment_doc_count();
135 assert_eq!(collection.doc_count(), 2);
136 collection.decrement_doc_count();
137 assert_eq!(collection.doc_count(), 1);
138 collection.decrement_doc_count();
139 collection.decrement_doc_count();
140 assert_eq!(collection.doc_count(), 0);
141 assert_eq!(collection.name(), "users");
142 assert_eq!(collection.id(), 7);
143 assert_eq!(collection.compression(), CompressionProfile::Dictionary);
144 }
145}