pub trait DataController:
Sized
+ Send
+ Sync
+ 'static {
type Key: Debug + Display + Hash + Clone + Eq + Sized + Send + Sync + 'static;
type Value: Debug + Clone + Send + Sync + 'static;
type CacheUpdate: Debug + Send + Sync + 'static;
type Error: Display + Debug + Send + Sync + 'static;
// Required methods
fn get_for_key<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
) -> Pin<Box<dyn Future<Output = Result<Option<Self::Value>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait;
fn write_back<'life0, 'async_trait>(
&'life0 self,
updates: Arc<UpdateIterator<Self>>,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
fn on_new<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
value: &'life2 Self::Value,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn on_delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
update: Option<&'life2 Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn on_change<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
value: &'life2 Self::Value,
old_value: Self::Value,
prev_handler: Option<Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait;
fn primary_key_of(&self, value: &Self::Value) -> Self::Key;
// Provided methods
fn secondary_keys_of(&self, _value: &Self::Value) -> Vec<Self::Key> { ... }
fn get_primary_key_for<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
) -> Pin<Box<dyn Future<Output = Result<Option<Self::Key>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait { ... }
fn is_primary(&self, _key: &Self::Key) -> bool { ... }
fn on_access<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_key: &'life1 Self::Key,
_value: &'life2 Self::Value,
prev_update: Option<Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait { ... }
}Expand description
The data controller implementation.
Use of the Cache must start with creating a type that implements this trait.
This crate includes example implementations of data controllers in the simulation code. These can be found in the
test::simulation::db::entity module as the Manager types. Since they all
use the same backend (SeaORM framework), they implement the trait
DCCommon which provides a set of common methods for simulation
data controllers.
Required Associated Types§
Sourcetype Key: Debug + Display + Hash + Clone + Eq + Sized + Send + Sync + 'static
type Key: Debug + Display + Hash + Clone + Eq + Sized + Send + Sync + 'static
The key type to be used with methods like Cache::get() or
Cache::entry().
To implement multi-key access you can use an enum as the key type. See, for example,
CustomerBy key type in the supplied simulation
code.
Sourcetype Value: Debug + Clone + Send + Sync + 'static
type Value: Debug + Clone + Send + Sync + 'static
The record type to be stored in the cache and maintained by the data controller.
Sourcetype CacheUpdate: Debug + Send + Sync + 'static
type CacheUpdate: Debug + Send + Sync + 'static
The type of the update pool records that are produced by the data controller.
The simulation code uses the CacheUpdates enum for this purpose.
Then, every every model’s data controller uses this enum with respective active model type. See the implemenation
for the customer model for example.
Required Methods§
Sourcefn get_for_key<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
) -> Pin<Box<dyn Future<Output = Result<Option<Self::Value>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_for_key<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
) -> Pin<Box<dyn Future<Output = Result<Option<Self::Value>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Must return the value for the given key, if it exists, None otherwise.
Example: customer model.
Sourcefn write_back<'life0, 'async_trait>(
&'life0 self,
updates: Arc<UpdateIterator<Self>>,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn write_back<'life0, 'async_trait>(
&'life0 self,
updates: Arc<UpdateIterator<Self>>,
) -> Pin<Box<dyn Future<Output = Result<(), Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
Given a list of update records, must apply these updates to the underlying backend.
Example: DCCommon::wbdc_write_back().
Sourcefn on_new<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
value: &'life2 Self::Value,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn on_new<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
value: &'life2 Self::Value,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Called when a new record is added to the cache. On success, it must return a DataControllerResponse with the
operation type set to what the data controller considers appropriate for the new record. For example, if it is
known that the new record will have exactly the same field values after being written to the backend as it had
when submitted to this method, then the operation can be set to DataControllerOp::Insert.
Example: DCCommon::wbdbc_on_new(). The trait
classifies DB models into two categories: immutable and mutable. Immutable models do not modify written records
(e.g., when there is no primary key autoincrement) and their records are immediately cached without a roundtrip
to the database.
Sourcefn on_delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
update: Option<&'life2 Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn on_delete<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
update: Option<&'life2 Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Called when there is a delete request for the given key has been received. Don’t mix it up with the invalidate
request which is only clearing a cache entry.
The most typical response operation for this method is DataControllerOp::Revoke.
Example: DCCommon::wbdc_on_delete().
Sourcefn on_change<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
value: &'life2 Self::Value,
old_value: Self::Value,
prev_handler: Option<Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn on_change<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
value: &'life2 Self::Value,
old_value: Self::Value,
prev_handler: Option<Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
Called when a record is modified by the user.
Example: DCCommon::wbdc_on_change().
Sourcefn primary_key_of(&self, value: &Self::Value) -> Self::Key
fn primary_key_of(&self, value: &Self::Value) -> Self::Key
Returns the primary key for the given value.
Example: customer model.
Provided Methods§
Sourcefn secondary_keys_of(&self, _value: &Self::Value) -> Vec<Self::Key>
fn secondary_keys_of(&self, _value: &Self::Value) -> Vec<Self::Key>
Returns a list of secondary keys for the given value. Default implementation returns an empty vector.
Example: customer model.
Sourcefn get_primary_key_for<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
) -> Pin<Box<dyn Future<Output = Result<Option<Self::Key>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
fn get_primary_key_for<'life0, 'life1, 'async_trait>(
&'life0 self,
key: &'life1 Self::Key,
) -> Pin<Box<dyn Future<Output = Result<Option<Self::Key>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
Take a key and return its corresponding primary key. This operation may require a backend request.
The default implementation covers the simple case where there are no secondary keys, simply returning the key itself.
Example: customer model.
Sourcefn is_primary(&self, _key: &Self::Key) -> bool
fn is_primary(&self, _key: &Self::Key) -> bool
Returns true if the given key is considered the primary key.
The default implementation always returns true, which is appropriate when no secondary keys exist.
Example: customer model.
Sourcefn on_access<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_key: &'life1 Self::Key,
_value: &'life2 Self::Value,
prev_update: Option<Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
fn on_access<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_key: &'life1 Self::Key,
_value: &'life2 Self::Value,
prev_update: Option<Self::CacheUpdate>,
) -> Pin<Box<dyn Future<Output = Result<DataControllerResponse<Self>, Self::Error>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
This method is called on every access to the given key in the cache. It can be used to implement various related functionality like updateing the access time column in the backend, or calculating related metrics or statistics.
The default implementation does nothing and returns a no-op response.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.