1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
# Deadpool [](https://crates.io/crates/deadpool) [](https://github.com/bikeshedder/deadpool/actions?query=workflow%3ARust)  [](https://blog.rust-lang.org/2023/12/28/Rust-1.75.0.html)
Deadpool is a dead simple async pool for connections and objects
of any type.
This crate provides two implementations:
- Managed pool (`deadpool::managed::Pool`)
- Creates and recycles objects as needed
- Useful for [database connection pools](#database-connection-pools)
- Enabled via the `managed` feature in your `Cargo.toml`
- Unmanaged pool (`deadpool::unmanaged::Pool`)
- All objects either need to be created by the user and added to the
pool manually. It is also possible to create a pool from an existing
collection of objects.
- Enabled via the `unmanaged` feature in your `Cargo.toml`
## Features
| Feature | Description | Extra dependencies | Default |
| ------- | ----------- | ------------------ | ------- |
| `managed` | Enable managed pool implementation | - | yes |
| `unmanaged` | Enable unmanaged pool implementation | - | yes |
| `rt_tokio_1` | Enable support for [tokio](https://crates.io/crates/tokio) crate | `tokio/time` | no |
| `rt_async-std_1` | Enable support for [async-std](https://crates.io/crates/async-std) crate | `async-std` | no |
| `serde` | Enable support for deserializing pool config | `serde/derive` | no |
The runtime features (`rt_*`) are only needed if you need support for
timeouts. If you try to use timeouts without specifying a runtime at
pool creation the pool get methods will return an
`PoolError::NoRuntimeSpecified` error.
## Managed pool (aka. connection pool)
This is the obvious choice for connection pools of any kind. Deadpool already
comes with a couple of [database connection pools](#database-connection-pools)
which work out of the box.
### Example
```rust
use deadpool::managed;
#[derive(Debug)]
enum Error { Fail }
struct Computer {}
impl Computer {
async fn get_answer(&self) -> i32 {
42
}
}
struct Manager {}
impl managed::Manager for Manager {
type Type = Computer;
type Error = Error;
async fn create(&self) -> Result<Computer, Error> {
Ok(Computer {})
}
async fn recycle(&self, _: &mut Computer, _: &managed::Metrics) -> managed::RecycleResult<Error> {
Ok(())
}
}
type Pool = managed::Pool<Manager>;
#[tokio::main]
async fn main() {
let mgr = Manager {};
let pool = Pool::builder(mgr).build().unwrap();
let mut conn = pool.get().await.unwrap();
let answer = conn.get_answer().await;
assert_eq!(answer, 42);
}
```
### Database connection pools
Deadpool supports various database backends by implementing the
`deadpool::managed::Manager` trait. The following backends are
currently supported:
Backend | Crate | Latest Version |
------- | ----- | -------------- |
[bolt-client](https://crates.io/crates/bolt-client) | [deadpool-bolt](https://crates.io/crates/deadpool-bolt) | [](https://crates.io/crates/deadpool-bolt) |
[tokio-postgres](https://crates.io/crates/tokio-postgres) | [deadpool-postgres](https://crates.io/crates/deadpool-postgres) | [](https://crates.io/crates/deadpool-postgres) |
[lapin](https://crates.io/crates/lapin) (AMQP) | [deadpool-lapin](https://crates.io/crates/deadpool-lapin) | [](https://crates.io/crates/deadpool-lapin) |
[redis](https://crates.io/crates/redis) | [deadpool-redis](https://crates.io/crates/deadpool-redis) | [](https://crates.io/crates/deadpool-redis) |
[async-memcached](https://crates.io/crates/async-memcached) | [deadpool-memcached](https://crates.io/crates/deadpool-memcached) | [](https://crates.io/crates/deadpool-memcached) |
[rusqlite](https://crates.io/crates/rusqlite) | [deadpool-sqlite](https://crates.io/crates/deadpool-sqlite) | [](https://crates.io/crates/deadpool-sqlite) |
[diesel](https://crates.io/crates/diesel) | [deadpool-diesel](https://crates.io/crates/deadpool-diesel) | [](https://crates.io/crates/deadpool-diesel) |
[tiberius](https://crates.io/crates/tiberius) | [deadpool-tiberius](https://crates.io/crates/deadpool-tiberius) | [](https://crates.io/crates/deadpool-tiberius) |
[r2d2](https://crates.io/crates/r2d2) | [deadpool-r2d2](https://crates.io/crates/deadpool-r2d2) | [](https://crates.io/crates/deadpool-r2d2) |
[rbatis](https://crates.io/crates/rbatis) | [rbatis](https://crates.io/crates/rbatis) | [](https://crates.io/crates/rbatis) |
### Reasons for yet another connection pool
Deadpool is by no means the only pool implementation available. It does
things a little different and that is the main reason for it to exist:
- **Deadpool is compatible with any executor.** Objects are returned to the
pool using the `Drop` trait. The health of those objects is checked upon
next retrieval and not when they are returned. Deadpool never performs any
actions in the background. This is the reason why deadpool does not need
to spawn futures and does not rely on a background thread or task of any
type.
- **Identical startup and runtime behaviour**. When writing long running
application there usually should be no difference between startup and
runtime if a database connection is temporarily not available. Nobody
would expect an application to crash if the database becomes unavailable
at runtime. So it should not crash on startup either. Creating the pool
never fails and errors are only ever returned when calling `Pool::get()`.
If you really want your application to crash on startup if objects can
not be created on startup simply call
`pool.get().await.expect("DB connection failed")` right after creating
the pool.
- **Deadpool is fast.** Whenever working with locking primitives they are
held for the shortest duration possible. When returning an object to the
pool a single mutex is locked and when retrieving objects from the pool
a Semaphore is used to make this Mutex as little contested as possible.
- **Deadpool is simple.** Dead simple. There is very little API surface.
The actual code is barely 100 lines of code and lives in the two functions
`Pool::get` and `Object::drop`.
- **Deadpool is extensible.** By using `post_create`, `pre_recycle` and
`post_recycle` hooks you can customize object creation and recycling
to fit your needs.
- **Deadpool provides insights.** All objects track `Metrics` and the pool
provides a `status` method that can be used to find out details about
the inner workings.
- **Deadpool is resizable.** You can grow and shrink the pool at runtime
without requiring an application restart.
## Unmanaged pool
An unmanaged pool is useful when you can't write a manager for the objects
you want to pool or simply don't want to. This pool implementation is slightly
faster than the managed pool because it does not use a `Manager` trait to
`create` and `recycle` objects but leaves it up to the user.
### Unmanaged pool example
```rust
use deadpool::unmanaged::Pool;
struct Computer {}
impl Computer {
async fn get_answer(&self) -> i32 {
42
}
}
#[tokio::main]
async fn main() {
let pool = Pool::from(vec![
Computer {},
Computer {},
]);
let s = pool.get().await.unwrap();
assert_eq!(s.get_answer().await, 42);
}
```
## FAQ
### Why does deadpool depend on `tokio`? I thought it was runtime agnostic...
Deadpool depends on `tokio::sync::Semaphore`. This does **not** mean that
the tokio runtime or anything else of tokio is being used or will be part
of your build. You can easily check this by running the following command
in your own code base:
```shell
cargo tree --format "{p} {f}"
```
## License
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0)>
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT)>
at your option.
|