picodata_plugin/internal/
types.rs

1use abi_stable::std_types::{RString, RVec};
2use abi_stable::StableAbi;
3use tarantool::session::UserId;
4use tarantool::space::{SpaceId, UpdateOps};
5use tarantool::tuple::{ToTupleBuffer, Tuple};
6
7/// *For internal usage, don't use it in your code*.
8#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
9#[repr(u8)]
10pub enum DmlInner {
11    Insert {
12        table: SpaceId,
13        tuple: RVec<u8>,
14        initiator: UserId,
15    },
16    Replace {
17        table: SpaceId,
18        tuple: RVec<u8>,
19        initiator: UserId,
20    },
21    Update {
22        table: SpaceId,
23        key: RVec<u8>,
24        ops: RVec<RVec<u8>>,
25        initiator: UserId,
26    },
27    Delete {
28        table: SpaceId,
29        key: RVec<u8>,
30        initiator: UserId,
31    },
32}
33
34/// Cluster-wide data modification operation.
35#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
36#[repr(C)]
37pub struct Dml(
38    /// `DmlInner` is public just for internal purposes - implement
39    /// `From<DmlInner>` trait for `picodata::traft::op::Dml` at `picodata` side.
40    ///
41    /// *You should not use it explicitly*.
42    pub DmlInner,
43);
44
45impl Dml {
46    /// Insert operation.
47    pub fn insert(space_id: SpaceId, tuple: Tuple, initiator: UserId) -> Self {
48        Dml(DmlInner::Insert {
49            table: space_id,
50            tuple: RVec::from(tuple.to_vec()),
51            initiator,
52        })
53    }
54
55    /// Replace operation.
56    pub fn replace(space_id: SpaceId, tuple: Tuple, initiator: UserId) -> Self {
57        Dml(DmlInner::Replace {
58            table: space_id,
59            tuple: RVec::from(tuple.to_vec()),
60            initiator,
61        })
62    }
63
64    /// Update operation.
65    pub fn update(
66        space_id: SpaceId,
67        key: &impl ToTupleBuffer,
68        ops: UpdateOps,
69        initiator: UserId,
70    ) -> tarantool::Result<Self> {
71        let tb = key.to_tuple_buffer()?;
72        let raw_key = Vec::from(tb);
73
74        let ops: RVec<_> = ops
75            .into_inner()
76            .into_iter()
77            .map(|tb| RVec::from(Vec::from(tb)))
78            .collect();
79
80        Ok(Dml(DmlInner::Update {
81            table: space_id,
82            key: RVec::from(raw_key),
83            ops,
84            initiator,
85        }))
86    }
87
88    /// Delete operation.
89    pub fn delete(
90        space_id: SpaceId,
91        key: &impl ToTupleBuffer,
92        initiator: UserId,
93    ) -> tarantool::Result<Self> {
94        let tb = key.to_tuple_buffer()?;
95        let raw_key = Vec::from(tb);
96
97        Ok(Dml(DmlInner::Delete {
98            table: space_id,
99            key: RVec::from(raw_key),
100            initiator,
101        }))
102    }
103}
104
105/// *For internal usage, don't use it in your code*.
106#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
107#[repr(u8)]
108pub enum OpInner {
109    Nop,
110    Dml(Dml),
111    BatchDml(RVec<Dml>),
112}
113
114/// RAFT operation.
115#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
116#[repr(C)]
117pub struct Op(
118    /// `OpInner` is public just for internal purposes - implement
119    /// `From<OpInner>` trait for `picodata::traft::op::Op` at `picodata` side.
120    ///
121    /// *You should not use it explicitly*.
122    pub OpInner,
123);
124
125impl Op {
126    /// Nop - empty raft record.
127    pub fn nop() -> Self {
128        Self(OpInner::Nop)
129    }
130
131    /// Dml request.
132    pub fn dml(dml: Dml) -> Self {
133        Self(OpInner::Dml(dml))
134    }
135
136    /// Batch Dml request.
137    pub fn dml_batch(batch: Vec<Dml>) -> Self {
138        Self(OpInner::BatchDml(RVec::from(batch)))
139    }
140}
141
142#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
143#[repr(C)]
144pub struct Bound {
145    pub is_included: bool,
146    pub key: RVec<u8>,
147}
148
149impl Bound {
150    pub fn new(is_included: bool, key: &impl ToTupleBuffer) -> tarantool::Result<Self> {
151        let tb = key.to_tuple_buffer()?;
152        let raw_key = Vec::from(tb);
153
154        Ok(Self {
155            is_included,
156            key: RVec::from(raw_key),
157        })
158    }
159}
160
161#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
162#[repr(C)]
163pub struct Range {
164    pub table: SpaceId,
165    pub key_min: Bound,
166    pub key_max: Bound,
167}
168
169#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
170#[repr(C)]
171pub struct Predicate {
172    pub index: u64,
173    pub term: u64,
174    pub ranges: RVec<Range>,
175}
176
177impl Predicate {
178    pub fn new(index: u64, term: u64, ranges: Vec<Range>) -> Self {
179        Self {
180            index,
181            term,
182            ranges: RVec::from(ranges),
183        }
184    }
185}
186
187::tarantool::define_str_enum! {
188    /// Activity state of an instance.
189    #[derive(Default, StableAbi)]
190    #[repr(C)]
191    pub enum StateVariant {
192        /// Instance has gracefully shut down or has not been started yet.
193        #[default]
194        Offline = "Offline",
195        /// Instance is active and is handling requests.
196        Online = "Online",
197        /// Instance has permanently removed from cluster.
198        Expelled = "Expelled",
199    }
200}
201
202#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
203#[repr(C)]
204pub struct State {
205    variant: StateVariant,
206    incarnation: u64,
207}
208
209impl State {
210    pub fn new(variant: StateVariant, incarnation: u64) -> Self {
211        Self {
212            variant,
213            incarnation,
214        }
215    }
216
217    /// State name. May be one of:
218    /// - Offline
219    /// - Online
220    /// - Expelled
221    pub fn name(&self) -> StateVariant {
222        self.variant
223    }
224
225    /// Monotonically increase counter.
226    pub fn incarnation(&self) -> u64 {
227        self.incarnation
228    }
229}
230
231#[derive(StableAbi, Clone, Debug, PartialEq, Eq, Hash)]
232#[repr(C)]
233pub struct InstanceInfo {
234    raft_id: u64,
235    advertise_address: RString,
236    name: RString,
237    uuid: RString,
238    replicaset_name: RString,
239    replicaset_uuid: RString,
240    cluster_name: RString,
241    current_state: State,
242    target_state: State,
243    tier: RString,
244}
245
246impl InstanceInfo {
247    #[allow(clippy::too_many_arguments)]
248    pub fn new(
249        raft_id: u64,
250        advertise_address: String,
251        name: String,
252        instance_uuid: String,
253        replicaset_name: String,
254        replicaset_uuid: String,
255        cluster_name: String,
256        current_state: State,
257        target_state: State,
258        tier: String,
259    ) -> Self {
260        Self {
261            raft_id,
262            advertise_address: RString::from(advertise_address),
263            name: RString::from(name),
264            uuid: RString::from(instance_uuid),
265            replicaset_name: RString::from(replicaset_name),
266            replicaset_uuid: RString::from(replicaset_uuid),
267            cluster_name: RString::from(cluster_name),
268            current_state,
269            target_state,
270            tier: RString::from(tier),
271        }
272    }
273
274    /// Unique identifier of node in RAFT protocol.
275    pub fn raft_id(&self) -> u64 {
276        self.raft_id
277    }
278
279    /// Returns address where other instances can connect to this instance.
280    pub fn advertise_address(&self) -> &str {
281        self.advertise_address.as_str()
282    }
283
284    /// Returns the persisted `InstanceName` of the current instance.
285    pub fn name(&self) -> &str {
286        self.name.as_str()
287    }
288
289    /// Return current instance UUID.
290    pub fn uuid(&self) -> &str {
291        self.uuid.as_str()
292    }
293
294    /// ID of a replicaset the instance belongs to.
295    pub fn replicaset_name(&self) -> &str {
296        self.replicaset_name.as_str()
297    }
298
299    /// UUID of a replicaset the instance belongs to.
300    pub fn replicaset_uuid(&self) -> &str {
301        self.replicaset_uuid.as_str()
302    }
303
304    /// Name of a cluster the instance belongs to.
305    pub fn cluster_name(&self) -> &str {
306        self.cluster_name.as_str()
307    }
308
309    /// Current state of a current instance.
310    pub fn current_state(&self) -> &State {
311        &self.current_state
312    }
313
314    /// Target state of a current instance.
315    pub fn target_state(&self) -> &State {
316        &self.target_state
317    }
318
319    /// Name of a tier the instance belongs to.
320    pub fn tier(&self) -> &str {
321        self.tier.as_str()
322    }
323}
324
325#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
326#[repr(C)]
327pub struct RaftInfo {
328    id: u64,
329    term: u64,
330    applied: u64,
331    leader_id: u64,
332    state: RaftState,
333}
334
335#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
336#[repr(u8)]
337pub enum RaftState {
338    Follower,
339    Candidate,
340    Leader,
341    PreCandidate,
342}
343
344impl RaftInfo {
345    pub fn new(id: u64, term: u64, applied: u64, leader_id: u64, state: RaftState) -> Self {
346        Self {
347            id,
348            term,
349            applied,
350            leader_id,
351            state,
352        }
353    }
354
355    /// Unique identifier of node in RAFT protocol.
356    pub fn id(&self) -> u64 {
357        self.id
358    }
359
360    /// RAFT term.
361    pub fn term(&self) -> u64 {
362        self.term
363    }
364
365    /// Last applied RAFT index.
366    pub fn applied(&self) -> u64 {
367        self.applied
368    }
369
370    /// Unique identifier of a RAFT leader node.
371    pub fn leader_id(&self) -> u64 {
372        self.leader_id
373    }
374
375    /// RAFT state of the current node. Maybe one of:
376    /// - Follower
377    /// - Candidate
378    /// - Leader
379    /// - PreCandidate
380    pub fn state(&self) -> RaftState {
381        self.state
382    }
383}