matrix_sdk_indexeddb/transaction/
mod.rs1#![allow(dead_code)]
20
21use futures_util::TryStreamExt;
22use indexed_db_futures::{
23 BuildSerde, cursor::CursorDirection, internals::SystemRepr, query_source::QuerySource,
24 transaction as inner,
25};
26use serde::{
27 Serialize,
28 de::{DeserializeOwned, Error},
29};
30use thiserror::Error;
31use wasm_bindgen::JsValue;
32
33use crate::{
34 error::{AsyncErrorDeps, GenericError},
35 serializer::indexed_type::{
36 IndexedTypeSerializer,
37 range::IndexedKeyRange,
38 traits::{Indexed, IndexedKey},
39 },
40};
41
42#[derive(Debug, Error)]
43pub enum TransactionError {
44 #[error("DomException {name} ({code}): {message}")]
45 DomException { name: String, message: String, code: u16 },
46 #[error("serialization: {0}")]
47 Serialization(Box<dyn AsyncErrorDeps>),
48 #[error("item is not unique")]
49 ItemIsNotUnique,
50 #[error("item not found")]
51 ItemNotFound,
52 #[error("a numerical operation overflowed")]
53 NumericalOverflow,
54 #[error("backend: {0}")]
55 Backend(Box<dyn AsyncErrorDeps>),
56}
57
58impl From<web_sys::DomException> for TransactionError {
59 fn from(value: web_sys::DomException) -> Self {
60 Self::DomException { name: value.name(), message: value.message(), code: value.code() }
61 }
62}
63
64impl From<serde_wasm_bindgen::Error> for TransactionError {
65 fn from(e: serde_wasm_bindgen::Error) -> Self {
66 Self::Serialization(Box::new(serde_json::Error::custom(e.to_string())))
67 }
68}
69
70impl From<indexed_db_futures::error::SerialisationError> for TransactionError {
71 fn from(e: indexed_db_futures::error::SerialisationError) -> Self {
72 Self::Serialization(Box::new(serde_json::Error::custom(e.to_string())))
73 }
74}
75
76impl From<indexed_db_futures::error::JSError> for TransactionError {
77 fn from(value: indexed_db_futures::error::JSError) -> Self {
78 Self::Backend(Box::new(GenericError::from(value.to_string())))
79 }
80}
81
82impl From<indexed_db_futures::error::Error> for TransactionError {
83 fn from(value: indexed_db_futures::error::Error) -> Self {
84 use indexed_db_futures::error::Error;
85 match value {
86 Error::DomException(e) => e.into_sys().into(),
87 Error::Serialisation(e) => e.into(),
88 Error::MissingData(e) => Self::Backend(Box::new(e)),
89 Error::Unknown(e) => e.into(),
90 }
91 }
92}
93
94pub struct Transaction<'a> {
98 transaction: inner::Transaction<'a>,
99 serializer: &'a IndexedTypeSerializer,
100}
101
102impl<'a> Transaction<'a> {
103 pub fn new(transaction: inner::Transaction<'a>, serializer: &'a IndexedTypeSerializer) -> Self {
104 Self { transaction, serializer }
105 }
106
107 pub fn serializer(&self) -> &IndexedTypeSerializer {
110 self.serializer
111 }
112
113 pub fn into_inner(self) -> inner::Transaction<'a> {
115 self.transaction
116 }
117
118 pub async fn commit(self) -> Result<(), TransactionError> {
120 self.transaction.commit().await.map_err(Into::into)
121 }
122
123 pub async fn get_items_by_key<T, K>(
125 &self,
126 range: impl Into<IndexedKeyRange<K>>,
127 ) -> Result<Vec<T>, TransactionError>
128 where
129 T: Indexed,
130 T::IndexedType: DeserializeOwned,
131 T::Error: AsyncErrorDeps,
132 K: IndexedKey<T> + Serialize,
133 {
134 let range = self.serializer.encode_key_range::<T, K>(range);
135 let object_store = self.transaction.object_store(T::OBJECT_STORE)?;
136 let array = if let Some(index) = K::INDEX {
137 object_store.index(index)?.get_all().with_query(range).serde()?.await?
138 } else {
139 object_store.get_all().with_query(range).serde()?.await?
140 };
141 let mut items = Vec::with_capacity(array.len());
142 for value in array {
143 let item = T::from_indexed(value?, self.serializer.inner())
144 .map_err(|e| TransactionError::Serialization(Box::new(e)))?;
145 items.push(item);
146 }
147 Ok(items)
148 }
149
150 pub async fn get_items_by_key_components<'b, T, K>(
152 &self,
153 range: impl Into<IndexedKeyRange<K::KeyComponents<'b>>>,
154 ) -> Result<Vec<T>, TransactionError>
155 where
156 T: Indexed + 'b,
157 T::IndexedType: DeserializeOwned,
158 T::Error: AsyncErrorDeps,
159 K: IndexedKey<T> + Serialize + 'b,
160 {
161 let range: IndexedKeyRange<K> = range.into().encoded(self.serializer.inner());
162 self.get_items_by_key::<T, K>(range).await
163 }
164
165 pub async fn get_item_by_key<T, K>(&self, key: K) -> Result<Option<T>, TransactionError>
168 where
169 T: Indexed,
170 T::IndexedType: DeserializeOwned,
171 T::Error: AsyncErrorDeps,
172 K: IndexedKey<T> + Serialize,
173 {
174 let mut items = self.get_items_by_key::<T, K>(key).await?;
175 if items.len() > 1 {
176 return Err(TransactionError::ItemIsNotUnique);
177 }
178 Ok(items.pop())
179 }
180
181 pub async fn get_item_by_key_components<'b, T, K>(
184 &self,
185 components: K::KeyComponents<'b>,
186 ) -> Result<Option<T>, TransactionError>
187 where
188 T: Indexed + 'b,
189 T::IndexedType: DeserializeOwned,
190 T::Error: AsyncErrorDeps,
191 K: IndexedKey<T> + Serialize + 'b,
192 {
193 let mut items = self.get_items_by_key_components::<T, K>(components).await?;
194 if items.len() > 1 {
195 return Err(TransactionError::ItemIsNotUnique);
196 }
197 Ok(items.pop())
198 }
199
200 pub async fn get_items_count_by_key<T, K>(
202 &self,
203 range: impl Into<IndexedKeyRange<K>>,
204 ) -> Result<usize, TransactionError>
205 where
206 T: Indexed,
207 T::IndexedType: DeserializeOwned,
208 T::Error: AsyncErrorDeps,
209 K: IndexedKey<T> + Serialize,
210 {
211 let range = self.serializer.encode_key_range::<T, K>(range);
212 let object_store = self.transaction.object_store(T::OBJECT_STORE)?;
213 let count = if let Some(index) = K::INDEX {
214 object_store.index(index)?.count().with_query(range).serde()?.await?
215 } else {
216 object_store.count().with_query(range).serde()?.await?
217 };
218 Ok(count as usize)
219 }
220
221 pub async fn get_items_count_by_key_components<'b, T, K>(
224 &self,
225 range: impl Into<IndexedKeyRange<K::KeyComponents<'b>>>,
226 ) -> Result<usize, TransactionError>
227 where
228 T: Indexed + 'b,
229 T::IndexedType: DeserializeOwned,
230 T::Error: AsyncErrorDeps,
231 K: IndexedKey<T> + Serialize + 'b,
232 {
233 let range: IndexedKeyRange<K> = range.into().encoded(self.serializer.inner());
234 self.get_items_count_by_key::<T, K>(range).await
235 }
236
237 pub async fn get_max_item_by_key<T, K>(
239 &self,
240 range: impl Into<IndexedKeyRange<K>>,
241 ) -> Result<Option<T>, TransactionError>
242 where
243 T: Indexed,
244 T::IndexedType: DeserializeOwned,
245 T::Error: AsyncErrorDeps,
246 K: IndexedKey<T> + Serialize + DeserializeOwned,
247 {
248 if let Some(key) = self.get_max_key::<T, K>(range).await? {
249 return self.get_item_by_key::<T, K>(key).await;
250 }
251 Ok(None)
252 }
253
254 pub async fn get_keys<T, K>(
256 &self,
257 range: impl Into<IndexedKeyRange<K>>,
258 ) -> Result<Vec<K>, TransactionError>
259 where
260 T: Indexed,
261 K: IndexedKey<T> + Serialize + DeserializeOwned,
262 {
263 let range = self.serializer.encode_key_range::<T, K>(range);
264 let object_store = self.transaction.object_store(T::OBJECT_STORE)?;
265 if let Some(index) = K::INDEX {
266 let index = object_store.index(index)?;
267 if let Some(cursor) = index.open_key_cursor().with_query(range).serde()?.await? {
268 return cursor.key_stream_ser().try_collect().await.map_err(Into::into);
269 }
270 } else if let Some(cursor) =
271 object_store.open_key_cursor().with_query(range).serde()?.await?
272 {
273 return cursor.key_stream_ser().try_collect().await.map_err(Into::into);
274 }
275 Ok(Vec::new())
276 }
277
278 pub async fn get_max_key<T, K>(
280 &self,
281 range: impl Into<IndexedKeyRange<K>>,
282 ) -> Result<Option<K>, TransactionError>
283 where
284 T: Indexed,
285 K: IndexedKey<T> + Serialize + DeserializeOwned,
286 {
287 let range = self.serializer.encode_key_range::<T, K>(range);
288 let direction = CursorDirection::Prev;
289 let object_store = self.transaction.object_store(T::OBJECT_STORE)?;
290 if let Some(index) = K::INDEX {
291 let index = object_store.index(index)?;
292 if let Some(mut cursor) =
293 index.open_key_cursor().with_query(range).with_direction(direction).serde()?.await?
294 {
295 return cursor.next_key_ser().await.map_err(Into::into);
296 }
297 } else if let Some(mut cursor) = object_store
298 .open_key_cursor()
299 .with_query(range)
300 .with_direction(direction)
301 .serde()?
302 .await?
303 {
304 return cursor.next_key_ser().await.map_err(Into::into);
305 }
306 Ok(None)
307 }
308
309 pub async fn fold_keys_while<T, K, Acc, F>(
320 &self,
321 direction: CursorDirection,
322 range: impl Into<IndexedKeyRange<K>>,
323 init: Acc,
324 mut f: F,
325 ) -> Result<(Acc, Option<K>), TransactionError>
326 where
327 T: Indexed,
328 K: IndexedKey<T> + Serialize + DeserializeOwned,
329 F: FnMut(&Acc, &K) -> Option<Acc>,
330 {
331 let range = self.serializer.encode_key_range::<T, K>(range);
332 let object_store = self.transaction.object_store(T::OBJECT_STORE)?;
333
334 let mut state = init;
335 if let Some(index) = K::INDEX {
336 let index = object_store.index(index)?;
337 if let Some(mut cursor) =
338 index.open_key_cursor().with_query(range).with_direction(direction).serde()?.await?
339 {
340 while let Some(key) = cursor.next_key_ser().await? {
341 match f(&state, &key) {
342 Some(s) => state = s,
343 None => return Ok((state, Some(key))),
344 }
345 }
346 }
347 } else if let Some(mut cursor) = object_store
348 .open_key_cursor()
349 .with_query(range)
350 .with_direction(direction)
351 .serde()?
352 .await?
353 {
354 while let Some(key) = cursor.next_key_ser().await? {
355 match f(&state, &key) {
356 Some(s) => state = s,
357 None => return Ok((state, Some(key))),
358 }
359 }
360 }
361 Ok((state, None))
362 }
363
364 pub async fn add_item<T>(&self, item: &T) -> Result<T::IndexedType, TransactionError>
370 where
371 T: Indexed + Serialize,
372 T::IndexedType: Serialize,
373 T::Error: AsyncErrorDeps,
374 {
375 let output = self
376 .serializer
377 .serialize(item)
378 .map_err(|e| TransactionError::Serialization(Box::new(e)))?;
379 self.transaction.object_store(T::OBJECT_STORE)?.add(output.value).await?;
380 Ok(output.indexed)
381 }
382
383 pub async fn put_item<T>(&self, item: &T) -> Result<T::IndexedType, TransactionError>
389 where
390 T: Indexed + Serialize,
391 T::IndexedType: Serialize,
392 T::Error: AsyncErrorDeps,
393 {
394 let output = self
395 .serializer
396 .serialize(item)
397 .map_err(|e| TransactionError::Serialization(Box::new(e)))?;
398 self.transaction.object_store(T::OBJECT_STORE)?.put(output.value).await?;
399 Ok(output.indexed)
400 }
401
402 pub async fn put_item_if<T>(
409 &self,
410 item: &T,
411 f: impl Fn(&T::IndexedType) -> bool,
412 ) -> Result<Option<T::IndexedType>, TransactionError>
413 where
414 T: Indexed + Serialize,
415 T::IndexedType: Serialize,
416 T::Error: AsyncErrorDeps,
417 {
418 let option = self
419 .serializer
420 .serialize_if(item, f)
421 .map_err(|e| TransactionError::Serialization(Box::new(e)))?;
422 if let Some(output) = option {
423 self.transaction.object_store(T::OBJECT_STORE)?.put(output.value).await?;
424 Ok(Some(output.indexed))
425 } else {
426 Ok(None)
427 }
428 }
429
430 pub async fn delete_items_by_key<T, K>(
432 &self,
433 range: impl Into<IndexedKeyRange<K>>,
434 ) -> Result<(), TransactionError>
435 where
436 T: Indexed,
437 K: IndexedKey<T> + Serialize,
438 {
439 let range = self.serializer.encode_key_range::<T, K>(range);
440 let object_store = self.transaction.object_store(T::OBJECT_STORE)?;
441 if let Some(index) = K::INDEX {
442 let index = object_store.index(index)?;
443 if let Some(mut cursor) = index.open_cursor().with_query(range).serde()?.await? {
444 loop {
445 cursor.delete()?;
446 if cursor.next_record::<JsValue>().await?.is_none() {
447 break;
448 }
449 }
450 }
451 } else {
452 object_store.delete(range).serde()?.await?;
453 }
454 Ok(())
455 }
456
457 pub async fn delete_items_by_key_components<'b, T, K>(
460 &self,
461 range: impl Into<IndexedKeyRange<K::KeyComponents<'b>>>,
462 ) -> Result<(), TransactionError>
463 where
464 T: Indexed + 'b,
465 K: IndexedKey<T> + Serialize + 'b,
466 {
467 let range: IndexedKeyRange<K> = range.into().encoded(self.serializer.inner());
468 self.delete_items_by_key::<T, K>(range).await
469 }
470
471 pub async fn delete_item_by_key<'b, T, K>(
474 &self,
475 key: K::KeyComponents<'b>,
476 ) -> Result<(), TransactionError>
477 where
478 T: Indexed + 'b,
479 K: IndexedKey<T> + Serialize + 'b,
480 {
481 self.delete_items_by_key_components::<T, K>(key).await
482 }
483
484 pub async fn clear<T>(&self) -> Result<(), TransactionError>
487 where
488 T: Indexed,
489 {
490 self.transaction.object_store(T::OBJECT_STORE)?.clear()?.await.map_err(Into::into)
491 }
492}