async_recorder/storage.rs
1use std::ops::Range;
2
3use async_trait::async_trait;
4
5/// Can save records asynchronously
6#[async_trait]
7pub trait Storage {
8 /// Records saved in the storage
9 type Record;
10
11 /// Describes the desired data for the load operation. Usefull for e.g. applying filters.
12 type Query;
13
14 /// Saves all the records to the persistence backend. Note that this method is infallible. This
15 /// implies that the responsibility of handling errors lies with the implementation of this
16 /// trait. So it is up to the implementation to decide how often to retry before (if ever)
17 /// giving up. What to log and so on.
18 ///
19 /// `records` contains all the records which are to be persisted with this call to save. The
20 /// records are passed in a `Vec` rather than in a single call to enable bulk insertion. They
21 /// are also passed in a `Vec` rather than a slice (`&[Record]`) in order to enable taking
22 /// ownership of each record and avoid cloning. Finally it is a `&mut Vec` rather than a buffer
23 /// so we can reuse it, without having to reallocate it a lot during the lifetime of our
24 /// application.
25 async fn save(&mut self, records: &mut Vec<Self::Record>);
26
27 /// Load the contents of the storage as a list of records.
28 async fn load(&mut self, query: Self::Query) -> Vec<Self::Record>;
29}
30
31/// This implementation is usefull for using as a fake for testing. In production you are more
32/// likely want to talk to a database.
33#[async_trait]
34impl<T> Storage for Vec<T>
35where
36 T: Send + Clone,
37{
38 type Query = Range<usize>;
39 type Record = T;
40
41 async fn save(&mut self, records: &mut Vec<T>) {
42 self.append(records);
43 }
44
45 async fn load(&mut self, query: Range<usize>) -> Vec<T> {
46 self[query].to_owned()
47 }
48}
49
50#[async_trait]
51impl<Q, R> Storage for Box<dyn Storage<Query = Q, Record = R> + Send> where Q: Send, R: Send {
52 type Query = Q;
53 type Record = R;
54
55 async fn save(&mut self, records: &mut Vec<R>) {
56 (**self).save(records).await
57 }
58
59 async fn load(&mut self, query: Q) -> Vec<R> {
60 (**self).load(query).await
61 }
62}