doido_model/databases.rs
1//! Multiple databases / read-write splitting (Rails `connects_to database:
2//! { writing:, reading: }`).
3//!
4//! [`Databases`] holds a primary (writing) connection and an optional replica
5//! (reading) connection; [`Databases::connection`] routes by [`Role`], falling
6//! back to the writer when no replica is configured.
7
8use sea_orm::DatabaseConnection;
9
10/// Which connection a query should use.
11#[derive(Clone, Copy, Debug, PartialEq, Eq)]
12pub enum Role {
13 Writing,
14 Reading,
15}
16
17/// A primary connection plus an optional read replica.
18pub struct Databases {
19 writing: DatabaseConnection,
20 reading: Option<DatabaseConnection>,
21}
22
23impl Databases {
24 /// A single-database setup (all queries hit `writing`).
25 pub fn new(writing: DatabaseConnection) -> Self {
26 Self {
27 writing,
28 reading: None,
29 }
30 }
31
32 /// Add a read replica; reads then route to it.
33 pub fn with_reading(mut self, reading: DatabaseConnection) -> Self {
34 self.reading = Some(reading);
35 self
36 }
37
38 /// Whether a read replica is configured.
39 pub fn has_replica(&self) -> bool {
40 self.reading.is_some()
41 }
42
43 /// The connection for `role` — reads fall back to the writer without a replica.
44 pub fn connection(&self, role: Role) -> &DatabaseConnection {
45 match role {
46 Role::Writing => &self.writing,
47 Role::Reading => self.reading.as_ref().unwrap_or(&self.writing),
48 }
49 }
50
51 /// The writing connection.
52 pub fn writing(&self) -> &DatabaseConnection {
53 &self.writing
54 }
55
56 /// The reading connection (falls back to the writer).
57 pub fn reading(&self) -> &DatabaseConnection {
58 self.connection(Role::Reading)
59 }
60}