wb_cache/types.rs
1use crate::entry::Entry;
2use crate::traits::DataController;
3use std::fmt::Debug;
4use std::sync::Arc;
5
6/// The result of a compute operation on an entry. Results that affect the cache content are reflected in the
7/// controller's update pool.
8///
9/// Variants that contain an [`Entry`] are returned with the final entry value.
10pub enum CompResult<DC>
11where
12 DC: DataController,
13{
14 /// The entry has been inserted into the cache.
15 Inserted(Entry<DC>),
16 /// The entry has been replaced with a new one.
17 ReplacedWith(Entry<DC>),
18 /// The entry has been removed from the cache.
19 Removed(Entry<DC>),
20 /// The entry is in the cache and remains unchanged.
21 Unchanged(Entry<DC>),
22 /// There is still no entry for the key.
23 StillNone(Arc<DC::Key>),
24}
25
26impl<DC> Debug for CompResult<DC>
27where
28 DC: DataController,
29{
30 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31 match self {
32 Self::Inserted(e) => fmt.debug_tuple("CompResult::Inserted").field(e).finish(),
33 Self::Removed(e) => fmt.debug_tuple("CompResult::Removed").field(e).finish(),
34 Self::ReplacedWith(e) => fmt.debug_tuple("CompResult::ReplacedWith").field(e).finish(),
35 Self::Unchanged(e) => fmt.debug_tuple("CompResult::Unchanged").field(e).finish(),
36 Self::StillNone(k) => fmt.debug_tuple("CompResult::StillNone").field(k).finish(),
37 }
38 }
39}
40
41/// What the cache controller should do with the initial value that was submitted for data controller processing.
42#[derive(Debug, Clone, Copy)]
43pub enum DataControllerOp {
44 /// Do nothing, only put the returned update record into the update pool.
45 Nop,
46 /// Insert the value into the cache. This is possible for "immutable" records, i.e., those for which it can be
47 /// guaranteed that they won't be changed by the backend. For example, if the primary key field is pre-generated by
48 /// the client application, then inserting the record into the database won't change it. If the same guarantee can
49 /// be made for all other fields as well, it means that injecting the value into the cache immediately would have
50 /// the same effect as inserting it into the database and then reading it back.
51 ///
52 /// Contrary, if there is an auto-increment field in the record, then sending it to the backend and reading it back
53 /// is mandatory to achieve a consistent final state.
54 Insert,
55 /// Revoke the value from the cache. Useful for cases when the data controller knows that the value must undergo a
56 /// flushing operation either to be deleted from the backend or to be updated.
57 ///
58 /// _Note:_ There is a nuance in how the cache controller decides to flush an individual record when necessary: if
59 /// there is an update record for its key but the data record itself is not cached, then it is time to flush that
60 /// key under certain circumstances. Such circumstances may include, for example, a request to update the data
61 /// record. Since the cache controller does not know how to apply the update (and the data controller may also be
62 /// uncertain about this), the only way to provide the user with a valid data record is to flush the update first.
63 ///
64 /// 
65 Revoke,
66 /// An extreme case of the `Revoke` operation. The value is not only revoked from the cache, but the corresponding entry
67 /// is also removed from the update pool. This would be an ideal case of an "immutable" record which is inserted and deleted
68 /// sufficiently fast to not require being written back to the backend.
69 Drop,
70}
71
72/// The response that the cache controller receives from the data controller after processing a new/change/delete/access
73/// request.
74pub struct DataControllerResponse<DC>
75where
76 DC: DataController,
77{
78 /// The operation that the data controller suggests to perform with the value associated with the processed request.
79 pub op: DataControllerOp,
80 /// The update record produced by the data controller. If it is not `None` then the cache controller must put it
81 /// into the update pool and will later pass it into the
82 /// [`DataController::write_back()`](crate::traits::DataController::write_back) method.
83 pub update: Option<DC::CacheUpdate>,
84}
85
86impl<DC> Debug for DataControllerResponse<DC>
87where
88 DC: DataController,
89{
90 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 fmt.debug_struct("DataControllerResponse")
92 .field("op", &self.op)
93 .field("update", &self.update)
94 .finish()
95 }
96}