Skip to main content

coven/
file.rs

1//! Application file calls delegate to the composed sync file owner.
2use crate::*;
3
4impl CovenHandle {
5    /// The file's status as its record now stands (§17.6): one this device
6    /// uploads from local facts, one only on another device from its record,
7    /// and a stored one by a single-object status call. Network failures and
8    /// denied access are errors, not Missing.
9    pub async fn file_status(&self, file: &FileRef) -> Result<FileStatus, FileReadError> {
10        self.files.file_status(file).await
11    }
12    /// Prepares keeping stored files whole on this device regardless of the
13    /// cache budget, which pinned bytes don't count toward (§17.8): downloads what each lacks into a whole copy,
14    /// checked against its content hash, and pins nothing; a write commits
15    /// the result with `CovenWrite::pin`. A file only on one device, this
16    /// one included while it uploads, is refused with
17    /// `FileReadError::DeviceOnly`, and one whose record goes, or leaves its
18    /// stored bytes, while they download keeps nothing and fails with
19    /// `DbError::NoLongerStored`. A prepare that stops, dropped or ended by
20    /// a crash, keeps the bytes it downloaded of each file, apart from the
21    /// cache, and the next prepare of the file continues from them; the
22    /// app's unpin of the file ends them, and a prepare it ends fails with
23    /// `DbError::PinChanged`. Which files are downloading is in
24    /// `coven_downloading`, how far each has got on the download watch.
25    pub async fn prepare_pin(&self, files: &[FileRef]) -> Result<PreparedPin, FileReadError> {
26        self.files.prepare_pin(files).await
27    }
28    /// Prepares a pin and commits it in a write of its own.
29    pub async fn pin(&self, files: &[FileRef]) -> Result<(), FileReadError> {
30        let prepared = self.prepare_pin(files).await?;
31        self.write(move |write| write.pin(prepared)).await.map_err(FileReadError::from)
32    }
33    /// Verified cache coverage for these fixed references, in one snapshot.
34    pub async fn pin_progress(&self, files: Vec<FileRef>) -> CovenResult<PinProgress> {
35        self.database.pin_progress(files).await.map_err(CovenError::from)
36    }
37    /// The same pre-built cache query with the same fixed references.
38    pub fn subscribe_pin_progress(
39        &self,
40        files: Vec<FileRef>,
41    ) -> LiveQuery<PinProgress, CovenError> {
42        self.database.subscribe_pin_progress(files)
43    }
44    /// Remove the files' copies from this device, in a write of its own
45    /// (`CovenWrite::unpin`).
46    pub async fn unpin(&self, files: &[FileId]) -> CovenResult<()> {
47        let files = files.to_vec();
48        self.write(move |write| Ok(write.unpin(&files)?)).await
49    }
50    /// Whether each file is pinned, one answer per file in order, or `None`
51    /// for a file this device has no record of. The answer is whether
52    /// `coven_pins` lists it.
53    pub async fn files_pinned(&self, files: &[FileId]) -> CovenResult<Vec<Option<bool>>> {
54        self.database.files_pinned(files.to_vec()).await.map_err(CovenError::from)
55    }
56    /// The same internal query, live. To watch different files, drop this
57    /// query and subscribe with the new files.
58    pub fn subscribe_files_pinned(
59        &self,
60        files: &[FileId],
61    ) -> LiveQuery<Vec<Option<bool>>, CovenError> {
62        self.database.subscribe_files_pinned(files.to_vec())
63    }
64    /// Remove cache copies only, in a write of its own
65    /// (`CovenWrite::evict_file`).
66    pub async fn evict_file(&self, file: FileId) -> CovenResult<()> {
67        self.write(move |write| Ok(write.evict_file(file)?)).await
68    }
69    /// Clear a namespace's cache, in a write of its own
70    /// (`CovenWrite::clear_cache`).
71    pub async fn clear_cache(&self, namespace: &str) -> CovenResult<()> {
72        let namespace = namespace.to_owned();
73        self.write(move |write| Ok(write.clear_cache(&namespace)?)).await
74    }
75    /// Set and enforce a namespace's independent byte budget, in a write of
76    /// its own (`CovenWrite::set_cache_budget`).
77    pub async fn set_cache_budget(&self, namespace: &str, max_bytes: u64) -> CovenResult<()> {
78        let namespace = namespace.to_owned();
79        self.write(move |write| Ok(write.set_cache_budget(&namespace, max_bytes)?)).await
80    }
81    /// The namespace's budget, declared or since set.
82    pub async fn get_cache_budget(&self, namespace: &str) -> Result<u64, DbError> {
83        self.files.get_cache_budget(namespace).await
84    }
85}
86#[cfg(test)]
87#[path = "file_tests.rs"]
88mod tests;