flippico_cache/types/
provider.rs

1use redis::Client;
2
3use crate::{
4    providers::redis::Redis,
5    types::channels::{ChannelMessage, SubscriptionChannel},
6};
7use dotenv::dotenv;
8use std::env;
9use std::future::Future;
10use std::pin::Pin;
11
12pub trait ProviderTrait {
13    fn new(url: String) -> Self
14    where
15        Self: Sized;
16}
17
18pub trait Connectable {
19    fn set_client(&mut self);
20    fn get_connection(&self) -> &Client;
21    fn get_mut_connection(&mut self) -> &mut Client;
22}
23
24pub type PubSubProviderError = &'static str;
25
26pub trait PubSubProvider {
27    type Channels;
28    fn subscribe(
29        &self,
30        channel: Self::Channels,
31        callback: Box<dyn Fn(ChannelMessage) + Send + Sync>,
32    ) -> Pin<Box<dyn Future<Output = Result<(), &'static str>> + Send + '_>>;
33    fn publish(&mut self, channel: Self::Channels, message: ChannelMessage);
34}
35
36pub trait ConnectableProvider: ProviderTrait + Connectable {}
37impl<T> ConnectableProvider for T where T: ProviderTrait + Connectable {}
38
39pub trait ConnectablePubSubProvider: ConnectableProvider + PubSubProvider {}
40impl<T> ConnectablePubSubProvider for T where T: ConnectableProvider + PubSubProvider {}
41
42pub enum Provider {
43    Redis,
44}
45
46pub enum ProviderEither {
47    Left(Box<dyn ConnectablePubSubProvider<Channels = SubscriptionChannel> + Send + Sync>),
48    Right(Box<dyn ConnectableProvider + Send + Sync>),
49}
50
51impl ProviderEither {
52    pub fn pub_sub(
53        self,
54    ) -> Result<
55        Box<dyn ConnectablePubSubProvider<Channels = SubscriptionChannel> + Send + Sync>,
56        &'static str,
57    > {
58        match self {
59            ProviderEither::Left(provider) => Ok(provider),
60            ProviderEither::Right(_) => Err("Wrong provider"),
61        }
62    }
63
64    pub fn connectable(self) -> Result<Box<dyn ConnectableProvider + Send + Sync>, &'static str> {
65        match self {
66            ProviderEither::Right(provider) => Ok(provider),
67            ProviderEither::Left(_) => Err("Wrong provider"),
68        }
69    }
70}
71
72impl Provider {
73    pub(crate) fn create_provider(&self) -> ProviderEither {
74        match self {
75            Provider::Redis => {
76                dotenv().ok();
77                let url = env::var("FLIPPICO_CACHE_REDIS_URL");
78                if let Ok(url) = url {
79                    let mut provider = Redis::new(url);
80                    provider.set_client();
81                    ProviderEither::Left(Box::new(provider))
82                } else {
83                    log::error!("FLIPPICO_CACHE_REDIS_URL is not set");
84                    panic!("FLIPPICO_CACHE_REDIS_URL is not set");
85                }
86            }
87        }
88    }
89}