#ExponentialBackoff
November 26, 2025 at 8:00 AM
Help me get this to compile, please
Once again I attempt something that I find trivial in Scala and end up beating my head against a wall for a half hour trying to do it in Rust. I just want to write a general fn to use backoff::retry to retry an async operation, as a sync op, meaning running the inner op with `task::block_in_place`. IOW, the operation (f) is just any async fn. Here's one of the things I've tried: pub fn run_with_retry<F, B, T, E>(backoff: ExponentialBackoff, f: F) -> Result<T, Error<E>> where F: FnMut() -> Future<Output = Result<T, Error<E>>>, { retry(backoff, || { task::block_in_place(move || runtime::Handle::current().block_on(f)) .map_err(backoff::Error::transient) }) } The error here: error[E0782]: expected a type, found a trait --> util/src/future_runner.rs:33:23 | 33 | F: FnMut() -> Future<Output = Result<T, Error<E>>>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: you can add the `dyn` keyword if you want a trait object | 33 | F: FnMut() -> dyn Future<Output = Result<T, Error<E>>>, Following the compiler directive, and then another one, we get to pub fn run_with_retry<F, B, T, E>(backoff: ExponentialBackoff, f: F) -> Result<T, Error<E>> where F: FnMut() -> (dyn Future<Output = Result<T, Error<E>>>) + std::future::Future, { retry(backoff, || { task::block_in_place(move || runtime::Handle::current().block_on(f)) .map_err(backoff::Error::transient) }) } First, I cannot grok why such type bounds are necessary: Why does F have to be both `dyn Future` _and_ `Future`? And that still doesn't compile, as `map_err` doesn't exist on Future. Yet, I can do this, directly: let result = retry(backoff(), || { block_in_place(|| { Handle::current().block_on( <some_async_fn>(), ) }) .map_err(backoff::Error::transient) }); Very often I find it difficult to take a bit of Rust code and abstract it into something general for reasons along these lines. It seems the types the compiler is working with (inferring) are often quite complex. Can someone steer me in the right direction here?
users.rust-lang.org
April 4, 2025 at 5:44 PM
Http-tower-hs — A Rust Tower-inspired middleware library for Haskell
something like this @LaurentRDC ? import Servant.Tower.Adapter import Tower.Middleware.Retry import Tower.Middleware.Timeout import Tower.Middleware.CircuitBreaker breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } env = withTowerMiddleware ( withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker ) (mkClientEnv manager baseUrl) result <- runClientM (getUsers <|> getHealth) env working on it. Trying to see if it makes sense. I use an adapter approach now. Where http-tower-hs holds the main implementation and servant-tower-hs is just a clean and simple adapter. The question begs, will this work for other libraries as well? is it generic enough? with the current change I’m also able to do generic implementation like this (which sort of answers my question): import Tower -- Wrap a database query as a Service let dbService :: Service SQL.Query [SQL.Row] dbService = Service $ \query -> do result <- try $ SQL.query conn query pure $ case result of Left err -> Left (TransportError err) Right rows -> Right rows -- Add resilience with the same middleware you'd use for HTTP breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } robust = withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker $ dbService result <- runService robust "SELECT * FROM users" which sort of should give the “aha” towards whether this is tied into http directly. The answer is no. EDIT: working on it now. Making it a mono repo and trying to make as much of the middlewares as generic if possible. EDIT2: have a PR up here if anyone is interested in looking at it. tried to make it as resusable as possible, and extensible, so it should be possible to use generically with anything not just http, and to implement more packages in the future for ex grpc etc. Refactor into multi-package mono-repo by sillychipmunk · Pull Request #7 · jarlah/http-tower-hs · GitHub
discourse.haskell.org
April 7, 2026 at 2:52 AM
Http-tower-hs — A Rust Tower-inspired middleware library for Haskell
something like this @LaurentRDC ? import Servant.Tower.Adapter import Tower.Middleware.Retry import Tower.Middleware.Timeout import Tower.Middleware.CircuitBreaker breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } env = withTowerMiddleware ( withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker ) (mkClientEnv manager baseUrl) result <- runClientM (getUsers <|> getHealth) env working on it. Trying to see if it makes sense. I use an adapter approach now. Where http-tower-hs holds the main implementation and servant-tower-hs is just a clean and simple adapter. The question begs, will this work for other libraries as well? is it generic enough? with the current change I’m also able to do generic implementation like this (which sort of answers my question): import Tower -- Wrap a database query as a Service let dbService :: Service SQL.Query [SQL.Row] dbService = Service $ \query -> do result <- try $ SQL.query conn query pure $ case result of Left err -> Left (TransportError err) Right rows -> Right rows -- Add resilience with the same middleware you'd use for HTTP breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } robust = withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker $ dbService result <- runService robust "SELECT * FROM users" which sort of should give the “aha” towards whether this is tied into http directly. The answer is no. EDIT: working on it now. Making it a mono repo and trying to make as much of the middlewares as generic if possible. EDIT2: have a PR up here if anyone is interested in looking at it. tried to make it as resusable as possible, and extensible, so it should be possible to use generically with anything not just http, and to implement more packages in the future for ex grpc etc. Refactor into multi-package mono-repo by sillychipmunk · Pull Request #7 · jarlah/http-tower-hs · GitHub
discourse.haskell.org
April 7, 2026 at 12:46 AM
Http-tower-hs — A Rust Tower-inspired middleware library for Haskell
something like this @LaurentRDC ? import Servant.Tower.Adapter import Tower.Middleware.Retry import Tower.Middleware.Timeout import Tower.Middleware.CircuitBreaker breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } env = withTowerMiddleware ( withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker ) (mkClientEnv manager baseUrl) result <- runClientM (getUsers <|> getHealth) env working on it. Trying to see if it makes sense. I use an adapter approach now. Where http-tower-hs holds the main implementation and servant-tower-hs is just a clean and simple adapter. The question begs, will this work for other libraries as well? is it generic enough? with the current change I’m also able to do generic implementation like this (which sort of answers my question): import Tower -- Wrap a database query as a Service let dbService :: Service SQL.Query [SQL.Row] dbService = Service $ \query -> do result <- try $ SQL.query conn query pure $ case result of Left err -> Left (TransportError err) Right rows -> Right rows -- Add resilience with the same middleware you'd use for HTTP breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } robust = withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker $ dbService result <- runService robust "SELECT * FROM users" which sort of should give the “aha” towards whether this is tied into http directly. The answer is no. EDIT: working on it now. Making it a mono repo and trying to make as much of the middlewares as generic if possible. EDIT2: have a PR up here if anyone is interested in looking at it. tried to make it as resusable as possible, and extensible, so it should be possible to use generically with anything not just http, and to implement more packages in the future for ex grpc etc. Refactor into multi-package mono-repo by sillychipmunk · Pull Request #7 · jarlah/http-tower-hs · GitHub
discourse.haskell.org
April 7, 2026 at 12:46 AM
Http-tower-hs — A Rust Tower-inspired middleware library for Haskell
something like this @LaurentRDC ? import Servant.Tower.Adapter import Tower.Middleware.Retry import Tower.Middleware.Timeout import Tower.Middleware.CircuitBreaker breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } env = withTowerMiddleware ( withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker ) (mkClientEnv manager baseUrl) result <- runClientM (getUsers <|> getHealth) env working on it. Trying to see if it makes sense. I use an adapter approach now. Where http-tower-hs holds the main implementation and servant-tower-hs is just a clean and simple adapter. The question begs, will this work for other libraries as well? is it generic enough? with the current change I’m also able to do generic implementation like this (which sort of answers my question): import Tower -- Wrap a database query as a Service let dbService :: Service SQL.Query [SQL.Row] dbService = Service $ \query -> do result <- try $ SQL.query conn query pure $ case result of Left err -> Left (TransportError err) Right rows -> Right rows -- Add resilience with the same middleware you'd use for HTTP breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } robust = withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker $ dbService result <- runService robust "SELECT * FROM users" which sort of should give the “aha” towards whether this is tied into http directly. The answer is no. EDIT: working on it now. Making it a mono repo and trying to make as much of the middlewares as generic if possible. EDIT2: have a PR up here if anyone is interested in looking at it. tried to make it as resusable as possible, and extensible, so it should be possible to use generically with anything not just http, and to implement more packages in the future for ex grpc etc. Refactor into multi-package mono-repo by sillychipmunk · Pull Request #7 · jarlah/http-tower-hs · GitHub
discourse.haskell.org
April 7, 2026 at 12:45 AM
Http-tower-hs — A Rust Tower-inspired middleware library for Haskell
something like this @LaurentRDC ? import Servant.Tower.Adapter import Tower.Middleware.Retry import Tower.Middleware.Timeout import Tower.Middleware.CircuitBreaker breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } env = withTowerMiddleware ( withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker ) (mkClientEnv manager baseUrl) result <- runClientM (getUsers <|> getHealth) env working on it. Trying to see if it makes sense. I use an adapter approach now. Where http-tower-hs holds the main implementation and servant-tower-hs is just a clean and simple adapter. The question begs, will this work for other libraries as well? is it generic enough? with the current change I’m also able to do generic implementation like this (which sort of answers my question): import Tower -- Wrap a database query as a Service let dbService :: Service SQL.Query [SQL.Row] dbService = Service $ \query -> do result <- try $ SQL.query conn query pure $ case result of Left err -> Left (TransportError err) Right rows -> Right rows -- Add resilience with the same middleware you'd use for HTTP breaker <- newCircuitBreaker let config = CircuitBreakerConfig { cbFailureThreshold = 5, cbCooldownPeriod = 30 } robust = withRetry (exponentialBackoff 3 0.5 2.0) . withTimeout 5000 . withCircuitBreaker config breaker $ dbService result <- runService robust "SELECT * FROM users" which sort of should give the “aha” towards whether this is tied into http directly. The answer is no. EDIT: working on it now. Making it a mono repo and trying to make as much of the middlewares as generic if possible.
discourse.haskell.org
April 7, 2026 at 12:45 AM
API integrations got you stuck? Try exponentialbackoff for retries! Prevents server overload & saves time. Pro tip: Start small, double delays. What's your biggest API headache? 👇
April 9, 2026 at 6:02 PM