Skip to main content

obj/asynchronous/
collection.rs

1//! `AsyncCollection` — async-facing wrapper over a runtime-named
2//! read-only [`crate::Collection`] handle.
3//!
4//! Construction is infallible (see [`crate::Db::collection`]); each
5//! async method opens a fresh blocking [`crate::Db::collection`]
6//! handle inside the [`blocking`] pool and dispatches one of its
7//! read-only methods.
8//!
9//! Writes via a runtime-named handle are intentionally out of scope —
10//! Phase 1B (M11 #94) limits the runtime accessor to reads. Use
11//! [`crate::asynchronous::AsyncDb::transaction`] +
12//! [`crate::WriteTxn::collection`] for the typed-write path.
13
14use std::marker::PhantomData;
15use std::sync::Arc;
16
17use obj_core::{Document, Id, Result};
18
19use crate::asynchronous::db::unblock;
20use crate::Db;
21
22/// Async-facing wrapper over a runtime-named read-only collection
23/// handle.
24///
25/// Cheap to clone — holds one `Arc<Db>` + the collection name.
26#[derive(Debug)]
27pub struct AsyncCollection<T> {
28    db: Arc<Db>,
29    name: String,
30    _phantom: PhantomData<fn() -> T>,
31}
32
33impl<T> Clone for AsyncCollection<T> {
34    fn clone(&self) -> Self {
35        Self {
36            db: Arc::clone(&self.db),
37            name: self.name.clone(),
38            _phantom: PhantomData,
39        }
40    }
41}
42
43impl<T> AsyncCollection<T>
44where
45    T: Document + Send + 'static,
46{
47    pub(crate) fn lazy(db: Arc<Db>, name: String) -> Self {
48        Self {
49            db,
50            name,
51            _phantom: PhantomData,
52        }
53    }
54
55    /// Async sibling of [`crate::Collection::get`]. Opens a private
56    /// read transaction inside the blocking task.
57    ///
58    /// # Errors
59    ///
60    /// As [`crate::Collection::get`].
61    pub async fn get(&self, id: Id) -> Result<Option<T>> {
62        let db = Arc::clone(&self.db);
63        let name = self.name.clone();
64        unblock(move || db.collection::<T>(name).get(id)).await
65    }
66
67    /// Async sibling of [`crate::Collection::all`].
68    ///
69    /// # Errors
70    ///
71    /// As [`crate::Collection::all`].
72    pub async fn all(&self) -> Result<Vec<(Id, T)>> {
73        let db = Arc::clone(&self.db);
74        let name = self.name.clone();
75        unblock(move || db.collection::<T>(name).all()).await
76    }
77
78    /// Async sibling of [`crate::Collection::count_all`].
79    ///
80    /// # Errors
81    ///
82    /// As [`crate::Collection::count_all`].
83    pub async fn count_all(&self) -> Result<u64> {
84        let db = Arc::clone(&self.db);
85        let name = self.name.clone();
86        unblock(move || db.collection::<T>(name).count_all()).await
87    }
88
89    /// Async sibling of [`crate::Collection::find_unique`].
90    ///
91    /// # Errors
92    ///
93    /// As [`crate::Collection::find_unique`].
94    pub async fn find_unique<K>(&self, index_name: &str, key: K) -> Result<Option<T>>
95    where
96        K: Into<obj_core::codec::Dynamic> + Send + 'static,
97    {
98        let db = Arc::clone(&self.db);
99        let name = self.name.clone();
100        let index_name = index_name.to_owned();
101        unblock(move || db.collection::<T>(name).find_unique(&index_name, key)).await
102    }
103}