From 0c5ef6abcf1b59c62f99ab60f44c90c2e5ddd267 Mon Sep 17 00:00:00 2001 From: Aaryamann Challani <43716372+rymnc@users.noreply.github.com> Date: Fri, 25 Aug 2023 05:34:20 +0530 Subject: [PATCH] fix(rln): use config.open instead of sled::open (#209) fix: include tries & exp backoff to catch WouldBlock errors --- utils/src/pm_tree/sled_adapter.rs | 48 ++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/utils/src/pm_tree/sled_adapter.rs b/utils/src/pm_tree/sled_adapter.rs index 96dc16c..c35533f 100644 --- a/utils/src/pm_tree/sled_adapter.rs +++ b/utils/src/pm_tree/sled_adapter.rs @@ -2,29 +2,51 @@ use pmtree::*; use sled::Db as Sled; use std::collections::HashMap; +use std::thread; +use std::time::Duration; pub struct SledDB(Sled); +impl SledDB { + fn new_with_tries(config: ::Config, tries: u32) -> PmtreeResult { + // If we've tried more than 10 times, we give up and return an error. + if tries >= 10 { + return Err(PmtreeErrorKind::DatabaseError( + DatabaseErrorKind::CustomError(format!( + "Cannot create database: exceeded maximum retry attempts. {config:#?}" + )), + )); + } + match config.open() { + Ok(db) => Ok(SledDB(db)), + Err(e) if e.to_string().contains("WouldBlock") => { + // try till the fd is freed + // sleep for 10^tries milliseconds, then recursively try again + thread::sleep(Duration::from_millis(10u64.pow(tries))); + Self::new_with_tries(config, tries + 1) + } + Err(e) => { + // On any other error, we return immediately. + Err(PmtreeErrorKind::DatabaseError( + DatabaseErrorKind::CustomError(format!( + "Cannot create database: {e} {config:#?}" + )), + )) + } + } + } +} + impl Database for SledDB { type Config = sled::Config; fn new(config: Self::Config) -> PmtreeResult { - let db: Sled = match config.open() { - Ok(db) => db, - Err(e) => { - return Err(PmtreeErrorKind::DatabaseError( - DatabaseErrorKind::CustomError(format!( - "Cannot create database: {e} {config:#?}", - )), - )) - } - }; - - Ok(SledDB(db)) + let db = Self::new_with_tries(config, 0)?; + Ok(db) } fn load(config: Self::Config) -> PmtreeResult { - let db: Sled = match sled::open(&config.path) { + let db = match config.open() { Ok(db) => db, Err(e) => { return Err(PmtreeErrorKind::DatabaseError(