hitbox_actix/
messages.rs

1//! QueryCache message declaration and converting.
2use actix::{dev::MessageResponse, prelude::*};
3use hitbox::{CacheError, Cacheable};
4
5/// Trait describes coversion from any [actix::Message] into QueryCache message.
6pub trait IntoCache: Cacheable {
7    /// Helper method to convert Message into [QueryCache] message.
8    ///
9    /// # Examples
10    /// ```
11    /// use actix::prelude::*;
12    /// use hitbox_actix::prelude::*;
13    /// use serde::Serialize;
14    ///
15    /// struct Upstream;
16    ///
17    /// impl Actor for Upstream {
18    ///     type Context = Context<Self>;
19    /// }
20    ///
21    /// #[derive(Cacheable, Serialize, Message, Debug, PartialEq)]
22    /// #[rtype(result = "()")]
23    /// struct QueryNothing {
24    ///     id: Option<i32>,
25    /// }
26    ///
27    /// #[actix_rt::main]
28    /// async fn main() {
29    ///     let upstream = Upstream.start();
30    ///     let query = QueryNothing { id: Some(1) }
31    ///         .into_cache(&upstream);
32    /// }
33    /// ```
34    fn into_cache<A>(self, upstream: &Addr<A>) -> QueryCache<A, Self>
35    where
36        A: Actor,
37        Self: Message + Send + Sized,
38        Self::Result: MessageResponse<A, Self> + Send + 'static,
39    {
40        QueryCache {
41            upstream: upstream.clone(),
42            message: self,
43        }
44    }
45}
46
47impl<M: Message + Cacheable> IntoCache for M {}
48
49/// Intermediate actix message which handled by Cache actor.
50///
51/// This message a product of upstream message and upstream actor address.
52/// In other words, QueryCache is a struct that includes base message with user data
53/// and address of an actor that is a recipient of this message.
54/// You can only send QueryCache messages to Cache actor.
55pub struct QueryCache<A, M>
56where
57    M: Message + Cacheable + Send,
58    M::Result: MessageResponse<A, M> + Send,
59    A: Actor,
60{
61    pub(crate) upstream: Addr<A>,
62    pub(crate) message: M,
63}
64
65impl<A, M> QueryCache<A, M>
66where
67    M: Message + Cacheable + Send,
68    M::Result: MessageResponse<A, M> + Send,
69    A: Actor,
70{
71    /// Returns upstream actor type name or <Unknown>.
72    pub(crate) fn upstream_name(&self) -> &'static str {
73        std::any::type_name::<A>()
74            .rsplit("::")
75            .next()
76            .unwrap_or("<Unknown>")
77    }
78
79    /// Returns final cache key.
80    ///
81    /// This method compose final cache key from Cacheable::cache_key
82    /// and Upstream actor type name.
83    pub fn cache_key(&self) -> Result<String, CacheError> {
84        Ok(format!(
85            "{}::{}",
86            self.upstream_name(),
87            self.message.cache_key()?
88        ))
89    }
90}
91
92impl<'a, A, M> Message for QueryCache<A, M>
93where
94    A: Actor,
95    M: Message + Cacheable + Send,
96    M::Result: MessageResponse<A, M> + Send,
97{
98    type Result = Result<<M as Message>::Result, CacheError>;
99}