Skip to main content

max / audiofiles

4.7 KB · 136 lines History Blame Raw
1 //! `DirectBackend` analysis and rules: stored analysis results, batch saves,
2 //! feature backfill queries, and rule application over one or many samples.
3
4 use super::{
5 AnalysisBackend, AnalysisResult, BackendResult, ConfigBackend, DirectBackend, RulesBackend,
6 SearchCommand, VfsId, instrument, vfs,
7 };
8 use crate::backend::ConfigKey;
9
10 impl AnalysisBackend for DirectBackend {
11 // --- Analysis ---
12
13 fn get_analysis(&self, hash: &str) -> BackendResult<Option<AnalysisResult>> {
14 let db = self.db.lock();
15 Ok(audiofiles_core::analysis::load_analysis(&db, hash))
16 }
17
18 fn save_analysis_batch(&self, results: &[AnalysisResult]) -> BackendResult<()> {
19 if results.is_empty() {
20 return Ok(());
21 }
22 let db = self.db.lock();
23 audiofiles_core::analysis::save_analysis_batch(&db, results)?;
24 // Invalidate the search worker's cached VP-trees once for the batch, new
25 // analysis data changes normalization ranges and may add fingerprints, so
26 // both indexes must rebuild on the next query.
27 if let Some(w) = self.search_worker.lock().as_ref() {
28 // Fire-and-forget cache drop; if the worker is gone it rebuilds
29 // on next spawn, so a dropped Invalidate is harmless (no busy flag).
30 let _ = w.send(SearchCommand::Invalidate);
31 }
32 Ok(())
33 }
34
35 fn apply_rules_to_sample(&self, hash: &str) -> BackendResult<bool> {
36 let db = self.db.lock();
37 Ok(audiofiles_core::rules::apply_rules_to_sample(&db, hash)?)
38 }
39
40 fn apply_rules_to_samples(&self, hashes: &[String]) -> BackendResult<usize> {
41 let db = self.db.lock();
42 Ok(audiofiles_core::rules::apply_rules_to_samples(&db, hashes)?)
43 }
44
45 fn samples_needing_features(&self) -> BackendResult<Vec<(String, String)>> {
46 let db = self.db.lock();
47 Ok(audiofiles_core::analysis::samples_needing_features(&db)?)
48 }
49 }
50
51 impl RulesBackend for DirectBackend {
52 fn list_rules(&self) -> BackendResult<Vec<audiofiles_core::rules::Rule>> {
53 let db = self.db.lock();
54 Ok(audiofiles_core::rules::list_rules(&db)?)
55 }
56
57 fn create_rule(
58 &self,
59 rule: audiofiles_core::rules::NewRule,
60 ) -> BackendResult<audiofiles_core::rules::Rule> {
61 let db = self.db.lock();
62 Ok(audiofiles_core::rules::create_rule(&db, rule)?)
63 }
64
65 fn update_rule(&self, rule: &audiofiles_core::rules::Rule) -> BackendResult<()> {
66 let db = self.db.lock();
67 Ok(audiofiles_core::rules::update_rule(&db, rule)?)
68 }
69
70 fn delete_rule(&self, id: &str) -> BackendResult<()> {
71 let db = self.db.lock();
72 Ok(audiofiles_core::rules::delete_rule(&db, id)?)
73 }
74
75 fn set_rule_enabled(&self, id: &str, enabled: bool) -> BackendResult<()> {
76 let db = self.db.lock();
77 Ok(audiofiles_core::rules::set_rule_enabled(&db, id, enabled)?)
78 }
79
80 fn preview_rule_matches(&self, rule: &audiofiles_core::rules::Rule) -> BackendResult<usize> {
81 let db = self.db.lock();
82 Ok(audiofiles_core::rules::preview_rule_matches(&db, rule)?)
83 }
84
85 fn apply_all_rules(&self) -> BackendResult<usize> {
86 let db = self.db.lock();
87 Ok(audiofiles_core::rules::apply_all_rules(&db)?)
88 }
89
90 fn sample_tag_provenance(
91 &self,
92 hash: &str,
93 ) -> BackendResult<Vec<(String, String, Option<String>)>> {
94 let db = self.db.lock();
95 Ok(audiofiles_core::rules::sample_tag_provenance(&db, hash)?)
96 }
97 }
98
99 impl ConfigBackend for DirectBackend {
100 // --- Config ---
101
102 fn get_config(&self, key: ConfigKey) -> BackendResult<Option<String>> {
103 let db = self.db.lock();
104 // A read error reads as "unset" the way the old direct query did, so a
105 // transient DB hiccup falls back to the caller's default rather than
106 // surfacing an error on a settings read.
107 Ok(db.get_config(key).ok().flatten())
108 }
109
110 #[instrument(skip(self, value))]
111 fn set_config(&self, key: ConfigKey, value: &str) -> BackendResult<()> {
112 let db = self.db.lock();
113 db.set_config(key, value)
114 .map_err(audiofiles_core::error::CoreError::from)?;
115 Ok(())
116 }
117
118 fn delete_config(&self, key: ConfigKey) -> BackendResult<()> {
119 let db = self.db.lock();
120 db.delete_config(key)
121 .map_err(audiofiles_core::error::CoreError::from)?;
122 Ok(())
123 }
124
125 fn set_vfs_sync_files(&self, id: VfsId, enabled: bool) -> BackendResult<()> {
126 let db = self.db.lock();
127 vfs::set_vfs_sync_files(&db, id, enabled)?;
128 Ok(())
129 }
130
131 fn get_vfs_sync_files(&self, id: VfsId) -> BackendResult<bool> {
132 let db = self.db.lock();
133 Ok(vfs::get_vfs_sync_files(&db, id)?)
134 }
135 }
136