Skip to content

Commit

Permalink
fix: restore try_many_times workaround
Browse files Browse the repository at this point in the history
Even though r2d2 connection pool is removed,
deleting accounts still fails in Windows CI.

This reverts commit e88f21c.
`try_many_times` documentation is modified to explain
why the workaround is still needed.
  • Loading branch information
link2xt committed Oct 26, 2023
1 parent 5fb92c7 commit 1478f32
Showing 1 changed file with 36 additions and 4 deletions.
40 changes: 36 additions & 4 deletions src/accounts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! # Account manager module.
use std::collections::BTreeMap;
use std::future::Future;
use std::path::{Path, PathBuf};

use anyhow::{ensure, Context as _, Result};
Expand Down Expand Up @@ -155,7 +156,7 @@ impl Accounts {
if let Some(cfg) = self.config.get_account(id) {
let account_path = self.dir.join(cfg.dir);

fs::remove_dir_all(&account_path)
try_many_times(|| fs::remove_dir_all(&account_path))
.await
.context("failed to remove account data")?;
}
Expand Down Expand Up @@ -191,10 +192,10 @@ impl Accounts {
fs::create_dir_all(self.dir.join(&account_config.dir))
.await
.context("failed to create dir")?;
fs::rename(&dbfile, &new_dbfile)
try_many_times(|| fs::rename(&dbfile, &new_dbfile))
.await
.context("failed to rename dbfile")?;
fs::rename(&blobdir, &new_blobdir)
try_many_times(|| fs::rename(&blobdir, &new_blobdir))
.await
.context("failed to rename blobdir")?;
if walfile.exists() {
Expand All @@ -219,7 +220,7 @@ impl Accounts {
}
Err(err) => {
let account_path = std::path::PathBuf::from(&account_config.dir);
fs::remove_dir_all(&account_path)
try_many_times(|| fs::remove_dir_all(&account_path))
.await
.context("failed to remove account data")?;
self.config.remove_account(account_config.id).await?;
Expand Down Expand Up @@ -560,6 +561,37 @@ impl Config {
}
}

/// Spend up to 1 minute trying to do the operation.
///
/// Even if Delta Chat itself does not hold the file lock,
/// there may be other processes such as antivirus,
/// or the filesystem may be network-mounted.
///
/// Without this workaround removing account may fail on Windows with an error
/// "The process cannot access the file because it is being used by another process. (os error 32)".
async fn try_many_times<F, Fut, T>(f: F) -> std::result::Result<(), T>
where
F: Fn() -> Fut,
Fut: Future<Output = std::result::Result<(), T>>,
{
let mut counter = 0;
loop {
counter += 1;

if let Err(err) = f().await {
if counter > 60 {
return Err(err);
}

// Wait 1 second and try again.
tokio::time::sleep(std::time::Duration::from_millis(1000)).await;
} else {
break;
}
}
Ok(())
}

/// Configuration of a single account.
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
struct AccountConfig {
Expand Down

0 comments on commit 1478f32

Please sign in to comment.