Repository: bikeshedder/deadpool (rust)

Issue:
Feature request: return the current number of connections in pool from `retain`
I'd like to track how many connections are currently in a given `Pool` so that I can gather some data and adjust the pool size. I'm pruning connections based on an idle timeout, so `retain` is perfect here. However, it takes an `Fn`, which prevents mutable state borrows. This means I can't do something like:
```rust
            let mut removed = 0;
            clone.retain(|_, metrics| {
                let retain = metrics.last_used() < idle_timeout;

                if !retain {
                    removed += 1;
                }

                retain
            });
```

The one way I can think of doing this is having `removed` be an `AtomicU64`, since that gives us access to `fetch_add` which takes an immutable receiver. That opens us up to unnecessary overhead though, what with all the atomic operations in an already-blocking closure. 

It seems like the calculation is already done, we just have to return `guard.size` from `retain()`:
```rust
    pub fn retain(&self, f: impl Fn(&M::Type, Metrics) -> bool) {
        let mut guard = self.inner.slots.lock().unwrap();
        let len_before = guard.vec.len();
        guard.vec.retain_mut(|obj| {
            if f(&obj.obj, obj.metrics) {
                true
            } else {
                self.manager().detach(&mut obj.obj);
                false
            }
        });
        guard.size -= len_before - guard.vec.len();
    }
```

I'm happy to raise a PR, or if there are any workarounds, please let me know!

Pull request:
Change retain() function to accept a FnMut
This closes #370

Patch:
diff --git a/postgres/CHANGELOG.md b/postgres/CHANGELOG.md
index 656d18d..c2cef60 100644
--- a/postgres/CHANGELOG.md
+++ b/postgres/CHANGELOG.md
@@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+## [0.14.1] - 2024-12-18
+
+- Add missing re-export of `LoadBalanceHosts`
+
 ## [0.14.0] - 2024-06-04
 
 - Add back `async_trait` to the `GenericClient` trait.
@@ -215,7 +219,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - First release
 
 <!-- next-url -->
-[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.14.0...HEAD
+[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.14.1...HEAD
+[0.14.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.14.0...deadpool-postgres-v0.14.1
 [0.14.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.13.2...deadpool-postgres-v0.14.0
 [0.13.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.13.1...deadpool-postgres-v0.13.2
 [0.13.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.13.0...deadpool-postgres-v0.13.1
diff --git a/postgres/Cargo.toml b/postgres/Cargo.toml
index 3313433..0aa9e9a 100644
--- a/postgres/Cargo.toml
+++ b/postgres/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "deadpool-postgres"
-version = "0.14.0"
+version = "0.14.1"
 edition = "2021"
 rust-version = "1.75"
 authors = ["Michael P. Jung <michael.jung@terreon.de>"]
diff --git a/postgres/src/lib.rs b/postgres/src/lib.rs
index 56c36e5..ec141ec 100644
--- a/postgres/src/lib.rs
+++ b/postgres/src/lib.rs
@@ -54,7 +54,7 @@ use tokio_postgres::{
 pub use tokio_postgres;
 
 pub use self::config::{
-    ChannelBinding, Config, ConfigError, ManagerConfig, RecyclingMethod, SslMode,
+    ChannelBinding, Config, ConfigError, LoadBalanceHosts, ManagerConfig, RecyclingMethod, SslMode,
     TargetSessionAttrs,
 };
 
diff --git a/src/managed/mod.rs b/src/managed/mod.rs
index 3c35ade..c7dd35f 100644
--- a/src/managed/mod.rs
+++ b/src/managed/mod.rs
@@ -519,7 +519,7 @@ impl<M: Manager, W: From<Object<M>>> Pool<M, W> {
     ///     }
     /// });
     /// ```
-    pub fn retain(&self, f: impl Fn(&M::Type, Metrics) -> bool) {
+    pub fn retain(&self, mut f: impl FnMut(&M::Type, Metrics) -> bool) {
         let mut guard = self.inner.slots.lock().unwrap();
         let len_before = guard.vec.len();
         guard.vec.retain_mut(|obj| {


Test patch:
diff --git a/tests/managed.rs b/tests/managed.rs
index adf8613..3aeb750 100644
--- a/tests/managed.rs
+++ b/tests/managed.rs
@@ -297,3 +297,22 @@ async fn retain() {
     pool.retain(|_, metrics| metrics.age() <= Duration::from_millis(10));
     assert_eq!(pool.status().size, 0);
 }
+
+#[tokio::test]
+async fn retain_fnmut() {
+    let mgr = Manager {};
+    let pool = Pool::builder(mgr).max_size(4).build().unwrap();
+    {
+        let _a = pool.get().await;
+        let _b = pool.get().await;
+        let _c = pool.get().await;
+        let _c = pool.get().await;
+    }
+    let mut removed = 0;
+    {
+        pool.retain(|_, _| {
+            removed += 1;
+            false
+        });
+    }
+}