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    /// ![](https://raw.githubusercontent.com/vrurg/wb-cache/d203ef0eec0060d4fd5eca34bb6646bd24f642d3/docs/flush_individual.svg)
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}