cocklock/
builder.rs

1use postgres::{Client, NoTls};
2use postgres_native_tls::MakeTlsConnector;
3use uuid::Uuid;
4
5use crate::errors::CockLockError;
6use crate::lock::{CockLock, CockLockQueries, DEFAULT_TABLE};
7
8pub struct CockLockBuilder {
9    /// List of all Postgres/Cockroach clients
10    clients: Vec<Client>,
11    client_connection_strings: Vec<String>,
12    tls_connector: Option<MakeTlsConnector>,
13    table_name: String,
14}
15
16impl Default for CockLockBuilder {
17    fn default() -> Self {
18        Self {
19            clients: vec![],
20            client_connection_strings: vec![],
21            tls_connector: None,
22            table_name: DEFAULT_TABLE.to_owned(),
23        }
24    }
25}
26
27/// A builder for the CockLock struct
28///
29/// Allows chaining of methods to build a new CockLock using either Postgres
30/// or Cockroach connections.
31impl CockLockBuilder {
32    /// Instantiate a new CockLock builder
33    pub fn new() -> Self {
34        Self::default()
35    }
36
37    /// Add some client connection strings
38    pub fn with_connection_strings<T: ToString>(mut self, connection_strings: Vec<T>) -> Self {
39        for connection_string in connection_strings {
40            self.client_connection_strings
41                .push(connection_string.to_string());
42        }
43        self
44    }
45
46    /// Change the table name to be used for locks
47    pub fn with_table_name<T: ToString>(mut self, table_name: T) -> Self {
48        self.table_name = table_name.to_string();
49        self
50    }
51
52    /// Add custom clients
53    ///
54    /// Clients may be made from the postgres package and added here
55    pub fn with_clients(mut self, clients: &mut Vec<Client>) -> Self {
56        self.clients.append(clients);
57        self
58    }
59
60    /// Build a CockLock instance using the builder
61    pub fn build(self) -> Result<CockLock, CockLockError> {
62        let mut clients = self.clients;
63        for connection_string in self.client_connection_strings {
64            match &self.tls_connector {
65                Some(connector) => {
66                    clients.push(Client::connect(&connection_string, connector.clone())?);
67                }
68                None => {
69                    clients.push(Client::connect(&connection_string, NoTls)?);
70                }
71            }
72        }
73
74        if clients.is_empty() {
75            return Err(CockLockError::NoClients);
76        }
77
78        let instance = CockLock::new(CockLock {
79            id: Uuid::new_v4(),
80            clients,
81            table_name: self.table_name,
82            queries: CockLockQueries::default(),
83        })?;
84
85        Ok(instance)
86    }
87}