valence_backend_redis/
fleet.rs1use std::sync::Arc;
4
5use valence_core::backend::DatabaseBackend;
6use valence_core::Result;
7
8use crate::backend::RedisBackend;
9use crate::config::{FleetRedisBackendBuilder, RedisConfig};
10
11#[derive(Debug)]
13pub struct FleetRedisBackend {
14 backends: Vec<RedisBackend>,
15}
16
17impl FleetRedisBackend {
18 pub fn builder() -> FleetRedisBackendBuilder {
20 FleetRedisBackendBuilder::new()
21 }
22
23 pub async fn from_env() -> Result<Self> {
30 Self::builder().from_env_defaults().build().await
31 }
32
33 pub async fn connect_with_urls(urls: Vec<String>, key_prefix: String) -> Result<Self> {
39 let mut backends = Vec::with_capacity(urls.len());
40 for url in urls {
41 backends.push(
42 RedisBackend::connect_with_config(RedisConfig::new(url, key_prefix.clone()))
43 .await?,
44 );
45 }
46 Ok(Self { backends })
47 }
48
49 fn backend_for_table(&self, table: &str) -> &RedisBackend {
50 let idx = table_slot_index(table, self.backends.len());
51 &self.backends[idx]
52 }
53}
54
55fn table_slot_index(table: &str, n: usize) -> usize {
56 if n == 0 {
57 return 0;
58 }
59 table
60 .bytes()
61 .fold(0usize, |acc, b| acc.wrapping_add(usize::from(b)))
62 % n
63}
64
65#[async_trait::async_trait]
66impl DatabaseBackend for FleetRedisBackend {
67 fn engine_id(&self) -> &'static str {
68 crate::ENGINE_ID
69 }
70
71 fn capabilities(&self) -> valence_core::BackendCapabilities {
72 self.backends[0].capabilities()
73 }
74
75 async fn execute_compiled_query(
76 &self,
77 compiled: &valence_core::CompiledQuery,
78 ) -> Result<Vec<serde_json::Value>> {
79 self.backends[0].execute_compiled_query(compiled).await
80 }
81
82 async fn ensure_schemaless_table(&self, table: &str) -> Result<()> {
83 for backend in &self.backends {
84 backend.ensure_schemaless_table(table).await?;
85 }
86 Ok(())
87 }
88
89 async fn get_record(&self, table: &str, id: &str) -> Result<Option<serde_json::Value>> {
90 self.backend_for_table(table).get_record(table, id).await
91 }
92
93 async fn create_record(
94 &self,
95 table: &str,
96 content: serde_json::Value,
97 ) -> Result<serde_json::Value> {
98 self.backend_for_table(table)
99 .create_record(table, content)
100 .await
101 }
102
103 async fn update_record(
104 &self,
105 table: &str,
106 id: &str,
107 content: serde_json::Value,
108 ) -> Result<serde_json::Value> {
109 self.backend_for_table(table)
110 .update_record(table, id, content)
111 .await
112 }
113
114 async fn merge_record(
115 &self,
116 table: &str,
117 id: &str,
118 patch: serde_json::Value,
119 ) -> Result<serde_json::Value> {
120 self.backend_for_table(table)
121 .merge_record(table, id, patch)
122 .await
123 }
124
125 async fn upsert_record(
126 &self,
127 table: &str,
128 id: &str,
129 content: serde_json::Value,
130 ) -> Result<serde_json::Value> {
131 self.backend_for_table(table)
132 .upsert_record(table, id, content)
133 .await
134 }
135
136 async fn delete_record(&self, table: &str, id: &str) -> Result<()> {
137 self.backend_for_table(table).delete_record(table, id).await
138 }
139
140 async fn relate_edge(
141 &self,
142 from: &valence_core::RecordId,
143 edge_table: &str,
144 to: &valence_core::RecordId,
145 ) -> Result<()> {
146 self.backend_for_table(from.table())
147 .relate_edge(from, edge_table, to)
148 .await
149 }
150
151 async fn unrelate_edge(
152 &self,
153 from: &valence_core::RecordId,
154 edge_table: &str,
155 to: &valence_core::RecordId,
156 ) -> Result<()> {
157 self.backend_for_table(from.table())
158 .unrelate_edge(from, edge_table, to)
159 .await
160 }
161
162 async fn get_edge_targets(
163 &self,
164 from: &valence_core::RecordId,
165 edge_table: &str,
166 ) -> Result<Vec<valence_core::RecordId>> {
167 self.backend_for_table(from.table())
168 .get_edge_targets(from, edge_table)
169 .await
170 }
171
172 async fn define_unique_index(&self, table: &str, field: &str) -> Result<()> {
173 for backend in &self.backends {
174 backend.define_unique_index(table, field).await?;
175 }
176 Ok(())
177 }
178
179 fn ttl_capability(&self) -> valence_core::ttl::BackendTtlCapability {
180 crate::ttl::ttl_capability()
181 }
182
183 async fn apply_ttl_policy(
184 &self,
185 table: &str,
186 policy: &valence_core::ttl::SchemaTtlPolicy,
187 ) -> Result<()> {
188 for backend in &self.backends {
189 backend.apply_ttl_policy(table, policy).await?;
190 }
191 Ok(())
192 }
193}
194
195pub async fn connect_fleet_arc(
201 builder: FleetRedisBackendBuilder,
202) -> Result<Arc<dyn DatabaseBackend>> {
203 Ok(Arc::new(builder.build().await?))
204}