Skip to main content

infinispan_fork/request/
counters.rs

1use crate::request::{Method, Request, ToHttpRequest};
2use serde::{Deserialize, Serialize};
3use serde_json::json;
4use std::collections::HashMap;
5
6const COUNTERS_ENDPOINT: &str = "/rest/v2/counters";
7
8type CounterVal = i64;
9
10#[derive(Debug, Serialize, Deserialize)]
11enum Counter {
12    #[serde(rename = "weak-counter")]
13    Weak(WeakCounter),
14    #[serde(rename = "strong-counter")]
15    Strong(StrongCounter),
16}
17
18#[derive(Debug, Serialize, Deserialize)]
19struct WeakCounter {
20    #[serde(rename = "initial-value", skip_serializing_if = "Option::is_none")]
21    initial_value: Option<CounterVal>,
22}
23
24impl WeakCounter {
25    pub fn set_value(&mut self, counter_val: CounterVal) {
26        self.initial_value = Some(counter_val);
27    }
28}
29
30#[derive(Debug, Serialize, Deserialize)]
31struct StrongCounter {
32    #[serde(rename = "initial-value", skip_serializing_if = "Option::is_none")]
33    initial_value: Option<CounterVal>,
34}
35
36impl StrongCounter {
37    pub fn set_value(&mut self, counter_val: CounterVal) {
38        self.initial_value = Some(counter_val);
39    }
40}
41
42#[derive(Debug, Copy, Clone)]
43pub enum CounterType {
44    Weak,
45    Strong,
46}
47
48#[derive(Debug)]
49pub struct CreateCounterReq {
50    name: String,
51    counter: Counter,
52}
53
54#[derive(Debug)]
55enum Action {
56    Add {
57        delta: CounterVal,
58    },
59    Increment,
60    Decrement,
61    Reset,
62    CompareAndSet {
63        expect: CounterVal,
64        update: CounterVal,
65    },
66    CompareAndSwap {
67        expect: CounterVal,
68        update: CounterVal,
69    },
70}
71
72impl Action {
73    pub fn to_query_args(&self) -> String {
74        match self {
75            Action::Add { delta } => {
76                format!("action=add&delta={}", delta)
77            }
78            Action::Increment => "action=increment".to_string(),
79            Action::Decrement => "action=decrement".to_string(),
80            Action::Reset => "action=reset".to_string(),
81            Action::CompareAndSet { expect, update } => {
82                format!("action=compareAndSet&expect={}&update={}", expect, update)
83            }
84            Action::CompareAndSwap { expect, update } => {
85                format!("action=compareAndSwap&expect={}&update={}", expect, update)
86            }
87        }
88    }
89}
90
91impl CreateCounterReq {
92    pub fn new(name: impl Into<String>, counter_type: CounterType) -> Self {
93        let counter = match counter_type {
94            CounterType::Weak => Counter::Weak(WeakCounter {
95                initial_value: None,
96            }),
97            CounterType::Strong => Counter::Strong(StrongCounter {
98                initial_value: None,
99            }),
100        };
101
102        Self {
103            name: name.into(),
104            counter,
105        }
106    }
107
108    pub fn with_value(mut self, value: CounterVal) -> Self {
109        match &mut self.counter {
110            Counter::Weak(counter) => counter.set_value(value),
111            Counter::Strong(counter) => counter.set_value(value),
112        }
113
114        self
115    }
116}
117
118impl From<&CreateCounterReq> for Request {
119    fn from(request: &CreateCounterReq) -> Self {
120        Self::new(
121            Method::Post,
122            counter_path(&request.name),
123            HashMap::new(),
124            Some(json!(request.counter).to_string()),
125        )
126    }
127}
128
129impl ToHttpRequest for CreateCounterReq {
130    fn to_http_req(&self, base_url: impl AsRef<str>) -> http::Request<String> {
131        Request::from(self).to_http_req(base_url)
132    }
133}
134
135#[derive(Debug)]
136pub struct IncrementCounterReq {
137    name: String,
138    delta: Option<CounterVal>,
139}
140
141impl IncrementCounterReq {
142    pub fn new(name: impl Into<String>) -> Self {
143        Self {
144            name: name.into(),
145            delta: None,
146        }
147    }
148
149    pub fn by(mut self, delta: CounterVal) -> Self {
150        self.delta = Some(delta);
151        self
152    }
153
154    fn action(&self) -> Action {
155        match self.delta {
156            Some(delta) => Action::Add { delta },
157            None => Action::Increment,
158        }
159    }
160}
161
162impl From<&IncrementCounterReq> for Request {
163    fn from(request: &IncrementCounterReq) -> Self {
164        Self::new(
165            Method::Post,
166            counter_path_with_action(&request.name, &request.action()),
167            HashMap::new(),
168            None,
169        )
170    }
171}
172
173impl ToHttpRequest for IncrementCounterReq {
174    fn to_http_req(&self, base_url: impl AsRef<str>) -> http::Request<String> {
175        Request::from(self).to_http_req(base_url)
176    }
177}
178
179pub fn create_weak(name: impl Into<String>) -> CreateCounterReq {
180    CreateCounterReq::new(name, CounterType::Weak)
181}
182
183pub fn create_strong(name: impl Into<String>) -> CreateCounterReq {
184    CreateCounterReq::new(name, CounterType::Strong)
185}
186
187pub fn get(name: impl AsRef<str>) -> Request {
188    Request::new(Method::Get, counter_path(name), HashMap::new(), None)
189}
190
191pub fn get_config(name: impl AsRef<str>) -> Request {
192    Request::new(Method::Get, counter_config_path(name), HashMap::new(), None)
193}
194
195pub fn increment(name: impl Into<String>) -> IncrementCounterReq {
196    IncrementCounterReq::new(name)
197}
198
199pub fn decrement(name: impl AsRef<str>) -> Request {
200    Request::new(
201        Method::Post,
202        counter_path_with_action(name, &Action::Decrement),
203        HashMap::new(),
204        None,
205    )
206}
207
208pub fn reset(name: impl AsRef<str>) -> Request {
209    Request::new(
210        Method::Post,
211        counter_path_with_action(name, &Action::Reset),
212        HashMap::new(),
213        None,
214    )
215}
216
217pub fn delete(name: impl AsRef<str>) -> Request {
218    Request::new(Method::Delete, counter_path(name), HashMap::new(), None)
219}
220
221pub fn compare_and_set(name: impl AsRef<str>, expect: CounterVal, update: CounterVal) -> Request {
222    Request::new(
223        Method::Post,
224        counter_path_with_action(name, &Action::CompareAndSet { expect, update }),
225        HashMap::new(),
226        None,
227    )
228}
229
230pub fn compare_and_swap(name: impl AsRef<str>, expect: CounterVal, update: CounterVal) -> Request {
231    Request::new(
232        Method::Post,
233        counter_path_with_action(name, &Action::CompareAndSwap { expect, update }),
234        HashMap::new(),
235        None,
236    )
237}
238
239pub fn list() -> Request {
240    Request::new(Method::Get, COUNTERS_ENDPOINT, HashMap::new(), None)
241}
242
243fn counter_path(name: impl AsRef<str>) -> String {
244    format!(
245        "/{counters_endpoint}/{counter_name}",
246        counters_endpoint = COUNTERS_ENDPOINT,
247        counter_name = urlencoding::encode(name.as_ref())
248    )
249}
250
251fn counter_path_with_action(name: impl AsRef<str>, action: &Action) -> String {
252    format!("{}?{}", counter_path(name), action.to_query_args())
253}
254
255fn counter_config_path(name: impl AsRef<str>) -> String {
256    format!("{}/config", counter_path(name))
257}