1use serde::{Deserialize, Serialize};
2use std::sync::atomic::{AtomicI64, Ordering};
3
4use crate::StorageError;
5
6#[derive(Debug, Serialize, Deserialize)]
11pub struct SequenceDef {
12 pub name: String,
14 #[serde(skip)]
16 current_value: AtomicI64,
17 pub increment: i64,
19 pub min_value: i64,
21 pub max_value: i64,
23 pub cycle: bool,
25 pub start_value: i64,
27}
28
29impl Clone for SequenceDef {
30 fn clone(&self) -> Self {
31 Self {
32 name: self.name.clone(),
33 current_value: AtomicI64::new(self.current_value.load(Ordering::SeqCst)),
34 increment: self.increment,
35 min_value: self.min_value,
36 max_value: self.max_value,
37 cycle: self.cycle,
38 start_value: self.start_value,
39 }
40 }
41}
42
43impl SequenceDef {
44 pub fn new(
45 name: String,
46 start: i64,
47 increment: i64,
48 min_value: i64,
49 max_value: i64,
50 cycle: bool,
51 ) -> Self {
52 Self {
53 name,
54 current_value: AtomicI64::new(start),
55 increment,
56 min_value,
57 max_value,
58 cycle,
59 start_value: start,
60 }
61 }
62
63 pub fn current_value(&self) -> i64 {
65 self.current_value.load(Ordering::SeqCst)
66 }
67
68 pub fn next_value(&self) -> Result<i64, StorageError> {
74 loop {
75 let current = self.current_value.load(Ordering::SeqCst);
76 let next = current + self.increment;
77
78 let new_value = if next > self.max_value {
79 if self.cycle {
80 self.min_value
81 } else {
82 return Err(StorageError::db_error(format!(
83 "Sequence '{}' overflow: value {} would exceed max_value {}",
84 self.name, next, self.max_value
85 )));
86 }
87 } else if next < self.min_value {
88 if self.cycle {
89 self.max_value
90 } else {
91 return Err(StorageError::db_error(format!(
92 "Sequence '{}' underflow: value {} would go below min_value {}",
93 self.name, next, self.min_value
94 )));
95 }
96 } else {
97 next
98 };
99
100 match self.current_value.compare_exchange(
101 current,
102 new_value,
103 Ordering::SeqCst,
104 Ordering::SeqCst,
105 ) {
106 Ok(_) => return Ok(new_value),
107 Err(_) => continue,
109 }
110 }
111 }
112
113 pub fn reset(&self) {
115 self.current_value.store(self.start_value, Ordering::SeqCst);
116 }
117
118 pub fn set_value(&self, value: i64) {
120 self.current_value.store(value, Ordering::SeqCst);
121 }
122}
123
124impl Default for SequenceDef {
125 fn default() -> Self {
126 Self::new(String::new(), 1, 1, i64::MIN, i64::MAX, false)
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_sequence_basic() {
136 let seq = SequenceDef::new("test".into(), 1, 1, 1, 100, false);
137 assert_eq!(seq.current_value(), 1);
138 assert_eq!(seq.next_value().unwrap(), 2);
139 assert_eq!(seq.next_value().unwrap(), 3);
140 assert_eq!(seq.current_value(), 3);
141 }
142
143 #[test]
144 fn test_sequence_increment() {
145 let seq = SequenceDef::new("test".into(), 10, 5, 1, 1000, false);
146 assert_eq!(seq.next_value().unwrap(), 15);
147 assert_eq!(seq.next_value().unwrap(), 20);
148 }
149
150 #[test]
151 fn test_sequence_negative_increment() {
152 let seq = SequenceDef::new("test".into(), 100, -10, 1, 1000, false);
153 assert_eq!(seq.next_value().unwrap(), 90);
154 assert_eq!(seq.next_value().unwrap(), 80);
155 }
156
157 #[test]
158 fn test_sequence_cycle() {
159 let seq = SequenceDef::new("test".into(), 1, 1, 1, 3, true);
160 assert_eq!(seq.next_value().unwrap(), 2);
161 assert_eq!(seq.next_value().unwrap(), 3);
162 assert_eq!(seq.next_value().unwrap(), 1); }
164
165 #[test]
166 fn test_sequence_overflow_no_cycle() {
167 let seq = SequenceDef::new("test".into(), 1, 1, 1, 3, false);
168 assert_eq!(seq.next_value().unwrap(), 2);
169 assert_eq!(seq.next_value().unwrap(), 3);
170 assert!(seq.next_value().is_err());
171 }
172
173 #[test]
174 fn test_sequence_underflow_no_cycle() {
175 let seq = SequenceDef::new("test".into(), 100, -50, 10, 200, false);
176 assert_eq!(seq.next_value().unwrap(), 50);
177 assert!(seq.next_value().is_err());
178 }
179
180 #[test]
181 fn test_sequence_reset() {
182 let seq = SequenceDef::new("test".into(), 1, 1, 1, 100, false);
183 seq.next_value().unwrap();
184 seq.next_value().unwrap();
185 assert_eq!(seq.current_value(), 3);
186 seq.reset();
187 assert_eq!(seq.current_value(), 1);
188 }
189
190 #[test]
191 fn test_sequence_set_value() {
192 let seq = SequenceDef::new("test".into(), 1, 1, 1, 100, false);
193 seq.set_value(50);
194 assert_eq!(seq.current_value(), 50);
195 assert_eq!(seq.next_value().unwrap(), 51);
196 }
197
198 #[test]
199 fn test_sequence_concurrent_next_value() {
200 use std::sync::Arc;
201 use std::thread;
202
203 let seq = Arc::new(SequenceDef::new("test".into(), 0, 1, 0, 10000, false));
204 let mut handles = vec![];
205
206 for _ in 0..10 {
207 let seq = Arc::clone(&seq);
208 handles.push(thread::spawn(move || {
209 for _ in 0..1000 {
210 seq.next_value().unwrap();
211 }
212 }));
213 }
214
215 for h in handles {
216 h.join().unwrap();
217 }
218
219 assert_eq!(seq.current_value(), 10000);
220 }
221}