Skip to content

Commit 7c38c78

Browse files
committed
delete cache using the Cache trait
1 parent 069b8ef commit 7c38c78

File tree

3 files changed

+90
-29
lines changed

3 files changed

+90
-29
lines changed

src/cache.rs

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66

77
use std::{
88
collections::BTreeSet,
9-
fs::{OpenOptions, create_dir_all},
9+
fs::{OpenOptions, create_dir_all, remove_dir_all},
1010
io::{self, BufReader},
1111
path::PathBuf,
1212
};
@@ -18,6 +18,8 @@ use tracing::{error, info, trace};
1818
pub(crate) trait Cache<K, V> {
1919
fn load(&self, key: &K) -> Result<Option<V>>;
2020
fn store(&self, key: K, value: V) -> Result<()>;
21+
22+
fn clear(&self, service: FormValue, owner: &str, repo: &str) -> Result<()>;
2123
}
2224

2325
pub(crate) trait ToQuery {
@@ -88,23 +90,36 @@ impl Persist {
8890
disk: DiskCache { settings },
8991
}
9092
}
91-
92-
/// Clear the in-memory part of the cache
93-
pub(crate) fn clear(&self) {
94-
// TODO: currently this removes everything from the cache. maybe use layered maps to clear
95-
// only for specific `service + owner + repo`
96-
self.in_memory.cache.clear();
97-
}
9893
}
9994

10095
impl Drop for Persist {
10196
fn drop(&mut self) {
10297
info!("persisting cache");
10398
for r in &self.in_memory.cache {
104-
if let Err(err) = self.disk.store(r.key().clone(), r.value().clone()) {
105-
error!(%err, key = ?r.key(), "cannot write cache to disk");
106-
} else {
107-
trace!(key = ?r.key(), "persisted");
99+
let service = *r.key();
100+
for r in r.value() {
101+
let owner = r.key();
102+
for r in r.value() {
103+
let repo = r.key();
104+
for r in r.value() {
105+
let branch = r.key();
106+
for r in r.value() {
107+
let excludes = r.key().clone();
108+
let key = CacheKey::new(
109+
service,
110+
owner.clone(),
111+
repo.clone(),
112+
branch.clone(),
113+
excludes,
114+
);
115+
if let Err(err) = self.disk.store(key, r.value().clone()) {
116+
error!(%err, key = ?r.key(), "cannot write cache to disk");
117+
} else {
118+
trace!(key = ?r.key(), "persisted");
119+
}
120+
}
121+
}
122+
}
108123
}
109124
}
110125
}
@@ -125,10 +140,26 @@ impl Cache<CacheKey, CacheEntry> for Persist {
125140
fn store(&self, key: CacheKey, value: CacheEntry) -> Result<()> {
126141
self.in_memory.store(key, value)
127142
}
143+
144+
fn clear(&self, service: FormValue, owner: &str, repo: &str) -> Result<()> {
145+
let im_res = self.in_memory.clear(service, owner, repo);
146+
let disk_res = self.disk.clear(service, owner, repo);
147+
if let Err(e) = im_res {
148+
Err(e)?
149+
} else if let Err(e) = disk_res {
150+
Err(e)?
151+
} else {
152+
Ok(())
153+
}
154+
}
128155
}
129156

130157
struct InMemoryCache {
131-
cache: DashMap<CacheKey, CacheEntry>,
158+
#[allow(clippy::type_complexity)]
159+
cache: DashMap<
160+
FormValue,
161+
DashMap<String, DashMap<String, DashMap<String, DashMap<Excludes, CacheEntry>>>>,
162+
>,
132163
}
133164

134165
impl InMemoryCache {
@@ -141,12 +172,37 @@ impl InMemoryCache {
141172

142173
impl Cache<CacheKey, CacheEntry> for InMemoryCache {
143174
fn store(&self, key: CacheKey, value: CacheEntry) -> Result<()> {
144-
self.cache.insert(key, value);
175+
self.cache
176+
.entry(key.service)
177+
.or_default()
178+
.entry(key.owner)
179+
.or_default()
180+
.entry(key.repo)
181+
.or_default()
182+
.entry(key.branch)
183+
.or_default()
184+
.insert(key.excludes, value);
145185
Ok(())
146186
}
147187

148188
fn load(&self, key: &CacheKey) -> Result<Option<CacheEntry>> {
149-
Ok(self.cache.get(key).map(|r| r.value().clone()))
189+
Ok(self.cache.get(&key.service).and_then(|c| {
190+
c.get(&key.owner).and_then(|c| {
191+
c.get(&key.repo).and_then(|c| {
192+
c.get(&key.branch)
193+
.and_then(|c| c.get(&key.excludes).map(|r| r.value().clone()))
194+
})
195+
})
196+
}))
197+
}
198+
199+
fn clear(&self, service: FormValue, owner: &str, repo: &str) -> Result<()> {
200+
if let Some(c) = self.cache.get(&service)
201+
&& let Some(c) = c.value().get(owner)
202+
{
203+
c.value().remove(repo);
204+
}
205+
Ok(())
150206
}
151207
}
152208

@@ -187,6 +243,23 @@ impl Cache<CacheKey, CacheEntry> for DiskCache {
187243
)?;
188244
Ok(())
189245
}
246+
247+
fn clear(&self, service: FormValue, owner: &str, repo: &str) -> Result<()> {
248+
let cache_dir = self
249+
.settings
250+
.cachedir
251+
.join(service.service())
252+
.join(owner)
253+
.join(repo);
254+
remove_dir_all(cache_dir).or_else(|e| {
255+
if e.kind() == io::ErrorKind::NotFound {
256+
Ok(())
257+
} else {
258+
Err(e)
259+
}
260+
})?;
261+
Ok(())
262+
}
190263
}
191264

192265
#[derive(Serialize, Deserialize, Clone, Debug)]

src/http/hoc.rs

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::{
22
State,
3-
cache::{Excludes, Persist, ToQuery},
3+
cache::{Cache, Excludes, Persist, ToQuery},
44
error::Result,
55
hoc, http,
66
service::Service,
@@ -110,15 +110,7 @@ where
110110
data.1.to_lowercase()
111111
);
112112
info!("Deleting cache and repository");
113-
let cache_dir = state.cache().join(&repo);
114113
let repo_dir = state.repos().join(&repo);
115-
std::fs::remove_dir_all(cache_dir).or_else(|e| {
116-
if e.kind() == io::ErrorKind::NotFound {
117-
Ok(())
118-
} else {
119-
Err(e)
120-
}
121-
})?;
122114
std::fs::remove_dir_all(repo_dir).or_else(|e| {
123115
if e.kind() == io::ErrorKind::NotFound {
124116
Ok(())
@@ -128,7 +120,7 @@ where
128120
})?;
129121
repo_count.fetch_sub(1, Ordering::Relaxed);
130122

131-
cache.clear();
123+
cache.clear(T::form_value(), data.0.as_str(), data.1.as_str())?;
132124

133125
let branch_query = branch.branch.as_ref().map(|b| format!("branch={b}"));
134126

src/lib.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,6 @@ impl State {
3636
fn repos(&self) -> &Path {
3737
&self.settings.repodir
3838
}
39-
40-
fn cache(&self) -> &Path {
41-
&self.settings.cachedir
42-
}
4339
}
4440

4541
#[allow(clippy::unused_async)]

0 commit comments

Comments
 (0)