1use crate::config::{AveInternalDBConfig, AveInternalDBFeatureConfig};
5
6#[cfg(feature = "sqlite")]
7use ave_actors::SqliteManager;
8use ave_actors::{Actor, ActorContext, ActorError, EncryptedKey, MachineSpec};
9use ave_actors::{Collection, DbManager, PersistentActor, State, StoreError};
10#[cfg(feature = "rocksdb")]
11use ave_actors::{RocksDbManager, RocksDbStore};
12
13use async_trait::async_trait;
14use borsh::{BorshDeserialize, BorshSerialize};
15
16#[derive(Clone)]
17pub enum Database {
18 #[cfg(feature = "rocksdb")]
19 RocksDb(RocksDbManager),
20 #[cfg(feature = "sqlite")]
21 SQLite(SqliteManager),
22}
23
24impl Database {
25 pub fn open(
26 config: &AveInternalDBConfig,
27 spec: Option<MachineSpec>,
28 ) -> Result<Self, StoreError> {
29 match &config.db {
30 #[cfg(feature = "rocksdb")]
31 AveInternalDBFeatureConfig::Rocksdb { path } => {
32 let manager =
33 RocksDbManager::new(path, config.durability, spec)?;
34 Ok(Database::RocksDb(manager))
35 }
36 #[cfg(feature = "sqlite")]
37 AveInternalDBFeatureConfig::Sqlite { path } => {
38 let manager =
39 SqliteManager::new(path, config.durability, spec)?;
40 Ok(Self::SQLite(manager))
41 }
42 }
43 }
44}
45
46impl DbManager<DbCollection, DbCollection> for Database {
47 fn create_collection(
48 &self,
49 name: &str,
50 prefix: &str,
51 ) -> Result<DbCollection, StoreError> {
52 match self {
53 #[cfg(feature = "rocksdb")]
54 Database::RocksDb(manager) => {
55 let store = manager.create_collection(name, prefix)?;
56 Ok(DbCollection::RocksDb(store))
57 }
58 #[cfg(feature = "sqlite")]
59 Self::SQLite(manager) => {
60 let store = manager.create_collection(name, prefix)?;
61 Ok(DbCollection::SQLite(store))
62 }
63 }
64 }
65
66 fn create_state(
67 &self,
68 name: &str,
69 prefix: &str,
70 ) -> Result<DbCollection, StoreError> {
71 match self {
72 #[cfg(feature = "rocksdb")]
73 Database::RocksDb(manager) => {
74 let store = manager.create_state(name, prefix)?;
75 Ok(DbCollection::RocksDb(store))
76 }
77 #[cfg(feature = "sqlite")]
78 Self::SQLite(manager) => {
79 let store = manager.create_state(name, prefix)?;
80 Ok(DbCollection::SQLite(store))
81 }
82 }
83 }
84
85 fn stop(&mut self) -> Result<(), StoreError> {
86 match self {
87 #[cfg(feature = "rocksdb")]
88 Database::RocksDb(manager) => manager.stop(),
89 #[cfg(feature = "sqlite")]
90 Self::SQLite(manager) => manager.stop(),
91 }
92 }
93}
94
95pub enum DbCollection {
96 #[cfg(feature = "rocksdb")]
97 RocksDb(RocksDbStore),
98 #[cfg(feature = "sqlite")]
99 SQLite(ave_actors::SqliteCollection),
100}
101
102impl Collection for DbCollection {
103 fn name(&self) -> &str {
104 match self {
105 #[cfg(feature = "rocksdb")]
106 DbCollection::RocksDb(store) => Collection::name(store),
107 #[cfg(feature = "sqlite")]
108 Self::SQLite(store) => Collection::name(store),
109 }
110 }
111
112 fn get(&self, key: &str) -> Result<Vec<u8>, StoreError> {
113 match self {
114 #[cfg(feature = "rocksdb")]
115 DbCollection::RocksDb(store) => Collection::get(store, key),
116 #[cfg(feature = "sqlite")]
117 Self::SQLite(store) => Collection::get(store, key),
118 }
119 }
120
121 fn put(&mut self, key: &str, data: &[u8]) -> Result<(), StoreError> {
122 match self {
123 #[cfg(feature = "rocksdb")]
124 DbCollection::RocksDb(store) => Collection::put(store, key, data),
125 #[cfg(feature = "sqlite")]
126 Self::SQLite(store) => Collection::put(store, key, data),
127 }
128 }
129
130 fn del(&mut self, key: &str) -> Result<(), StoreError> {
131 match self {
132 #[cfg(feature = "rocksdb")]
133 DbCollection::RocksDb(store) => Collection::del(store, key),
134 #[cfg(feature = "sqlite")]
135 Self::SQLite(store) => Collection::del(store, key),
136 }
137 }
138
139 fn iter<'a>(
140 &'a self,
141 reverse: bool,
142 ) -> Result<
143 Box<dyn Iterator<Item = Result<(String, Vec<u8>), StoreError>> + 'a>,
144 StoreError,
145 > {
146 match self {
147 #[cfg(feature = "rocksdb")]
148 DbCollection::RocksDb(store) => Collection::iter(store, reverse),
149 #[cfg(feature = "sqlite")]
150 Self::SQLite(store) => Collection::iter(store, reverse),
151 }
152 }
153
154 fn purge(&mut self) -> Result<(), StoreError> {
155 match self {
156 #[cfg(feature = "rocksdb")]
157 DbCollection::RocksDb(store) => Collection::purge(store),
158 #[cfg(feature = "sqlite")]
159 Self::SQLite(store) => Collection::purge(store),
160 }
161 }
162
163 fn last(&self) -> Result<Option<(String, Vec<u8>)>, StoreError> {
164 match self {
165 #[cfg(feature = "rocksdb")]
166 DbCollection::RocksDb(store) => Collection::last(store),
167 #[cfg(feature = "sqlite")]
168 Self::SQLite(store) => Collection::last(store),
169 }
170 }
171}
172
173impl State for DbCollection {
174 fn name(&self) -> &str {
175 match self {
176 #[cfg(feature = "rocksdb")]
177 DbCollection::RocksDb(store) => State::name(store),
178 #[cfg(feature = "sqlite")]
179 Self::SQLite(store) => State::name(store),
180 }
181 }
182
183 fn get(&self) -> Result<Vec<u8>, StoreError> {
184 match self {
185 #[cfg(feature = "rocksdb")]
186 DbCollection::RocksDb(store) => State::get(store),
187 #[cfg(feature = "sqlite")]
188 Self::SQLite(store) => State::get(store),
189 }
190 }
191
192 fn put(&mut self, data: &[u8]) -> Result<(), StoreError> {
193 match self {
194 #[cfg(feature = "rocksdb")]
195 DbCollection::RocksDb(store) => State::put(store, data),
196 #[cfg(feature = "sqlite")]
197 Self::SQLite(store) => State::put(store, data),
198 }
199 }
200
201 fn del(&mut self) -> Result<(), StoreError> {
202 match self {
203 #[cfg(feature = "rocksdb")]
204 DbCollection::RocksDb(store) => State::del(store),
205 #[cfg(feature = "sqlite")]
206 Self::SQLite(store) => State::del(store),
207 }
208 }
209
210 fn purge(&mut self) -> Result<(), StoreError> {
211 match self {
212 #[cfg(feature = "rocksdb")]
213 DbCollection::RocksDb(store) => State::purge(store),
214 #[cfg(feature = "sqlite")]
215 Self::SQLite(store) => State::purge(store),
216 }
217 }
218}
219
220#[async_trait]
221pub trait Storable: PersistentActor
222where
223 <Self as Actor>::Event: BorshSerialize + BorshDeserialize,
224{
225 async fn init_store(
226 &mut self,
227 name: &str,
228 prefix: Option<String>,
229 encrypt: bool,
230 ctx: &mut ActorContext<Self>,
231 ) -> Result<(), ActorError> {
232 let db = match ctx.system().get_helper::<Database>("store").await {
234 Some(db) => db,
235 None => {
236 return Err(ActorError::Helper {
237 name: "store".to_string(),
238 reason: "Not found".to_string(),
239 });
240 }
241 };
242 let encrypt_key = if encrypt {
244 if let Some(encrypt_key) = ctx
245 .system()
246 .get_helper::<EncryptedKey>("encrypted_key")
247 .await
248 {
249 Some(encrypt_key)
250 } else {
251 return Err(ActorError::Helper {
252 name: "encrypted_key".to_string(),
253 reason: "Not found".to_string(),
254 });
255 }
256 } else {
257 None
258 };
259
260 self.start_store(name, prefix, ctx, db, encrypt_key).await?;
262 Ok(())
263 }
264}