Skip to content

Commit a1fe53b

Browse files
authored
Merge pull request #1 from appsignal/clear_cache
Clear cache if size is over configured percentage (defaults to 90%)
2 parents 2a5e7c3 + 6b4d682 commit a1fe53b

File tree

4 files changed

+65
-0
lines changed

4 files changed

+65
-0
lines changed

config/src/manager.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ const fn _default_overlay_size() -> u32 {
2424
10 // 10GB
2525
}
2626

27+
const fn _default_max_cache_pct() -> u8 {
28+
90
29+
}
30+
2731
#[derive(Deserialize, Debug, Clone)]
2832
pub struct Role {
2933
pub name: String,
@@ -38,6 +42,8 @@ pub struct Role {
3842
pub instance_count: u8,
3943
#[serde(default)]
4044
pub cache_paths: Vec<Utf8PathBuf>,
45+
#[serde(default = "_default_max_cache_pct")]
46+
pub max_cache_pct: u8,
4147
#[serde(default)]
4248
pub labels: Vec<String>,
4349
}

manager/src/disk.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ impl Disk {
2828
self.size as u64 * 1024
2929
}
3030

31+
pub fn size_in_kilobytes(&self) -> u64 {
32+
self.size_in_megabytes() * 1024
33+
}
34+
3135
pub fn filename(&self) -> Utf8PathBuf {
3236
match self.format {
3337
DiskFormat::Ext4 => Utf8PathBuf::from(format!("{}.ext4", &self.name)),
@@ -44,9 +48,22 @@ impl Disk {
4448
}
4549
}
4650

51+
pub fn usage_on_disk(&self) -> Result<u64, std::io::Error> {
52+
fs::du(self.path_with_filename())
53+
}
54+
4755
pub fn setup_ext4(&self) -> Result<(), std::io::Error> {
4856
fs::dd(self.path_with_filename(), self.size_in_megabytes())?;
4957
fs::mkfs_ext4(self.path_with_filename())?;
5058
Ok(())
5159
}
60+
61+
pub fn destroy(&self) -> Result<(), std::io::Error> {
62+
fs::rm_rf(self.path_with_filename())?;
63+
Ok(())
64+
}
65+
66+
pub fn usage_pct(&self) -> Result<u8, std::io::Error> {
67+
Ok((self.usage_on_disk()? * 100 / self.size_in_kilobytes()) as u8)
68+
}
5269
}

manager/src/instance.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub struct Instance {
3434
memory_size: u32,
3535
cache_paths: Vec<Utf8PathBuf>,
3636
cache: Disk,
37+
max_cache_pct: u8,
3738
idx: u8,
3839
role: String,
3940
github: GitHub,
@@ -62,6 +63,7 @@ impl Instance {
6263
memory_size: role.memory_size,
6364
cache_paths: role.cache_paths.clone(),
6465
role: role.slug(),
66+
max_cache_pct: role.max_cache_pct,
6567
labels: role.labels.clone(),
6668
github,
6769
cache,
@@ -203,6 +205,8 @@ impl Instance {
203205
let _ = rm_rf(self.work_dir.join("rootfs.ext4"));
204206
copy_sparse(&self.rootfs_image, self.work_dir.join("rootfs.ext4"))?;
205207

208+
self.try_clear_cache()?;
209+
206210
debug!(
207211
"{} Generate config: '{}'",
208212
self.log_prefix(),
@@ -225,6 +229,20 @@ impl Instance {
225229
self.child = None;
226230
}
227231

232+
pub fn try_clear_cache(&mut self) -> Result<()> {
233+
let usage_pct = self.cache.usage_pct()?;
234+
if usage_pct > self.max_cache_pct {
235+
info!(
236+
"Cache disk is over {}% ({}%), clearing cache",
237+
self.max_cache_pct, usage_pct
238+
);
239+
240+
self.cache.destroy()?;
241+
self.cache.setup()?;
242+
}
243+
Ok(())
244+
}
245+
228246
pub fn stop(&mut self) -> Result<()> {
229247
info!("{} Shutting down instance", self.log_prefix());
230248

@@ -303,6 +321,7 @@ mod tests {
303321
cpus: 1,
304322
memory_size: 1,
305323
cache_size: 1,
324+
max_cache_pct: 90,
306325
overlay_size: 1,
307326
instance_count: 1,
308327
cache_paths: Vec::new(),

util/src/fs.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,29 @@ pub fn dd(path: impl AsRef<Utf8Path>, size_in_mb: u64) -> std::io::Result<()> {
5454
Ok(())
5555
}
5656

57+
pub fn du(path: impl AsRef<Utf8Path>) -> std::io::Result<u64> {
58+
let path = path.as_ref();
59+
60+
let du_output = exec(Command::new("du").args([&path.as_str()]))
61+
.map(|o| String::from_utf8_lossy(&o.stdout).to_string())
62+
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
63+
64+
let size = du_output
65+
.split_whitespace()
66+
.next()
67+
.ok_or(std::io::Error::new(
68+
std::io::ErrorKind::Other,
69+
format!("Couldn not split '{:?}' into number and rest", du_output),
70+
))?;
71+
72+
size.parse().map_err(|e| {
73+
std::io::Error::new(
74+
std::io::ErrorKind::Other,
75+
format!("Could not parse '{:?}' to number: {}", size, e),
76+
)
77+
})
78+
}
79+
5780
#[cfg(test)]
5881
mod tests {
5982
use super::*;

0 commit comments

Comments
 (0)