diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 09bb01a1..b393d92e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,9 +1,14 @@ -# [Choice] Debian OS version (use bullseye on local arm64/Apple Silicon): buster, bullseye, bookworm -ARG VARIANT="bookworm" -FROM mcr.microsoft.com/devcontainers/rust:1-${VARIANT} +FROM mcr.microsoft.com/devcontainers/base:ubuntu-22.04 # Include lld linker to improve build times either by using environment variable # RUSTFLAGS="-C link-arg=-fuse-ld=lld" or with Cargo's configuration file (i.e see .cargo/config.toml). RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ - && apt-get -y install clang lld \ + && apt-get -y install clang lld libsqlite3-dev libmariadb-dev-compat libmariadb-dev libpq-dev pkg-config \ && apt-get autoremove -y && apt-get clean -y + +USER vscode + +RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain 1.75 --no-modify-path -y + +RUN /home/vscode/.cargo/bin/cargo install cargo-release +RUN /home/vscode/.cargo/bin/cargo install --locked cargo-outdated \ No newline at end of file diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index fe6631fe..dd9fe7d7 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -5,7 +5,6 @@ "dockerComposeFile": "docker-compose.yml", "service": "app", "workspaceFolder": "/workspace", - // Configure tool-specific properties. "customizations": { // Configure properties specific to VS Code. @@ -19,25 +18,24 @@ }, "rust-analyzer.checkOnSave.command": "clippy" }, - // Add the IDs of extensions you want installed when the container is created. "extensions": [ - "vadimcn.vscode-lldb", - "mutantdino.resourcemonitor", - "rust-lang.rust-analyzer", - "tamasfe.even-better-toml", - "serayuzgur.crates", - "ms-azuretools.vscode-docker" - ] + "vadimcn.vscode-lldb", + "mutantdino.resourcemonitor", + "rust-lang.rust-analyzer", + "tamasfe.even-better-toml", + "serayuzgur.crates", + "ms-azuretools.vscode-docker" + ] } }, - // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [5432], - // Use 'postCreateCommand' to run commands after the container is created. // "postCreateCommand": "rustc --version", - // Comment out to connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode" -} + "remoteUser": "vscode", + "remoteEnv": { + "PATH": "${containerEnv:PATH}:/home/vscode/.cargo/bin" + } +} \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 35cda9ae..737bba96 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -41,7 +41,7 @@ services: # (Adding the "ports" property to this file will not forward from a Codespace.) postgres: - image: postgres:15-alpine + image: postgres:16-alpine restart: unless-stopped volumes: - postgres-data:/var/lib/postgresql/data diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 070dc673..11b66101 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,6 @@ jobs: - deadpool-postgres - deadpool-r2d2 - deadpool-redis - - deadpool-redis-cluster - deadpool-sqlite # Examples - example-postgres-actix-web @@ -102,7 +101,6 @@ jobs: - lapin - postgres - redis - - redis-cluster - sqlite feature: - rt_tokio_1 @@ -131,22 +129,45 @@ jobs: - run: cargo check -p deadpool-${{ matrix.crate }} --features ${{ matrix.feature }} + check-integration-wasm: + name: Check integration (WebAssembly) + strategy: + fail-fast: false + matrix: + crate: + - postgres + feature: + - --features rt_tokio_1 + - --features serde --features rt_tokio_1 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + target: wasm32-unknown-unknown + + - run: cargo check -p deadpool-${{ matrix.crate }} + --no-default-features + ${{ matrix.feature }} + --target wasm32-unknown-unknown + msrv: name: MSRV strategy: fail-fast: false matrix: include: - - { crate: deadpool-runtime, msrv: '1.63.0' } - - { crate: deadpool-sync, msrv: '1.63.0' } - - { crate: deadpool, msrv: '1.63.0' } - - { crate: deadpool-arangodb, msrv: '1.63.0' } - - { crate: deadpool-diesel, msrv: '1.63.0' } - - { crate: deadpool-lapin, msrv: '1.63.0' } - - { crate: deadpool-postgres, msrv: '1.63.0' } - - { crate: deadpool-redis, msrv: '1.63.0' } - - { crate: deadpool-redis-cluster, msrv: '1.63.0' } - - { crate: deadpool-sqlite, msrv: '1.63.0' } + - { crate: deadpool-runtime, msrv: '1.75.0' } + - { crate: deadpool-sync, msrv: '1.75.0' } + - { crate: deadpool, msrv: '1.75.0' } + - { crate: deadpool-arangodb, msrv: '1.75.0' } + - { crate: deadpool-diesel, msrv: '1.78.0' } + - { crate: deadpool-lapin, msrv: '1.75.0' } + - { crate: deadpool-postgres, msrv: '1.75.0' } + - { crate: deadpool-redis, msrv: '1.75.0' } + - { crate: deadpool-sqlite, msrv: '1.75.0' } runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 @@ -177,7 +198,6 @@ jobs: - deadpool-lapin - deadpool-postgres - deadpool-redis - - deadpool-redis-cluster - deadpool-sqlite runs-on: ubuntu-latest services: @@ -260,7 +280,6 @@ jobs: - deadpool-lapin - deadpool-postgres - deadpool-redis - - deadpool-redis-cluster - deadpool-sqlite runs-on: ubuntu-latest steps: diff --git a/CHANGELOG.md b/CHANGELOG.md index 77d3a014..a7a69a51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,37 @@ -# Change Log +# Changelog -## v0.10.0 +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] + +## [0.12.1] - 2024-05-07 + +- Add WASM support + +## [0.12.0] - 2024-05-04 + +- Add `Send` to `Manager::Type` and `Manager::Error` associated types +- Add `Send` to `Manager::create` and `Manager::recycle` return types + +## [0.11.2] - 2024-04-10 + +- Make `Timeouts::new` and `Timeouts::wait_millis` functions const fns + +## [0.11.1] - 2024-04-06 + +- Remove unused `console` dependency + +## [0.11.0] - 2024-04-01 + +- Remove `async_trait` dependency +- Bump up MSRV to `1.75` + +## [0.10.0] - 2023-09-25 - Remove unreachable enum variant `BuildError::Backend` - Split `Status.available` into `available` and `waiting`. @@ -16,148 +47,181 @@ - Remove deprecated `managed::Pool::try_get` method. - Bump up MSRV to `1.63` to match the one of `tokio`. -## v0.9.5 +## [0.9.5] - 2022-05-20 - Fix bug causing the pool to exceed its `max_size` in the case of a recycling error. - Fix panic caused by an integer overflow in the case of a failing `post_create` hook. -## v0.9.4 +## [0.9.4] - 2022-04-27 - Fix `HookError` and `HookErrorCause` in re-exports -## v0.9.3 +## [0.9.3] - 2022-04-12 -* Add `Pool::retain` method -* Fix `Pool::get_timeouts` method -* Deprecate `managed::Pool::try_get` -* Add `Pool::timeouts` method +- Add `Pool::retain` method +- Fix `Pool::get_timeouts` method +- Deprecate `managed::Pool::try_get` +- Add `Pool::timeouts` method -## v0.9.2 +## [0.9.2] - 2021-11-15 -* `PoolConfig` now implements `Serialize` +- `PoolConfig` now implements `Serialize` -## v0.9.1 +## [0.9.1] - 2021-10-26 -* Deprecate `managed::sync` module in favor of `deadpool-sync` crate -* Extract `runtime` module as separate `deadpool-runtime` crate +- Deprecate `managed::sync` module in favor of `deadpool-sync` crate +- Extract `runtime` module as separate `deadpool-runtime` crate -## v0.9.0 +## [0.9.0] - 2021-10-18 -* __Breaking:__ Replace `config` feature with `serde` (opted out by default) -* Fix `std::error::Error::source` implementations for library errors -* Add `Runtime::spawn_blocking` method -* Add `Runtime::spawn_blocking_background` method -* Remove `Runtime::None` in favor of `Option` -* Remove `Pool::new` method -* Add `Pool::builder` method and `PoolBuilder` struct -* Add `Object::metrics` method and `Metrics` struct -* Update `tokio` dependency to version `1.5.0` -* Add `post_create`, `pre_recycle` and `post_recycle` hooks -* Add `Pool::resize` method -* Add `managed_reexports` macro +- __Breaking:__ Replace `config` feature with `serde` (opted out by default) +- Fix `std::error::Error::source` implementations for library errors +- Add `Runtime::spawn_blocking` method +- Add `Runtime::spawn_blocking_background` method +- Remove `Runtime::None` in favor of `Option` +- Remove `Pool::new` method +- Add `Pool::builder` method and `PoolBuilder` struct +- Add `Object::metrics` method and `Metrics` struct +- Update `tokio` dependency to version `1.5.0` +- Add `post_create`, `pre_recycle` and `post_recycle` hooks +- Add `Pool::resize` method +- Add `managed_reexports` macro -## v0.8.2 +## [0.8.2] - 2021-07-16 -* Add `deadpool-diesel` to README -* Add `Sync + Send` as supertrait to `Manager` -* Fix usage of `PhantomData` in `Pool` struct: `Pool is now `Sync` regardless of the wrapper. +- Add `deadpool-diesel` to README +- Add `Sync + Send` as supertrait to `Manager` +- Fix usage of `PhantomData` in `Pool` struct: `Pool is now `Sync` regardless of the wrapper. -## v0.8.1 +## [0.8.1] - 2021-07-04 -* Add `Object::pool` method +- Add `Object::pool` method -## v0.8.0 +## [0.8.0] - 2021-05-21 -* Add support for closing pools -* Replace `crossbeam-queue` by `Mutex>` -* Fix invalid `size` and `available` counts when recycling fails -* Update `config` dependency to version `0.11` -* Remove deprecated `from_env` methods -* Add support for wrappers returned by the pool -* Use associated types for traits +- Add support for closing pools +- Replace `crossbeam-queue` by `Mutex>` +- Fix invalid `size` and `available` counts when recycling fails +- Update `config` dependency to version `0.11` +- Remove deprecated `from_env` methods +- Add support for wrappers returned by the pool +- Use associated types for traits -## v0.7.0 +## [0.7.0] - 2020-12-26 -* Update `tokio` dependency to version `1` +- Update `tokio` dependency to version `1` -## v0.6.0 +## [0.6.0] - 2020-11-04 -* Update `tokio` dependency to version `0.3` -* Update `crossbeam-queue` dependency to version `0.3` -* Remove deprecated `deadpool::*` types -* Add `deadpool-memcached` to README +- Update `tokio` dependency to version `0.3` +- Update `crossbeam-queue` dependency to version `0.3` +- Remove deprecated `deadpool::*` types +- Add `deadpool-memcached` to README -## v0.5.2 +## [0.5.2] - 2020-07-14 -* Deprecate `managed::Config::from_env` -* Deprecate `unmanaged::Config::from_env` +- Deprecate `managed::Config::from_env` +- Deprecate `unmanaged::Config::from_env` -## v0.5.1 +## [0.5.1] - 2020-01-18 -* Add `managed::Object::take` method +- Add `managed::Object::take` method -## v0.5.0 +## [0.5.0] - 2020-01-16 -* Move current pool implementation into `managed` module -* Add unmanaged version of the `Pool` which does not use a `Manager` +- Move current pool implementation into `managed` module +- Add unmanaged version of the `Pool` which does not use a `Manager` to create and recycle objects. -* Add feature flags `"managed"` and `"unmanaged"` to enable only parts +- Add feature flags `"managed"` and `"unmanaged"` to enable only parts of this crate. -* Add `max_size` to pool `Status` -* Add support for `config` crate +- Add `max_size` to pool `Status` +- Add support for `config` crate -## v0.4.3 +## [0.4.3] - 2019-12-23 -* Add `std::error::Error` implementation for `PoolError` and `RecycleError`. +- Add `std::error::Error` implementation for `PoolError` and `RecycleError`. This makes it more convenient to use the `?` operator. -## v0.4.2 +## [0.4.2] - 2019-12-23 -* Replace `tokio::sync::mpsc::channel` by `crossbeam_queue::ArrayQueue` +- Replace `tokio::sync::mpsc::channel` by `crossbeam_queue::ArrayQueue` which gets rid of the mutex when fetching an object from the pool. -## v0.4.1 +## [0.4.1] - 2019-12-19 -* Make `Pool::timeout_get` public +- Make `Pool::timeout_get` public -## v0.4.0 +## [0.4.0] - 2019-12-19 -* Add support for timeouts -* Make fields of pool status public -* Fix possible deadlock and make implementation a lot simpler by using +- Add support for timeouts +- Make fields of pool status public +- Fix possible deadlock and make implementation a lot simpler by using the new tokio `Semaphore` and `Receiver::try_recv`. -* Add `Pool::try_get` and `Pool::timeout_get` functions +- Add `Pool::try_get` and `Pool::timeout_get` functions -## v0.3.0 +## [0.3.0] - 2019-12-13 -* Add `deadpool-lapin` to README -* Add `deadpool-redis` to README -* Fix possible stale state and deadlock if a future calling `Pool::get` is +- Add `deadpool-lapin` to README +- Add `deadpool-redis` to README +- Fix possible stale state and deadlock if a future calling `Pool::get` is aborted. This is related to -* Make recycling more robust by changing the `Manager::recycle` to a non +- Make recycling more robust by changing the `Manager::recycle` to a non consuming API. -## v0.2.3 +## [0.2.3] - 2019-12-02 -* Add documentation for `docs.rs` -* Remove `PoolInner` and `PoolSize` struct from public interface -* Improve example in `README.md` and crate root +- Add documentation for `docs.rs` +- Remove `PoolInner` and `PoolSize` struct from public interface +- Improve example in `README.md` and crate root -## v0.2.2 +## [0.2.2] - 2019-12-02 -* Update to `tokio 0.2` +- Update to `tokio 0.2` -## v0.2.1 +## 0.2.1 -* Version skipped; only `tokio-postgres` was updated. +- Version skipped; only `tokio-postgres` was updated. -## v0.2.0 +## [0.2.0] - 2019-11-14 -* Split `deadpool` and `deadpool-postgres` in separate crates instead of +- Split `deadpool` and `deadpool-postgres` in separate crates instead of one with feature flags. -## v0.1.0 - -* First release +## [0.1.0] - 2019-11-14 + +- First release + + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.12.1...HEAD +[0.12.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.12.0...deadpool-v0.12.1 +[0.12.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.11.2...deadpool-v0.12.0 +[0.11.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.11.1...deadpool-v0.11.2 +[0.11.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.11.0...deadpool-v0.11.1 +[0.11.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.10.0...deadpool-v0.11.0 +[0.10.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.9.5...deadpool-v0.10.0 +[0.9.5]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.9.4...deadpool-v0.9.5 +[0.9.4]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.9.3...deadpool-v0.9.4 +[0.9.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.9.2...deadpool-v0.9.3 +[0.9.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.9.1...deadpool-v0.9.2 +[0.9.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.9.0...deadpool-v0.9.1 +[0.9.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.8.2...deadpool-v0.9.0 +[0.8.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.8.1...deadpool-v0.8.2 +[0.8.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.8.0...deadpool-v0.8.1 +[0.8.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.7.0...deadpool-v0.8.0 +[0.7.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.6.0...deadpool-v0.7.0 +[0.6.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.5.2...deadpool-v0.6.0 +[0.5.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.5.1...deadpool-v0.5.2 +[0.5.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.5.0...deadpool-v0.5.1 +[0.5.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.4.4...deadpool-v0.5.0 +[0.4.4]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.4.3...deadpool-v0.4.4 +[0.4.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.4.2...deadpool-v0.4.3 +[0.4.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.4.1...deadpool-v0.4.2 +[0.4.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.4.0...deadpool-v0.4.1 +[0.4.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.3.0...deadpool-v0.4.0 +[0.3.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.2.3...deadpool-v0.3.0 +[0.2.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.2.2...deadpool-v0.2.3 +[0.2.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.2.1...deadpool-v0.2.2 +[0.2.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-v0.1.0...deadpool-v0.2.0 +[0.1.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-v0.1.0 diff --git a/Cargo.toml b/Cargo.toml index f9090f64..78503e37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool" -version = "0.10.0" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.12.1" +edition = "2021" +rust-version = "1.75" authors = ["Michael P. Jung "] description = "Dead simple async pool" keywords = ["async", "database", "pool"] @@ -17,15 +16,13 @@ rustdoc-args = ["--cfg", "docsrs"] [features] default = ["managed", "unmanaged"] -managed = ["async-trait"] +managed = [] unmanaged = [] rt_tokio_1 = ["deadpool-runtime/tokio_1"] rt_async-std_1 = ["deadpool-runtime/async-std_1"] [dependencies] num_cpus = "1.11.1" -# `managed` feature -async-trait = { version = "0.1.17", optional = true } # `serde` feature serde = { version = "1.0.103", features = ["derive"], optional = true } # `rt_async-std_1` feature @@ -37,9 +34,9 @@ tokio = { version = "1.0", features = ["sync"] } [dev-dependencies] async-std = { version = "1.0", features = ["attributes"] } -config = { version = "0.13", features = ["json"] } -criterion = { version = "0.3.4", features = ["html_reports", "async_tokio"] } -itertools = "0.10.3" +config = { version = "0.14", features = ["json"] } +criterion = { version = "0.5", features = ["html_reports", "async_tokio"] } +itertools = "0.12" tokio = { version = "1.5.0", features = [ "macros", "rt", @@ -64,7 +61,6 @@ members = [ "postgres", "r2d2", "redis", - "redis-cluster", "runtime", "sqlite", "sync", diff --git a/README.md b/README.md index db9d75b5..d5393453 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Deadpool [![Latest Version](https://img.shields.io/crates/v/deadpool.svg)](https://crates.io/crates/deadpool) [![Build Status](https://img.shields.io/github/actions/workflow/status/bikeshedder/deadpool/ci.yml?branch=master)](https://github.com/bikeshedder/deadpool/actions?query=workflow%3ARust) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool [![Latest Version](https://img.shields.io/crates/v/deadpool.svg)](https://crates.io/crates/deadpool) [![Build Status](https://img.shields.io/github/actions/workflow/status/bikeshedder/deadpool/ci.yml?branch=master)](https://github.com/bikeshedder/deadpool/actions?query=workflow%3ARust) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](https://blog.rust-lang.org/2023/12/28/Rust-1.75.0.html) Deadpool is a dead simple async pool for connections and objects @@ -21,7 +21,7 @@ This crate provides two implementations: | Feature | Description | Extra dependencies | Default | | ------- | ----------- | ------------------ | ------- | -| `managed` | Enable managed pool implementation | `async-trait` | yes | +| `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 | @@ -41,7 +41,6 @@ which work out of the box. ### Example ```rust -use async_trait::async_trait; use deadpool::managed; #[derive(Debug)] @@ -57,7 +56,6 @@ impl Computer { struct Manager {} -#[async_trait] impl managed::Manager for Manager { type Type = Computer; type Error = Error; @@ -95,7 +93,6 @@ Backend | Crate | Latest Version | [tokio-postgres](https://crates.io/crates/tokio-postgres) | [deadpool-postgres](https://crates.io/crates/deadpool-postgres) | [![Latest Version](https://img.shields.io/crates/v/deadpool-postgres.svg)](https://crates.io/crates/deadpool-postgres) | [lapin](https://crates.io/crates/lapin) (AMQP) | [deadpool-lapin](https://crates.io/crates/deadpool-lapin) | [![Latest Version](https://img.shields.io/crates/v/deadpool-lapin.svg)](https://crates.io/crates/deadpool-lapin) | [redis](https://crates.io/crates/redis) | [deadpool-redis](https://crates.io/crates/deadpool-redis) | [![Latest Version](https://img.shields.io/crates/v/deadpool-redis.svg)](https://crates.io/crates/deadpool-redis) | -[redis_cluster_async](https://crates.io/crates/redis_cluster_async) | [deadpool-redis-cluster](https://crates.io/crates/deadpool-redis-cluster) | [![Latest Version](https://img.shields.io/crates/v/deadpool-redis.svg)](https://crates.io/crates/deadpool-redis-cluster) | [async-memcached](https://crates.io/crates/async-memcached) | [deadpool-memcached](https://crates.io/crates/deadpool-memcached) | [![Latest Version](https://img.shields.io/crates/v/deadpool-memcached.svg)](https://crates.io/crates/deadpool-memcached) | [rusqlite](https://crates.io/crates/rusqlite) | [deadpool-sqlite](https://crates.io/crates/deadpool-sqlite) | [![Latest Version](https://img.shields.io/crates/v/deadpool-sqlite.svg)](https://crates.io/crates/deadpool-sqlite) | [diesel](https://crates.io/crates/diesel) | [deadpool-diesel](https://crates.io/crates/deadpool-diesel) | [![Latest Version](https://img.shields.io/crates/v/deadpool-diesel.svg)](https://crates.io/crates/deadpool-diesel) | diff --git a/benches/managed.rs b/benches/managed.rs index c55084b3..432cc59e 100644 --- a/benches/managed.rs +++ b/benches/managed.rs @@ -44,7 +44,6 @@ const CONFIGS: &[Config] = &[ struct Manager {} -#[async_trait::async_trait] impl deadpool::managed::Manager for Manager { type Type = (); type Error = (); diff --git a/diesel/CHANGELOG.md b/diesel/CHANGELOG.md index bf594f21..b996e21e 100644 --- a/diesel/CHANGELOG.md +++ b/diesel/CHANGELOG.md @@ -1,48 +1,85 @@ -# Change Log +# Changelog -## v0.5.0 +All notable changes to this project will be documented in this file. -* Update `deadpool` dependency to version `0.10` -* Add `tracing` feature -* Check for open transactions before recycling connections -* Allow to configure a custom recycle check function to customize ping queries for different database backends -* Bump up MSRV to `1.63` to match the one of `tokio` +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.4.1 + -* Fix error handling when recycling connections +## [Unreleased] -## v0.4.0 +- Fix deprecation warning introduced in diesel `2.2.0` +- Update `diesel` dependency to version `2.2.0` +- Bump up MSRV to `1.78` -* Update `diesel` dependency to version `2.0.0` +## [0.6.1] - 2024-05-04 -## v0.3.1 +- Update `deadpool` dependency to version `0.12` -* Add missing reexports from the `mysql` and `postgres` modules. +## [0.6.0] - 2024-04-01 -## v0.3.0 +- Update `deadpool` dependency to version `0.11` +- Remove `async_trait` dependency +- Bump up MSRV to `1.75` -* __Breaking:__ Replace `deadpool::managed::sync` by +## [0.5.0] - 2023-09-26 + +- Update `deadpool` dependency to version `0.10` +- Add `tracing` feature +- Check for open transactions before recycling connections +- Allow to configure a custom recycle check function to customize ping queries for different database backends +- Bump up MSRV to `1.63` to match the one of `tokio` + +## [0.4.1] - 2022-12-09 + +- Fix error handling when recycling connections + +## [0.4.0] - 2022-09-12 + +- Update `diesel` dependency to version `2.0.0` + +## [0.3.1] - 2021-11-03 + +- Add missing reexports from the `mysql` and `postgres` modules. + +## [0.3.0] - 2021-10-26 + +- __Breaking:__ Replace `deadpool::managed::sync` by `deadpool-sync::SyncWrapper` which fixes the return type of the `interact` method. -## v0.2.0 +## [0.2.0] - 2021-07-18 -* __Breaking:__ Replace `config` feature with `serde` (opted out by default) -* Fix `std::error::Error::source` implementations for library errors -* Remove unused `tokio` dependency -* Async unaware diesel connections are now wrapped inside +- __Breaking:__ Replace `config` feature with `serde` (opted out by default) +- Fix `std::error::Error::source` implementations for library errors +- Remove unused `tokio` dependency +- Async unaware diesel connections are now wrapped inside a `deadpool::managed::sync::SyncWrapper` which ensures that all database operations are run in a separate threads. -## v0.1.2 +## [0.1.2] - 2021-07-16 + +- Remove `unsafe impl` by better usage of `PhantomData` -* Remove `unsafe impl` by better usage of `PhantomData` +## [0.1.1] - 2021-07-14 -## v0.1.1 +- Fix title and crates.io badge in README -* Fix title and crates.io badge in README +## [0.1.0] - 2021-07-14 -## v0.1.0 +- First release -* First release + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.6.1...HEAD +[0.6.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.6.0...deadpool-diesel-v0.6.1 +[0.6.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.5.0...deadpool-diesel-v0.6.0 +[0.5.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.4.1...deadpool-diesel-v0.5.0 +[0.4.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.4.0...deadpool-diesel-v0.4.1 +[0.4.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.3.1...deadpool-diesel-v0.4.0 +[0.3.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.3.0...deadpool-diesel-v0.3.1 +[0.3.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.2.0...deadpool-diesel-v0.3.0 +[0.2.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.1.2...deadpool-diesel-v0.2.0 +[0.1.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.1.1...deadpool-diesel-v0.1.2 +[0.1.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-diesel-v0.1.0...deadpool-diesel-v0.1.1 +[0.1.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-diesel-v0.1.0 \ No newline at end of file diff --git a/diesel/Cargo.toml b/diesel/Cargo.toml index fc9f4499..8080e663 100644 --- a/diesel/Cargo.toml +++ b/diesel/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-diesel" -version = "0.5.0" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.6.1" +edition = "2021" +rust-version = "1.78" authors = ["Michael P. Jung "] description = "Dead simple async pool for diesel" keywords = ["async", "database", "pool", "diesel"] @@ -26,12 +25,12 @@ serde = ["deadpool/serde"] tracing = ["deadpool-sync/tracing"] [dependencies] -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ +deadpool = { path = "../", version = "0.12.0", default-features = false, features = [ "managed", ] } deadpool-sync = { path = "../sync", version = "0.1.1" } -diesel = { version = "2.0.0", default-features = false } +diesel = { version = "2.2.0", default-features = false } [dev-dependencies] -diesel = { version = "2.0.0", default-features = false, features = ["sqlite"] } +diesel = { version = "2.2.0", default-features = false, features = ["sqlite"] } tokio = { version = "1.0", features = ["macros", "rt", "rt-multi-thread"] } diff --git a/diesel/LICENSE-APACHE b/diesel/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/diesel/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/diesel/LICENSE-MIT b/diesel/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/diesel/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/diesel/README.md b/diesel/README.md index 21174720..9e7d5b62 100644 --- a/diesel/README.md +++ b/diesel/README.md @@ -1,4 +1,4 @@ -# Deadpool for Diesel [![Latest Version](https://img.shields.io/crates/v/deadpool-diesel.svg)](https://crates.io/crates/deadpool-diesel) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for Diesel [![Latest Version](https://img.shields.io/crates/v/deadpool-diesel.svg)](https://crates.io/crates/deadpool-diesel) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. diff --git a/diesel/src/manager.rs b/diesel/src/manager.rs index 98e3af56..25c26c82 100644 --- a/diesel/src/manager.rs +++ b/diesel/src/manager.rs @@ -1,7 +1,6 @@ use std::{borrow::Cow, fmt, marker::PhantomData, sync::Arc}; use deadpool::{ - async_trait, managed::{self, Metrics, RecycleError, RecycleResult}, Runtime, }; @@ -129,11 +128,10 @@ where } } -#[async_trait] impl managed::Manager for Manager where C: diesel::Connection + 'static, - diesel::dsl::BareSelect>: + diesel::helper_types::select>: QueryFragment, diesel::query_builder::SqlQuery: QueryFragment, { @@ -150,14 +148,14 @@ where async fn recycle(&self, obj: &mut Self::Type, _: &Metrics) -> RecycleResult { if obj.is_mutex_poisoned() { - return Err(RecycleError::StaticMessage( + return Err(RecycleError::message( "Mutex is poisoned. Connection is considered unusable.", )); } let config = Arc::clone(&self.manager_config); obj.interact(move |conn| config.recycling_method.perform_recycle_check(conn)) .await - .map_err(|e| RecycleError::Message(format!("Panic: {:?}", e))) + .map_err(|e| RecycleError::message(format!("Panic: {:?}", e))) .and_then(|r| r.map_err(RecycleError::Backend)) } } @@ -165,7 +163,7 @@ where impl RecyclingMethod where C: diesel::Connection, - diesel::dsl::BareSelect>: + diesel::helper_types::select>: QueryFragment, diesel::query_builder::SqlQuery: QueryFragment, { diff --git a/diesel/src/mysql.rs b/diesel/src/mysql.rs index b50996fd..d8e85e1e 100644 --- a/diesel/src/mysql.rs +++ b/diesel/src/mysql.rs @@ -9,7 +9,7 @@ deadpool::managed_reexports!( "diesel", Manager, deadpool::managed::Object, - diesel::ConnectionError, + crate::Error, std::convert::Infallible ); diff --git a/diesel/src/postgres.rs b/diesel/src/postgres.rs index 513b67fe..2cb78849 100644 --- a/diesel/src/postgres.rs +++ b/diesel/src/postgres.rs @@ -9,7 +9,7 @@ deadpool::managed_reexports!( "diesel", Manager, deadpool::managed::Object, - diesel::ConnectionError, + crate::Error, std::convert::Infallible ); diff --git a/diesel/src/sqlite.rs b/diesel/src/sqlite.rs index 237cf7eb..dc91ac02 100644 --- a/diesel/src/sqlite.rs +++ b/diesel/src/sqlite.rs @@ -9,7 +9,7 @@ deadpool::managed_reexports!( "diesel", Manager, deadpool::managed::Object, - diesel::ConnectionError, + crate::Error, std::convert::Infallible ); diff --git a/diesel/tests/basics.rs b/diesel/tests/basics.rs index 8f479665..e9f1804d 100644 --- a/diesel/tests/basics.rs +++ b/diesel/tests/basics.rs @@ -3,7 +3,7 @@ use tokio::sync::mpsc; use deadpool_diesel::{ - sqlite::{Manager, Pool, Runtime}, + sqlite::{Hook, HookError, Manager, Metrics, Pool, PoolError, Runtime}, InteractError, }; @@ -48,7 +48,8 @@ async fn pooled_connection_impls_connection() { use diesel::sql_types::Text; let pool = create_pool(1); - let conn = pool.get().await.unwrap(); + let conn_result: Result<_, PoolError> = pool.get().await; + let conn = conn_result.unwrap(); let result: Result, InteractError> = conn .interact(|conn| { let query = select("foo".into_sql::()); @@ -76,3 +77,14 @@ async fn lock() { .unwrap(); assert_eq!("foo", &result); } + +#[tokio::test] +async fn hooks() { + let manager = Manager::new(":memory:", Runtime::Tokio1); + Pool::builder(manager) + .post_create(Hook::sync_fn(|_conn, _metrics: &Metrics| { + Err(HookError::message("This is a static message")) + })) + .build() + .unwrap(); +} diff --git a/examples/diesel/Cargo.toml b/examples/diesel/Cargo.toml index 38d6cf99..e176fdf1 100644 --- a/examples/diesel/Cargo.toml +++ b/examples/diesel/Cargo.toml @@ -7,17 +7,6 @@ authors = ["Michael P. Jung "] publish = false [dependencies] -actix-web = "4.0.1" -anyhow = "1.0.65" -config = "0.13" -deadpool = { version = "0.10", path = "../.." } -deadpool-diesel = { version = "0.5.0", path = "../../diesel", features = [ - "postgres", -] } -diesel = { version = "2.0.0", features = ["postgres", "chrono"] } +deadpool-diesel = { path = "../../diesel", features = ["postgres"] } dotenvy = "0.15" -serde = { version = "1.0", features = ["derive"] } thiserror = "1.0" -tokio = { version = "1", features = ["rt-multi-thread", "macros"] } -tokio-postgres = { version = "0.7", features = ["with-uuid-1"] } -uuid = { version = "1", features = ["serde"] } diff --git a/examples/postgres-actix-web/Cargo.toml b/examples/postgres-actix-web/Cargo.toml index 90c99227..869349bb 100644 --- a/examples/postgres-actix-web/Cargo.toml +++ b/examples/postgres-actix-web/Cargo.toml @@ -8,11 +8,9 @@ publish = false [dependencies] actix-web = "4.0.1" -config = "0.13" -deadpool-postgres = { version = "0.11.0", path = "../../postgres", features = [ - "serde", -] } -dotenv = "0.15" +config = "0.14" +deadpool-postgres = { path = "../../postgres", features = ["serde"] } +dotenvy = "0.15" serde = { version = "1.0", features = ["derive"] } thiserror = "1.0" tokio-postgres = { version = "0.7", features = ["with-uuid-1"] } diff --git a/examples/postgres-actix-web/src/main.rs b/examples/postgres-actix-web/src/main.rs index b8a31c90..98372e78 100644 --- a/examples/postgres-actix-web/src/main.rs +++ b/examples/postgres-actix-web/src/main.rs @@ -1,7 +1,7 @@ use actix_web::{error, get, web, App, HttpResponse, HttpServer}; use config::ConfigError; use deadpool_postgres::{Client, Pool, PoolError, Runtime}; -use dotenv::dotenv; +use dotenvy::dotenv; use serde::{Deserialize, Serialize}; use uuid::Uuid; diff --git a/examples/postgres-axum/Cargo.toml b/examples/postgres-axum/Cargo.toml new file mode 100644 index 00000000..3a0afb0d --- /dev/null +++ b/examples/postgres-axum/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "postgres-axum" +version = "0.1.0" +edition = "2021" + +[dependencies] +axum = { version = "0.7.5", features = ["json"] } +thiserror = "1.0.60" +tokio = { version = "1.37.0", features = ["macros", "rt-multi-thread"] } +deadpool-postgres = { path = "../../postgres", features = ["serde"] } +tokio-postgres = { version = "0.7.10", features = ["with-uuid-1"] } +dotenvy = "0.15.7" +uuid = { version = "1.8.0", features = ["serde"] } +serde = { version = "1.0.200", features = ["derive"] } +config = "0.14.0" +axum-macros = "0.4.1" diff --git a/examples/postgres-axum/README.md b/examples/postgres-axum/README.md new file mode 100644 index 00000000..fab969b3 --- /dev/null +++ b/examples/postgres-axum/README.md @@ -0,0 +1,70 @@ +# `deadpool-postgres` + `axum` example + +This example combines `deadpool-postgres` with a `axum` webservice to +implement a simple API service that responds with JSON read from +PostgreSQL. + +## Running the example + +The following instructions assumes that your current user can access the +PostgreSQL running at local host passwordless via unix domain socket. The +default installation of PostgreSQL usually already contains the following line +in its [pg_hba.conf](https://www.postgresql.org/docs/16/auth-pg-hba-conf.html): + +```txt +local all all peer +``` + +All you need to do is to create a PostgreSQL user with the same name as +your system user: + +```shell +sudo -u postgres createuser -s my_user_name +``` + +Now create a database + +```shell +createdb deadpool +``` + +Now you should be able to connect to the newly created database without +without any options: + +```shell +psql deadpool +``` + +Load example data + +```shell +psql -f fixture.sql deadpool +``` + +Create `.env` file in this directory + +```env +LISTEN=[::1]:8000 +PG__DBNAME=deadpool +``` + +Run the example + +```shell +cargo run --release +``` + +## Configuration options + +If you want to connect to your database using a TCP/IP socket you can use +the following template for your `.env` file: + +```env +PG__HOST=127.0.0.1 +PG__PORT=5432 +PG__USER=deadpool +PG__PASSWORD=somepassword +PG__DBNAME=deadpool +``` + +For more configuration options see `deadpool_postgres::Config`. diff --git a/examples/postgres-axum/fixture.sql b/examples/postgres-axum/fixture.sql new file mode 100644 index 00000000..354f783d --- /dev/null +++ b/examples/postgres-axum/fixture.sql @@ -0,0 +1,37 @@ +CREATE EXTENSION IF NOT EXISTS pgcrypto WITH SCHEMA public; + +CREATE TABLE event ( + id uuid DEFAULT public.gen_random_uuid() NOT NULL, + title text NOT NULL +); + +COPY event (id, title) FROM stdin; +bec734be-97bd-4f48-b042-5ee859998c56 event1 +d36bc40a-fac4-4194-bec4-9ba8c602d994 event2 +18012fcf-3c53-4518-b9a6-22479ebe0212 event3 +6c4094fc-f8f7-4869-9c57-042bc43f257d event4 +e6173a6c-7cf4-4bc5-b676-0871d2705ed6 event5 +0d246195-537f-42dd-b7b3-6495116b8f56 event6 +c6b452b9-c1f3-4e11-9237-e22e0d6f14bd event7 +33ddb912-5bb1-4ba6-a03c-31a087ca8992 event8 +0da79dbe-63e9-4a0a-a3cb-34cfc451aa7e event9 +dec2f1cd-01af-41ed-a0d9-83a34a1c7b6d event10 +ecc1e7e4-828c-4ca3-a8a1-07444bb91300 event11 +c6ca56b1-9e02-4381-a248-3b9ef099eb93 event12 +f94693f0-789a-4a1f-a218-7399c294f00a event13 +c54ee1d7-2f8c-41c5-9478-a01f4c1c0e0b event14 +aa213e86-43fe-448d-8862-f2af9c686c82 event15 +7135cb1f-00ee-47be-b212-d45a791082ea event16 +b7dfa22b-f3a2-4547-a5df-2a6d3f54c90f event17 +c339d9fd-ce35-4578-a7c5-908cf619a321 event18 +7c49ba99-fdc3-4618-b23b-89ea3e5c4ee4 event19 +499b5807-abd2-4c24-9faa-5f463e6a19e3 event20 +d2ccbdb5-5b1e-4113-aded-24634ba1fb03 event21 +f2c82fc6-5b9a-446a-a6bc-27e814b1521b event22 +a818fbed-93dd-4e44-84a8-3591dbff3349 event23 +56dd7210-3869-4f1f-9f7a-fc58b3265f63 event24 +5803b0e8-98fe-47cd-b61d-478949b2ad70 event25 +b4a8d7da-ee5f-4d95-b452-86400697d051 event26 +f55fd18a-5532-453c-990e-098df71f2c24 event27 +3938cd54-65cf-4638-aba8-5861d9ba729e event28 +\. diff --git a/examples/postgres-axum/src/main.rs b/examples/postgres-axum/src/main.rs new file mode 100644 index 00000000..d9f0dc5c --- /dev/null +++ b/examples/postgres-axum/src/main.rs @@ -0,0 +1,88 @@ +use axum::{ + extract::State, + http::StatusCode, + response::{IntoResponse, Response}, + routing::get, + Json, Router, +}; +use axum_macros::debug_handler; +use config::ConfigError; +use deadpool_postgres::{Client, Pool, PoolError, Runtime}; +use dotenvy::dotenv; +use serde::{Deserialize, Serialize}; +use uuid::Uuid; + +#[derive(Debug, Deserialize)] +struct Config { + listen: String, + pg: deadpool_postgres::Config, +} + +impl Config { + pub fn from_env() -> Result { + config::Config::builder() + .add_source(config::Environment::default().separator("__")) + .build() + .unwrap() + .try_deserialize() + } +} + +#[derive(Deserialize, Serialize)] +struct Event { + id: Uuid, + title: String, +} + +#[derive(Debug, thiserror::Error)] +enum Error { + #[error("Pool error: {0}")] + PoolError(#[from] PoolError), + #[error("PostgreSQL error: {0}")] + PgError(#[from] tokio_postgres::Error), +} + +impl IntoResponse for Error { + fn into_response(self) -> Response { + ( + StatusCode::INTERNAL_SERVER_ERROR, + "An internal error occurred. Please try again later.", + ) + .into_response() + } +} + +#[debug_handler] +async fn event_list(pool: State) -> Result>, Error> { + let client: Client = pool.get().await?; + let stmt = client.prepare_cached("SELECT id, title FROM event").await?; + let rows = client.query(&stmt, &[]).await?; + let events = rows + .into_iter() + .map(|row| Event { + id: row.get(0), + title: row.get(1), + }) + .collect::>(); + Ok(Json(events)) +} + +#[tokio::main] +async fn main() { + dotenv().ok(); + let config = Config::from_env().unwrap(); + let pool = config + .pg + .create_pool(Some(Runtime::Tokio1), tokio_postgres::NoTls) + .unwrap(); + let app = Router::new() + .route("/v1.0/event.list", get(event_list)) + .with_state(pool); + let listener = tokio::net::TcpListener::bind(&config.listen).await.unwrap(); + println!("Server running at http://{}/", &config.listen); + println!( + "Try the following URLs: http://{}/v1.0/event.list", + &config.listen, + ); + axum::serve(listener, app).await.unwrap(); +} diff --git a/examples/postgres-benchmark/Cargo.toml b/examples/postgres-benchmark/Cargo.toml index af4c177d..a6e09899 100644 --- a/examples/postgres-benchmark/Cargo.toml +++ b/examples/postgres-benchmark/Cargo.toml @@ -7,11 +7,9 @@ authors = ["Michael P. Jung "] publish = false [dependencies] -config = "0.13" -deadpool-postgres = { version = "0.11.0", path = "../../postgres", features = [ - "serde", -] } -dotenv = "0.15" +config = "0.14" +deadpool-postgres = { path = "../../postgres", features = ["serde"] } +dotenvy = "0.15" serde = { version = "1.0", features = ["derive"] } tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } tokio-postgres = { version = "0.7" } diff --git a/examples/postgres-benchmark/src/main.rs b/examples/postgres-benchmark/src/main.rs index c2d7d6ad..134e018c 100644 --- a/examples/postgres-benchmark/src/main.rs +++ b/examples/postgres-benchmark/src/main.rs @@ -1,7 +1,7 @@ use std::time::{Duration, Instant}; use deadpool_postgres::Runtime; -use dotenv::dotenv; +use dotenvy::dotenv; use serde::{Deserialize, Serialize}; use tokio::sync::mpsc; diff --git a/examples/postgres-hyper/Cargo.toml b/examples/postgres-hyper/Cargo.toml index 0f338570..11f1a79d 100644 --- a/examples/postgres-hyper/Cargo.toml +++ b/examples/postgres-hyper/Cargo.toml @@ -7,11 +7,9 @@ authors = ["Michael P. Jung "] publish = false [dependencies] -config = "0.13" -deadpool-postgres = { version = "0.11.0", path = "../../postgres", features = [ - "serde", -] } -dotenv = "0.15" +config = "0.14" +deadpool-postgres = { path = "../../postgres", features = ["serde"] } +dotenvy = "0.15" hyper = { version = "0.14", features = ["http1", "http2", "server", "runtime"] } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/examples/postgres-hyper/src/main.rs b/examples/postgres-hyper/src/main.rs index e9cda329..47023e19 100644 --- a/examples/postgres-hyper/src/main.rs +++ b/examples/postgres-hyper/src/main.rs @@ -2,7 +2,7 @@ use std::net::SocketAddr; use config::ConfigError; use deadpool_postgres::{Client, Pool, PoolError, Runtime}; -use dotenv::dotenv; +use dotenvy::dotenv; use hyper::service::{make_service_fn, service_fn}; use hyper::{header, Body, Method, Request, Response, Server, StatusCode}; use serde::{Deserialize, Serialize}; diff --git a/examples/redis-actix-web/Cargo.toml b/examples/redis-actix-web/Cargo.toml index 98c60251..aed33e4f 100644 --- a/examples/redis-actix-web/Cargo.toml +++ b/examples/redis-actix-web/Cargo.toml @@ -8,5 +8,5 @@ publish = false [dependencies] actix-web = "4.0.0-beta.8" -deadpool-redis = { version = "0.13", path = "../../redis" } -redis = { version = "0.23", features = ["tokio-comp"] } +deadpool-redis = { path = "../../redis" } +redis = { version = "0.25", features = ["tokio-comp"] } diff --git a/lapin/CHANGELOG.md b/lapin/CHANGELOG.md index a9043e4f..47a24df7 100644 --- a/lapin/CHANGELOG.md +++ b/lapin/CHANGELOG.md @@ -1,50 +1,85 @@ -# Change Log +# Changelog -## v0.11.0 +All notable changes to this project will be documented in this file. -* Update `deadpool` dependency to version `0.10` -* Bump up MSRV to `1.63` to match the one of `tokio` +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.10.0 + -* Update `lapin` dependency to version `2.0` +## [Unreleased] -## v0.9.1 +## [0.12.1] - 2024-05-04 -* Config structs now implement `Serialize` +- Update `deadpool` dependency to version `0.12` +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates -## v0.9.0 +## [0.12.0] - 2024-04-01 -* __Breaking:__ Replace `config` feature with `serde` (opted out by default) -* Remove unused `futures` and `log` dependencies -* Update `deadpool` to `0.9` +- Update `deadpool` dependency to version `0.11` +- Remove `async_trait` dependency +- Bump up MSRV to `1.75` -## v0.8.0 +## [0.11.0] - 2023-09-26 -* Update `config` dependency to version `0.11` -* Remove deprecated `from_env` methods -* Add `rt_tokio_1` and `rt_async-std_1` features +- Update `deadpool` dependency to version `0.10` +- Bump up MSRV to `1.63` to match the one of `tokio` -## v0.7.0 +## [0.10.0] - 2022-02-22 -* Update `tokio` dependency to version `1` -* Update `tokio-amqp` dependency to version `1` -* Mark `Config::from_env` as deprecated -* Re-export `deadpool::managed::PoolConfig` +- Update `lapin` dependency to version `2.0` -## v0.6.2 +## [0.9.1] - 2021-11-15 -* Add support for `ConnectionProperties` +- Config structs now implement `Serialize` -## v0.6.1 +## [0.9.0] - 2021-10-18 -* Add support for `deadpool 0.5` (`tokio 0.2`) and `deadpool 0.6` (`tokio 0.3`) +- __Breaking:__ Replace `config` feature with `serde` (opted out by default) +- Remove unused `futures` and `log` dependencies +- Update `deadpool` to `0.9` -## v0.6.0 +## [0.8.0] - 2021-05-21 -* Update `lapin` dependency to version 1.0.0 -* Re-export for `lapin` crate +- Update `config` dependency to version `0.11` +- Remove deprecated `from_env` methods +- Add `rt_tokio_1` and `rt_async-std_1` features -## v0.5.0 +## [0.7.0] - 2020-12-26 -* First release +- Update `tokio` dependency to version `1` +- Update `tokio-amqp` dependency to version `1` +- Mark `Config::from_env` as deprecated +- Re-export `deadpool::managed::PoolConfig` + +## [0.6.2] - 2020-11-04 + +- Add support for `ConnectionProperties` + +## [0.6.1] - 2020-11-04 + +- Add support for `deadpool 0.5` (`tokio 0.2`) and `deadpool 0.6` (`tokio 0.3`) + +## [0.6.0] - 2020-07-14 + +- Update `lapin` dependency to version 1.0.0 +- Re-export for `lapin` crate + +## [0.5.0] - 2020-03-13 + +- First release + + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.12.1...HEAD +[0.12.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.12.0...deadpool-lapin-v0.12.1 +[0.12.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.11.0...deadpool-lapin-v0.12.0 +[0.11.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.10.0...deadpool-lapin-v0.11.0 +[0.10.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.9.1...deadpool-lapin-v0.10.0 +[0.9.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.9.0...deadpool-lapin-v0.9.1 +[0.9.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.8.0...deadpool-lapin-v0.9.0 +[0.8.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.7.0...deadpool-lapin-v0.8.0 +[0.7.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.6.2...deadpool-lapin-v0.7.0 +[0.6.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.6.1...deadpool-lapin-v0.6.2 +[0.6.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.6.0...deadpool-lapin-v0.6.1 +[0.6.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-lapin-v0.5.0...deadpool-lapin-v0.6.0 +[0.5.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-lapin-v0.5.0 \ No newline at end of file diff --git a/lapin/Cargo.toml b/lapin/Cargo.toml index 34ddcd99..a575a6da 100644 --- a/lapin/Cargo.toml +++ b/lapin/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-lapin" -version = "0.11.0" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.12.1" +edition = "2021" +rust-version = "1.75" authors = ["Michael P. Jung "] description = "Dead simple async pool for lapin" keywords = ["async", "lapin", "pool", "amqp", "rabbitmq"] @@ -19,15 +18,15 @@ rustdoc-args = ["--cfg", "docsrs"] default = ["rt_tokio_1"] rt_tokio_1 = ["deadpool/rt_tokio_1", "tokio-executor-trait"] rt_async-std_1 = ["deadpool/rt_async-std_1", "async-executor-trait"] -serde = ["deadpool/serde", "serde_1"] +serde = ["deadpool/serde", "dep:serde"] [dependencies] async-executor-trait = { version = "2.1", optional = true } -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ +deadpool = { path = "../", version = "0.12.0", default-features = false, features = [ "managed", ] } lapin = { version = "2.0", default-features = false } -serde_1 = { package = "serde", version = "1.0.103", features = [ +serde = { package = "serde", version = "1.0.103", features = [ "derive", ], optional = true } tokio-executor-trait = { version = "2.1.0", optional = true } @@ -39,6 +38,9 @@ tokio-executor-trait = { version = "2.1.0", optional = true } async-global-executor = { version = "2.3.1", optional = true, default-features = false } [dev-dependencies] -config = { version = "0.13", features = ["json"] } -dotenv = "0.15" +config = { version = "0.14", features = ["json"] } +dotenvy = "0.15" tokio = { version = "1.0", features = ["sync", "macros", "rt-multi-thread"] } + +[package.metadata.cargo-machete] +ignored = ["async-global-executor"] diff --git a/lapin/LICENSE-APACHE b/lapin/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/lapin/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/lapin/LICENSE-MIT b/lapin/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/lapin/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/lapin/README.md b/lapin/README.md index c7165625..bcf8344e 100644 --- a/lapin/README.md +++ b/lapin/README.md @@ -1,4 +1,4 @@ -# Deadpool for Lapin [![Latest Version](https://img.shields.io/crates/v/deadpool-lapin.svg)](https://crates.io/crates/deadpool-lapin) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for Lapin [![Latest Version](https://img.shields.io/crates/v/deadpool-lapin.svg)](https://crates.io/crates/deadpool-lapin) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. @@ -45,7 +45,7 @@ async fn main() -> Result<(), Box> { } ``` -## Example with `config`, `dotenv` and `tokio-amqp` crate +## Example with `config`, `dotenvy` and `tokio-amqp` crate ```rust use std::sync::Arc; @@ -55,11 +55,9 @@ use deadpool_lapin::lapin::{ options::BasicPublishOptions, BasicProperties, }; -use dotenv::dotenv; -# use serde_1 as serde; +use dotenvy::dotenv; #[derive(Debug, serde::Deserialize)] -# #[serde(crate = "serde_1")] struct Config { #[serde(default)] amqp: deadpool_lapin::Config diff --git a/lapin/src/config.rs b/lapin/src/config.rs index ab658d8e..db532294 100644 --- a/lapin/src/config.rs +++ b/lapin/src/config.rs @@ -15,10 +15,7 @@ use crate::{CreatePoolError, Manager, Pool, PoolBuilder, PoolConfig, Runtime}; /// AMQP__POOL__TIMEOUTS__WAIT__NANOS=0 /// ``` /// ```rust -/// # use serde_1 as serde; -/// # /// #[derive(serde::Deserialize)] -/// # #[serde(crate = "serde_1")] /// struct Config { /// amqp: deadpool_lapin::Config, /// } @@ -33,8 +30,7 @@ use crate::{CreatePoolError, Manager, Pool, PoolBuilder, PoolConfig, Runtime}; /// } /// ``` #[derive(Clone, Default)] -#[cfg_attr(feature = "serde", derive(serde_1::Deserialize, serde_1::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Config { /// AMQP server URL. pub url: Option, diff --git a/lapin/src/lib.rs b/lapin/src/lib.rs index 809e06d9..fcd5e10d 100644 --- a/lapin/src/lib.rs +++ b/lapin/src/lib.rs @@ -23,7 +23,7 @@ mod config; -use deadpool::{async_trait, managed}; +use deadpool::managed; use lapin::{ConnectionProperties, Error}; pub use lapin; @@ -34,7 +34,7 @@ pub use deadpool::managed::reexports::*; deadpool::managed_reexports!( "lapin", Manager, - deadpool::managed::Object, + managed::Object, Error, ConfigError ); @@ -59,7 +59,7 @@ impl std::fmt::Debug for Manager { .field("addr", &self.addr) .field( "connection_properties", - &self::config::ConnProps(&self.connection_properties), + &config::ConnProps(&self.connection_properties), ) .finish() } @@ -77,7 +77,6 @@ impl Manager { } } -#[async_trait] impl managed::Manager for Manager { type Type = lapin::Connection; type Error = Error; @@ -92,7 +91,7 @@ impl managed::Manager for Manager { async fn recycle(&self, conn: &mut lapin::Connection, _: &Metrics) -> RecycleResult { match conn.status().state() { lapin::ConnectionState::Connected => Ok(()), - other_state => Err(RecycleError::Message(format!( + other_state => Err(RecycleError::message(format!( "lapin connection is in state: {:?}", other_state ))), diff --git a/memcached/CHANGELOG.md b/memcached/CHANGELOG.md index 5133e28b..3420ae78 100644 --- a/memcached/CHANGELOG.md +++ b/memcached/CHANGELOG.md @@ -2,26 +2,46 @@ All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.2.0] - 2023-09-25 +## [Unreleased] + +## [0.3.2] - 2024-05-04 + +- Update `deadpool` dependency to version `0.12` +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates + +## [0.3.1] - 2024-04-06 + +- Remove unused `futures` and `log` dependencies + +## [0.3.0] - 2024-04-01 -### Changed +- Update `deadpool` dependency to version `0.11` +- Remove `async_trait` dependency +- Bump up MSRV to `1.75` + +## [0.2.0] - 2023-09-25 - Update `deadpool` dependency to version `0.10` - Bump up MSRV to `1.63` to match the one of `tokio` ## [0.1.2] - 2020-09-13 -### Changed - - Small documentation fixes and relaxed dependency version constraints. -## v0.1.0 - 2020-08-13 - -### Added +## [0.1.0] - 2020-08-13 - Initial release. + + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-memcached-v0.3.2...HEAD +[0.3.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-memcached-v0.3.1...deadpool-memcached-v0.3.2 +[0.3.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-memcached-v0.3.0...deadpool-memcached-v0.3.1 +[0.3.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-memcached-v0.2.0...deadpool-memcached-v0.3.0 +[0.2.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-memcached-v0.1.2...deadpool-memcached-v0.2.0 +[0.1.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-memcached-v0.1.0...deadpool-memcached-v0.1.2 +[0.1.0]: https://github.com/bikeshedder/deadpool/deadpool-memcached-v0.1.0 \ No newline at end of file diff --git a/memcached/Cargo.toml b/memcached/Cargo.toml index 4e139d33..ff038a29 100644 --- a/memcached/Cargo.toml +++ b/memcached/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-memcached" -version = "0.2.0" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.3.2" +edition = "2021" +rust-version = "1.75" authors = [ "Toby Lawrence ", "Michael P. Jung ", @@ -24,14 +23,14 @@ tcp = ["async-memcached/tcp"] [dependencies] async-memcached = { version = "0.1", default-features = false } -async-trait = "0.1" -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ +deadpool = { path = "../", version = "0.12.0", default-features = false, features = [ "managed", ] } -futures = { version = "0.3", features = ["compat"] } -log = "0.4" # This crate doesn't directly depend on tokio but async-memcached 0.1.7 # broke the build by forgetting to add the "net" feature to the tokio # dependency. Once async-memcached is fixed this dependency can be removed # again. tokio = { version = "1.0", default-features = false, features = ["net"] } + +[package.metadata.cargo-machete] +ignored = ["tokio"] diff --git a/memcached/LICENSE-APACHE b/memcached/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/memcached/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/memcached/LICENSE-MIT b/memcached/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/memcached/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/memcached/README.md b/memcached/README.md index 5281461a..675d230e 100644 --- a/memcached/README.md +++ b/memcached/README.md @@ -1,4 +1,4 @@ -# Deadpool for Memcached [![Latest Version](https://img.shields.io/crates/v/deadpool-memcached.svg)](https://crates.io/crates/deadpool-memcached) [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for Memcached [![Latest Version](https://img.shields.io/crates/v/deadpool-memcached.svg)](https://crates.io/crates/deadpool-memcached) [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. diff --git a/memcached/release.toml b/memcached/release.toml deleted file mode 100644 index 5078e03e..00000000 --- a/memcached/release.toml +++ /dev/null @@ -1,8 +0,0 @@ -no-dev-version = true -sign-commit = true -sign-tag = true -pre-release-replacements = [ - {file="CHANGELOG.md", search="Unreleased", replace="{{version}}"}, - {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}"}, - {file="CHANGELOG.md", search="", replace="\n\n## [Unreleased] - ReleaseDate"}, -] \ No newline at end of file diff --git a/memcached/src/lib.rs b/memcached/src/lib.rs index b43eda4f..2a8d2b3f 100644 --- a/memcached/src/lib.rs +++ b/memcached/src/lib.rs @@ -10,7 +10,6 @@ use std::convert::Infallible; use async_memcached::{Client, Error}; -use async_trait::async_trait; /// Type alias for using [`deadpool::managed::RecycleResult`] with [`redis`]. type RecycleResult = deadpool::managed::RecycleResult; @@ -32,7 +31,6 @@ impl Manager { } } -#[async_trait] impl deadpool::managed::Manager for Manager { type Type = Client; type Error = Error; diff --git a/postgres/CHANGELOG.md b/postgres/CHANGELOG.md index 199218d4..656d18d1 100644 --- a/postgres/CHANGELOG.md +++ b/postgres/CHANGELOG.md @@ -1,6 +1,50 @@ -# Change Log +# Changelog -## v0.11.0 +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] + +## [0.14.0] - 2024-06-04 + +- Add back `async_trait` to the `GenericClient` trait. + The removal of `async_trait` caused some errors for code using + the generic client interface. A test was added to ensure future + removals of `async_trait` will not cause this code to break. + +## [0.13.2] - 2024-05-07 + +- Add WASM support +- Expose API for providing a custom `Connect` implementation. +- Add `+ Send` to futures returned by `GenericClient` + +## [0.13.1] - 2024-05-04 + +- Update `deadpool` dependency to version `0.12` +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates + +## [0.13.0] - 2024-04-01 + +- Update `deadpool` dependency to version `0.11` +- Remove `async_trait` dependency +- Bump up MSRV to `1.75` + +## [0.12.1] - 2023-12-18 + +- Fix `Config::url` handling + +## [0.12.0] - 2023-12-15 + +- Add `load_balance_hosts` to `Config` struct. +- Add `hostaddr` and `hostaddrs` to `Config` struct. +- Add `url` field to `Config` struct. This enables parsing of + connection URLs. + +## [0.11.0] - 2023-09-26 - **BREAKING:** Disconnect immediately from the database when dropping clients. This is considered a breaking change as in previous versions @@ -12,160 +56,197 @@ - Update `deadpool` dependency to version `0.10` - Bump up MSRV to `1.63` to match the one of `tokio` -## v0.10.5 +## [0.10.5] - 2023-01-24 - Fix infinite recursion in `GenericClient` -## v0.10.4 (yanked) +## [0.10.4] - 2023-01-16 (yanked) - Add `GenericClient` -## v0.10.3 +## [0.10.3] - 2022-10-26 -* Make `Transaction::statement_cache` field public +- Make `Transaction::statement_cache` field public -## v0.10.2 +## [0.10.2] - 2022-03-22 -* Export `TargetSessionAttrs` and `ChannelBinding` enums (part of `Config` +- Export `TargetSessionAttrs` and `ChannelBinding` enums (part of `Config` struct) -## v0.10.1 +## [0.10.1] - 2021-11-15 -* Config structs now implement `Serialize` +- Config structs now implement `Serialize` -## v0.10.0 +## [0.10.0] - 2021-10-18 -* __Breaking:__ Replace `config` feature with `serde` (opted out by default) -* Re-export `deadpool::managed::Timeouts` -* Add `Runtime` parameter to `Config::create_pool` method -* Remove redundant `futures` dependency +- __Breaking:__ Replace `config` feature with `serde` (opted out by default) +- Re-export `deadpool::managed::Timeouts` +- Add `Runtime` parameter to `Config::create_pool` method +- Remove redundant `futures` dependency -## v0.9.0 +## [0.9.0] - 2021-06-01 -* Remove generic `` parameter from `Manager`, `Pool` and `Client` +- Remove generic `` parameter from `Manager`, `Pool` and `Client` types. This parameter was added by accident when deadpool switched to using associated types. -## v0.8.1 +## [0.8.1] - 2021-06-01 -* Update `tokio-postgres` dependency to version `0.7.2` +- Update `tokio-postgres` dependency to version `0.7.2` This crate depends on the `GenericClient::client` method which was added in `tokio-postgres` version `0.7.2`. -## v0.8.0 +## [0.8.0] - 2021-05-21 -* Do not detect unix domain socket paths at config creation. -* Update `config` dependency to version `0.11` -* Remove deprecated `from_env` methods -* Add `Manager::statement_caches` field which provides access +- Do not detect unix domain socket paths at config creation. +- Update `config` dependency to version `0.11` +- Remove deprecated `from_env` methods +- Add `Manager::statement_caches` field which provides access to managing the statement cache for all clients. -* Rename `prepare` to `prepare_cached` and `prepare_typed` to +- Rename `prepare` to `prepare_cached` and `prepare_typed` to `prepare_typed_cached`. This makes the non-caching prepare methods available without having to dereference `ClientWrapper` or `Transaction` objects first. -* Add `rt_tokio_1` and `rt_async-std_1` features -* Enable `RecyclingMethod::Fast` by default +- Add `rt_tokio_1` and `rt_async-std_1` features +- Enable `RecyclingMethod::Fast` by default -## v0.7.0 +## [0.7.0] - 2020-12-26 -* Update `tokio` dependency to version `1` -* Update `tokio-postgres` dependency to version `0.7` -* Re-export `deadpool::managed::PoolConfig` -* Add `StatementCache::remove` method +- Update `tokio` dependency to version `1` +- Update `tokio-postgres` dependency to version `0.7` +- Re-export `deadpool::managed::PoolConfig` +- Add `StatementCache::remove` method -## v0.6.0 +## [0.6.0] - 2020-11-04 -* Update `tokio` dependency to version `0.3` -* Update `tokio-postgres` dependency to version `0.6` +- Update `tokio` dependency to version `0.3` +- Update `tokio-postgres` dependency to version `0.6` -## v0.5.6 +## [0.5.6] - 2020-07-14 -* Add `Config::new` method -* Add `Client::build_transaction` method which makes it possible to +- Add `Config::new` method +- Add `Client::build_transaction` method which makes it possible to use the `TransactionBuilder` with the statement cache. -* Add `RecyclingMethod::Clean` which works similar to `DISCARD ALL` +- Add `RecyclingMethod::Clean` which works similar to `DISCARD ALL` but makes sure the statement cache is not rendered ineffective. -* Add `RecyclingMethod::Custom` which allows to execute arbitary SQL +- Add `RecyclingMethod::Custom` which allows to execute arbitary SQL when recycling connections. -* Re-export `tokio_postgres` crate +- Re-export `tokio_postgres` crate -## v0.5.5 +## [0.5.5] - 2020-02-28 -* Deprecate `Config::from_env` -* Add `Manager::from_config`, `ManagerConfig` and `RecyclingMethod` which +- Deprecate `Config::from_env` +- Add `Manager::from_config`, `ManagerConfig` and `RecyclingMethod` which makes it possible to specify how connections are recycled. The current default recycling method is `Verified` which is the same as before. The upcoming `0.6` release of this crate will change the default to `Fast`. -## v0.5.4 +## [0.5.4] - 2020-01-26 -* Implement `DerefMut` for `Transaction` wrapper -* Add `transaction` method to `Transaction` wrapper +- Implement `DerefMut` for `Transaction` wrapper +- Add `transaction` method to `Transaction` wrapper -## v0.5.3 +## [0.5.3] - 2020-01-24 -* Add `#[derive(Clone)]` to `Config` struct -* Make `config` module public +- Add `#[derive(Clone)]` to `Config` struct +- Make `config` module public -## v0.5.2 +## [0.5.2] - 2020-01-18 -* Disable `default-features` for `deadpool` dependency +- Disable `default-features` for `deadpool` dependency -## v0.5.1 +## [0.5.1] - 2020-01-17 -* Fix windows support +- Fix windows support -## v0.5.0 +## [0.5.0] - 2020-01-16 -* Add support for `config` crate +- Add support for `config` crate -## v0.4.3 +## [0.4.3] - 2020-01-10 -* `prepare` and `prepare_typed` now accept a `&self` instead of `&mut self` +- `prepare` and `prepare_typed` now accept a `&self` instead of `&mut self` which fixes support for pipelining. -## v0.4.2 +## [0.4.2] - 2019-12-31 -* Add `PoolError` type alias +- Add `PoolError` type alias -## v0.4.1 +## [0.4.1] - 2019-12-29 -* Update to `tokio-postgres 0.5.1` -* Add back `DerefMut` implementation for `deadpool_postgres::Client` which +- Update to `tokio-postgres 0.5.1` +- Add back `DerefMut` implementation for `deadpool_postgres::Client` which makes it compatible with code expecting `&mut tokio_postgres::Client`. -* Add statement cache support for `Client::prepare_typed` and +- Add statement cache support for `Client::prepare_typed` and `Transaction::prepare_typed`. -## v0.4.0 +## [0.4.0] - 2019-12-19 -* Rename `Client` struct to `ClientWrapper` -* Add `Client` type alias +- Rename `Client` struct to `ClientWrapper` +- Add `Client` type alias -## v0.3.0 +## [0.3.0] - 2019-12-13 -* Add `StatementCache` struct with the functions `size` and `clear` which +- Add `StatementCache` struct with the functions `size` and `clear` which are now accessible via `Connection::statement_cache` and `Transaction::statement_cache`. -* Make recycling more robust by changing the `Manager::recycle` to a non +- Make recycling more robust by changing the `Manager::recycle` to a non consuming API. -## v0.2.3 +## [0.2.3] - 2019-12-02 -* Add documentation for `docs.rs` -* Improve example in `README.md` and crate root -* Fix `Transaction::commit` and `Transaction::rollback` +- Add documentation for `docs.rs` +- Improve example in `README.md` and crate root +- Fix `Transaction::commit` and `Transaction::rollback` -## v0.2.2 +## [0.2.2] - 2019-12-02 -* Update to `tokio 0.2` and `tokio-postgres 0.5.0-alpha.2` +- Update to `tokio 0.2` and `tokio-postgres 0.5.0-alpha.2` -## v0.2.1 +## [0.2.1] - 2019-11-18 -* `deadpool_postgres::Client` no longer implements `DerefMut` which was not +- `deadpool_postgres::Client` no longer implements `DerefMut` which was not needed anyways. -* `deadpool_postgres::Client.transaction` now returns a wrapped transaction +- `deadpool_postgres::Client.transaction` now returns a wrapped transaction object which utilizes the statement cache of the wrapped client. -## v0.2.0 - -* First release +## [0.2.0] - 2019-11-18 + +- First release + + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.14.0...HEAD +[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 +[0.13.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.12.1...deadpool-postgres-v0.13.0 +[0.12.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.12.0...deadpool-postgres-v0.12.1 +[0.12.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.11.0...deadpool-postgres-v0.12.0 +[0.11.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.10.5...deadpool-postgres-v0.11.0 +[0.10.5]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.10.4...deadpool-postgres-v0.10.5 +[0.10.4]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.10.3...deadpool-postgres-v0.10.4 +[0.10.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.10.2...deadpool-postgres-v0.10.3 +[0.10.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.10.1...deadpool-postgres-v0.10.2 +[0.10.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.10.0...deadpool-postgres-v0.10.1 +[0.10.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.9.0...deadpool-postgres-v0.10.0 +[0.9.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.8.1...deadpool-postgres-v0.9.0 +[0.8.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.8.0...deadpool-postgres-v0.8.1 +[0.8.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.7.0...deadpool-postgres-v0.8.0 +[0.7.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.6.0...deadpool-postgres-v0.7.0 +[0.6.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.5.6...deadpool-postgres-v0.6.0 +[0.5.6]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.5.5...deadpool-postgres-v0.5.6 +[0.5.5]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.5.4...deadpool-postgres-v0.5.5 +[0.5.4]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.5.3...deadpool-postgres-v0.5.4 +[0.5.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.5.2...deadpool-postgres-v0.5.3 +[0.5.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.5.1...deadpool-postgres-v0.5.2 +[0.5.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.5.0...deadpool-postgres-v0.5.1 +[0.5.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.4.3...deadpool-postgres-v0.5.0 +[0.4.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.4.2...deadpool-postgres-v0.4.3 +[0.4.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.4.1...deadpool-postgres-v0.4.2 +[0.4.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.4.0...deadpool-postgres-v0.4.1 +[0.4.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.3.0...deadpool-postgres-v0.4.0 +[0.3.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.2.3...deadpool-postgres-v0.3.0 +[0.2.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.2.2...deadpool-postgres-v0.2.3 +[0.2.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.2.1...deadpool-postgres-v0.2.2 +[0.2.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-postgres-v0.2.0...deadpool-postgres-v0.2.1 +[0.2.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-postgres-v0.2.0 diff --git a/postgres/Cargo.toml b/postgres/Cargo.toml index 2dee8a3d..3313433d 100644 --- a/postgres/Cargo.toml +++ b/postgres/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-postgres" -version = "0.11.0" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.14.0" +edition = "2021" +rust-version = "1.75" authors = ["Michael P. Jung "] description = "Dead simple async pool for tokio-postgres" keywords = ["async", "database", "pool", "postgres"] @@ -18,21 +17,29 @@ all-features = true default = ["rt_tokio_1"] rt_tokio_1 = ["deadpool/rt_tokio_1"] rt_async-std_1 = ["deadpool/rt_async-std_1"] -serde = ["deadpool/serde", "serde_1"] +serde = ["deadpool/serde", "dep:serde"] [dependencies] -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ +async-trait = "0.1.80" +deadpool = { path = "../", version = "0.12.0", default-features = false, features = [ "managed", ] } -serde_1 = { package = "serde", version = "1.0", features = [ +serde = { package = "serde", version = "1.0", features = [ "derive", ], optional = true } -tokio = { version = "1", features = ["rt"] } -tokio-postgres = "0.7.2" +tokio = { version = "1.29", features = ["rt"] } tracing = "0.1.37" +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +tokio-postgres = "0.7.9" + +[target.'cfg(target_arch = "wasm32")'.dependencies] +getrandom = { version = "0.2", features = ["js"] } +tokio-postgres = { version = "0.7.9", default-features = false } + [dev-dependencies] -config = { version = "0.13", features = ["json"] } -dotenv = "0.15.0" +config = { version = "0.14", features = ["json"] } +dotenvy = "0.15.0" futures = "0.3.1" +futures-util = "0.3.30" tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } diff --git a/postgres/LICENSE-APACHE b/postgres/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/postgres/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/postgres/LICENSE-MIT b/postgres/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/postgres/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/postgres/README.md b/postgres/README.md index b0de6cc4..8553a2cc 100644 --- a/postgres/README.md +++ b/postgres/README.md @@ -1,4 +1,4 @@ -# Deadpool for PostgreSQL [![Latest Version](https://img.shields.io/crates/v/deadpool-postgres.svg)](https://crates.io/crates/deadpool-postgres) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for PostgreSQL [![Latest Version](https://img.shields.io/crates/v/deadpool-postgres.svg)](https://crates.io/crates/deadpool-postgres) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. @@ -31,17 +31,19 @@ and `password` in the connection config or use an alternative [authentication method](https://www.postgresql.org/docs/current/auth-methods.html). ```rust,no_run -use deadpool_postgres::{Config, Manager, ManagerConfig, Pool, RecyclingMethod, Runtime}; +use deadpool_postgres::{Config, ManagerConfig, RecyclingMethod, Runtime}; use tokio_postgres::NoTls; #[tokio::main] async fn main() { let mut cfg = Config::new(); cfg.dbname = Some("deadpool".to_string()); - cfg.manager = Some(ManagerConfig { recycling_method: RecyclingMethod::Fast }); + cfg.manager = Some(ManagerConfig { + recycling_method: RecyclingMethod::Fast, + }); let pool = cfg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap(); - for i in 1..10 { - let mut client = pool.get().await.unwrap(); + for i in 1..10i32 { + let client = pool.get().await.unwrap(); let stmt = client.prepare_cached("SELECT 1 + $1").await.unwrap(); let rows = client.query(&stmt, &[&i]).await.unwrap(); let value: i32 = rows[0].get(0); @@ -50,7 +52,7 @@ async fn main() { } ``` -## Example with `config` and `dotenv` crate +## Example with `config` and `dotenvy` crate ```env # .env @@ -58,33 +60,31 @@ PG__DBNAME=deadpool ``` ```rust -use deadpool_postgres::{Manager, Pool, Runtime}; -use dotenv::dotenv; -# use serde_1 as serde; +use deadpool_postgres::Runtime; +use dotenvy::dotenv; use tokio_postgres::NoTls; #[derive(Debug, serde::Deserialize)] -# #[serde(crate = "serde_1")] struct Config { - pg: deadpool_postgres::Config + pg: deadpool_postgres::Config, } impl Config { pub fn from_env() -> Result { config::Config::builder() - .add_source(config::Environment::default().separator("__")) - .build()? - .try_deserialize() + .add_source(config::Environment::default().separator("__")) + .build()? + .try_deserialize() } } #[tokio::main] async fn main() { dotenv().ok(); - let mut cfg = Config::from_env().unwrap(); + let cfg = Config::from_env().unwrap(); let pool = cfg.pg.create_pool(Some(Runtime::Tokio1), NoTls).unwrap(); - for i in 1..10 { - let mut client = pool.get().await.unwrap(); + for i in 1..10i32 { + let client = pool.get().await.unwrap(); let stmt = client.prepare_cached("SELECT 1 + $1").await.unwrap(); let rows = client.query(&stmt, &[&i]).await.unwrap(); let value: i32 = rows[0].get(0); @@ -101,8 +101,8 @@ In your own code you will probably want to use `::config::ConfigError` and ## Example using an existing `tokio_postgres::Config` object ```rust,no_run -use std::env; use deadpool_postgres::{Manager, ManagerConfig, Pool, RecyclingMethod}; +use std::env; use tokio_postgres::NoTls; #[tokio::main] @@ -113,12 +113,12 @@ async fn main() { pg_config.user(env::var("USER").unwrap().as_str()); pg_config.dbname("deadpool"); let mgr_config = ManagerConfig { - recycling_method: RecyclingMethod::Fast + recycling_method: RecyclingMethod::Fast, }; let mgr = Manager::from_config(pg_config, NoTls, mgr_config); let pool = Pool::builder(mgr).max_size(16).build().unwrap(); - for i in 1..10 { - let mut client = pool.get().await.unwrap(); + for i in 1..10i32 { + let client = pool.get().await.unwrap(); let stmt = client.prepare_cached("SELECT 1 + $1").await.unwrap(); let rows = client.query(&stmt, &[&i]).await.unwrap(); let value: i32 = rows[0].get(0); @@ -170,7 +170,7 @@ async fn main() { | deadpool-postgres | tokio-postgres | | ----------------- | -------------- | - | 0.7 – 0.11 | 0.7 | + | 0.7 – 0.12 | 0.7 | | 0.6 | 0.6 | | 0.4 – 0.5 | 0.5 | | 0.2 – 0.3 | 0.5.0-alpha | diff --git a/postgres/src/config.rs b/postgres/src/config.rs index dc15973b..477dfd4c 100644 --- a/postgres/src/config.rs +++ b/postgres/src/config.rs @@ -1,21 +1,23 @@ //! Configuration used for [`Pool`] creation. -use std::{env, fmt, time::Duration}; +use std::{env, fmt, net::IpAddr, str::FromStr, time::Duration}; -#[cfg(feature = "serde")] -use serde_1 as serde; +use tokio_postgres::config::{ + ChannelBinding as PgChannelBinding, LoadBalanceHosts as PgLoadBalanceHosts, + SslMode as PgSslMode, TargetSessionAttrs as PgTargetSessionAttrs, +}; + +#[cfg(not(target_arch = "wasm32"))] +use super::Pool; +#[cfg(not(target_arch = "wasm32"))] +use crate::{CreatePoolError, PoolBuilder, Runtime}; +#[cfg(not(target_arch = "wasm32"))] use tokio_postgres::{ - config::{ - ChannelBinding as PgChannelBinding, SslMode as PgSslMode, - TargetSessionAttrs as PgTargetSessionAttrs, - }, tls::{MakeTlsConnect, TlsConnect}, Socket, }; -use crate::{CreatePoolError, PoolBuilder, Runtime}; - -use super::{Pool, PoolConfig}; +use super::PoolConfig; /// Configuration object. /// @@ -33,10 +35,7 @@ use super::{Pool, PoolConfig}; /// PG__POOL__TIMEOUTS__WAIT__NANOS=0 /// ``` /// ```rust -/// # use serde_1 as serde; -/// # /// #[derive(serde::Deserialize, serde::Serialize)] -/// # #[serde(crate = "serde_1")] /// struct Config { /// pg: deadpool_postgres::Config, /// } @@ -51,8 +50,12 @@ use super::{Pool, PoolConfig}; /// ``` #[derive(Clone, Debug, Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] pub struct Config { + /// Initialize the configuration by parsing the URL first. + /// **Note**: All the other options override settings defined + /// by the URL except for the `host` and `hosts` options which + /// are additive! + pub url: Option, /// See [`tokio_postgres::Config::user`]. pub user: Option, /// See [`tokio_postgres::Config::password`]. @@ -76,6 +79,10 @@ pub struct Config { pub host: Option, /// See [`tokio_postgres::Config::host`]. pub hosts: Option>, + /// See [`tokio_postgres::Config::hostaddr`]. + pub hostaddr: Option, + /// See [`tokio_postgres::Config::hostaddr`]. + pub hostaddrs: Option>, /// This is similar to [`Config::ports`] but only allows one port to be /// specified. /// @@ -91,12 +98,15 @@ pub struct Config { pub connect_timeout: Option, /// See [`tokio_postgres::Config::keepalives`]. pub keepalives: Option, + #[cfg(not(target_arch = "wasm32"))] /// See [`tokio_postgres::Config::keepalives_idle`]. pub keepalives_idle: Option, /// See [`tokio_postgres::Config::target_session_attrs`]. pub target_session_attrs: Option, /// See [`tokio_postgres::Config::channel_binding`]. pub channel_binding: Option, + /// See [`tokio_postgres::Config::load_balance_hosts`]. + pub load_balance_hosts: Option, /// [`Manager`] configuration. /// @@ -108,8 +118,10 @@ pub struct Config { } /// This error is returned if there is something wrong with the configuration -#[derive(Copy, Clone, Debug)] +#[derive(Debug)] pub enum ConfigError { + /// This variant is returned if the `url` is invalid + InvalidUrl(tokio_postgres::Error), /// This variant is returned if the `dbname` is missing from the config DbnameMissing, /// This variant is returned if the `dbname` contains an empty string @@ -119,6 +131,7 @@ pub enum ConfigError { impl fmt::Display for ConfigError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { + Self::InvalidUrl(e) => write!(f, "configuration property \"url\" is invalid: {}", e), Self::DbnameMissing => write!(f, "configuration property \"dbname\" not found"), Self::DbnameEmpty => write!( f, @@ -138,6 +151,7 @@ impl Config { Self::default() } + #[cfg(not(target_arch = "wasm32"))] /// Creates a new [`Pool`] using this [`Config`]. /// /// # Errors @@ -157,6 +171,7 @@ impl Config { builder.build().map_err(CreatePoolError::Build) } + #[cfg(not(target_arch = "wasm32"))] /// Creates a new [`PoolBuilder`] using this [`Config`]. /// /// # Errors @@ -180,22 +195,34 @@ impl Config { /// the database. #[allow(unused_results)] pub fn get_pg_config(&self) -> Result { - let mut cfg = tokio_postgres::Config::new(); - if let Some(user) = &self.user { - cfg.user(user.as_str()); - } else if let Ok(user) = env::var("USER") { + let mut cfg = if let Some(url) = &self.url { + tokio_postgres::Config::from_str(url).map_err(ConfigError::InvalidUrl)? + } else { + tokio_postgres::Config::new() + }; + if let Some(user) = self.user.as_ref().filter(|s| !s.is_empty()) { cfg.user(user.as_str()); } + if !cfg.get_user().map_or(false, |u| !u.is_empty()) { + if let Ok(user) = env::var("USER") { + cfg.user(&user); + } + } if let Some(password) = &self.password { cfg.password(password); } - match &self.dbname { - Some(dbname) => match dbname.as_str() { - "" => return Err(ConfigError::DbnameMissing), - dbname => cfg.dbname(dbname), - }, - None => return Err(ConfigError::DbnameEmpty), - }; + if let Some(dbname) = self.dbname.as_ref().filter(|s| !s.is_empty()) { + cfg.dbname(dbname); + } + match cfg.get_dbname() { + None => { + return Err(ConfigError::DbnameMissing); + } + Some("") => { + return Err(ConfigError::DbnameEmpty); + } + _ => {} + } if let Some(options) = &self.options { cfg.options(options.as_str()); } @@ -210,7 +237,7 @@ impl Config { cfg.host(host.as_str()); } } - if self.host.is_none() && self.hosts.is_none() { + if cfg.get_hosts().is_empty() { // Systems that support it default to unix domain sockets. #[cfg(unix)] { @@ -222,6 +249,14 @@ impl Config { #[cfg(not(unix))] cfg.host("127.0.0.1"); } + if let Some(hostaddr) = self.hostaddr { + cfg.hostaddr(hostaddr); + } + if let Some(hostaddrs) = &self.hostaddrs { + for hostaddr in hostaddrs { + cfg.hostaddr(*hostaddr); + } + } if let Some(port) = self.port { cfg.port(port); } @@ -236,6 +271,7 @@ impl Config { if let Some(keepalives) = self.keepalives { cfg.keepalives(keepalives); } + #[cfg(not(target_arch = "wasm32"))] if let Some(keepalives_idle) = self.keepalives_idle { cfg.keepalives_idle(keepalives_idle); } @@ -269,7 +305,6 @@ impl Config { /// [`Verified`]: RecyclingMethod::Verified #[derive(Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] pub enum RecyclingMethod { /// Only run [`Client::is_closed()`][1] when recycling existing connections. /// @@ -351,7 +386,6 @@ impl RecyclingMethod { /// [`Manager`]: super::Manager #[derive(Clone, Debug, Default)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] pub struct ManagerConfig { /// Method of how a connection is recycled. See [`RecyclingMethod`]. pub recycling_method: RecyclingMethod, @@ -364,7 +398,6 @@ pub struct ManagerConfig { /// [`serde::Deserialize`] trait which is required for the [`serde`] support. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] #[non_exhaustive] pub enum TargetSessionAttrs { /// No special properties are required. @@ -390,7 +423,6 @@ impl From for PgTargetSessionAttrs { /// [`serde::Deserialize`] trait which is required for the [`serde`] support. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] #[non_exhaustive] pub enum SslMode { /// Do not use TLS. @@ -420,7 +452,6 @@ impl From for PgSslMode { /// [`serde::Deserialize`] trait which is required for the [`serde`] support. #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] #[non_exhaustive] pub enum ChannelBinding { /// Do not use channel binding. @@ -442,3 +473,27 @@ impl From for PgChannelBinding { } } } + +/// Load balancing configuration. +/// +/// This is a 1:1 copy of the [`PgLoadBalanceHosts`] enumeration. +/// This is duplicated here in order to add support for the +/// [`serde::Deserialize`] trait which is required for the [`serde`] support. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[non_exhaustive] +pub enum LoadBalanceHosts { + /// Make connection attempts to hosts in the order provided. + Disable, + /// Make connection attempts to hosts in a random order. + Random, +} + +impl From for PgLoadBalanceHosts { + fn from(cb: LoadBalanceHosts) -> Self { + match cb { + LoadBalanceHosts::Disable => Self::Disable, + LoadBalanceHosts::Random => Self::Random, + } + } +} diff --git a/postgres/src/generic_client.rs b/postgres/src/generic_client.rs index 91c77efa..96f48557 100644 --- a/postgres/src/generic_client.rs +++ b/postgres/src/generic_client.rs @@ -7,7 +7,7 @@ use tokio_postgres::types::{BorrowToSql, ToSql, Type}; use tokio_postgres::RowStream; use tokio_postgres::{Error, Row, Statement, ToStatement}; -use deadpool::async_trait; +use async_trait::async_trait; use crate::{Client, ClientWrapper, Transaction}; diff --git a/postgres/src/lib.rs b/postgres/src/lib.rs index 4fa68e87..56c36e5d 100644 --- a/postgres/src/lib.rs +++ b/postgres/src/lib.rs @@ -27,19 +27,28 @@ use std::{ borrow::Cow, collections::HashMap, fmt, + future::Future, ops::{Deref, DerefMut}, + pin::Pin, sync::{ atomic::{AtomicUsize, Ordering}, Arc, Mutex, RwLock, Weak, }, }; -use deadpool::{async_trait, managed}; -use tokio::{spawn, task::JoinHandle}; +use deadpool::managed; +#[cfg(not(target_arch = "wasm32"))] +use tokio::spawn; +use tokio::task::JoinHandle; use tokio_postgres::{ - tls::MakeTlsConnect, tls::TlsConnect, types::Type, Client as PgClient, Config as PgConfig, - Error, IsolationLevel, Socket, Statement, Transaction as PgTransaction, - TransactionBuilder as PgTransactionBuilder, + types::Type, Client as PgClient, Config as PgConfig, Error, IsolationLevel, Statement, + Transaction as PgTransaction, TransactionBuilder as PgTransactionBuilder, +}; + +#[cfg(not(target_arch = "wasm32"))] +use tokio_postgres::{ + tls::{MakeTlsConnect, TlsConnect}, + Socket, }; pub use tokio_postgres; @@ -55,16 +64,18 @@ pub use deadpool::managed::reexports::*; deadpool::managed_reexports!( "tokio_postgres", Manager, - deadpool::managed::Object, + managed::Object, Error, ConfigError ); +type BoxFuture<'a, T> = Pin + Send + 'a>>; + /// Type alias for [`Object`] pub type Client = Object; -type RecycleResult = deadpool::managed::RecycleResult; -type RecycleError = deadpool::managed::RecycleError; +type RecycleResult = managed::RecycleResult; +type RecycleError = managed::RecycleError; /// [`Manager`] for creating and recycling PostgreSQL connections. /// @@ -78,6 +89,7 @@ pub struct Manager { } impl Manager { + #[cfg(not(target_arch = "wasm32"))] /// Creates a new [`Manager`] using the given [`tokio_postgres::Config`] and /// `tls` connector. pub fn new(pg_config: tokio_postgres::Config, tls: T) -> Self @@ -90,6 +102,7 @@ impl Manager { Self::from_config(pg_config, tls, ManagerConfig::default()) } + #[cfg(not(target_arch = "wasm32"))] /// Create a new [`Manager`] using the given [`tokio_postgres::Config`], and /// `tls` connector and [`ManagerConfig`]. pub fn from_config(pg_config: tokio_postgres::Config, tls: T, config: ManagerConfig) -> Self @@ -99,10 +112,20 @@ impl Manager { T::TlsConnect: Sync + Send, >::Future: Send, { + Self::from_connect(pg_config, ConfigConnectImpl { tls }, config) + } + + /// Create a new [`Manager`] using the given [`tokio_postgres::Config`], and + /// `connect` impl and [`ManagerConfig`]. + pub fn from_connect( + pg_config: tokio_postgres::Config, + connect: impl Connect + 'static, + config: ManagerConfig, + ) -> Self { Self { config, pg_config, - connect: Box::new(ConnectImpl { tls }), + connect: Box::new(connect), statement_caches: StatementCaches::default(), } } @@ -119,7 +142,6 @@ impl fmt::Debug for Manager { } } -#[async_trait] impl managed::Manager for Manager { type Type = ClientWrapper; type Error = Error; @@ -135,7 +157,7 @@ impl managed::Manager for Manager { async fn recycle(&self, client: &mut ClientWrapper, _: &Metrics) -> RecycleResult { if client.is_closed() { tracing::warn!(target: "deadpool.postgres", "Connection could not be recycled: Connection closed"); - return Err(RecycleError::StaticMessage("Connection closed")); + return Err(RecycleError::message("Connection closed")); } match self.config.recycling_method.query() { Some(sql) => match client.simple_query(sql).await { @@ -154,37 +176,57 @@ impl managed::Manager for Manager { } } -#[async_trait] -trait Connect: Sync + Send { - async fn connect(&self, pg_config: &PgConfig) -> Result<(PgClient, JoinHandle<()>), Error>; +/// Describes a mechanism for establishing a connection to a PostgreSQL +/// server via `tokio_postgres`. +pub trait Connect: Sync + Send { + /// Establishes a new `tokio_postgres` connection, returning + /// the associated `Client` and a `JoinHandle` to a tokio task + /// for processing the connection. + fn connect( + &self, + pg_config: &PgConfig, + ) -> BoxFuture<'_, Result<(PgClient, JoinHandle<()>), Error>>; } -struct ConnectImpl +#[cfg(not(target_arch = "wasm32"))] +/// Provides an implementation of [`Connect`] that establishes the connection +/// using the `tokio_postgres` configuration itself. +#[derive(Debug)] +pub struct ConfigConnectImpl where T: MakeTlsConnect + Clone + Sync + Send + 'static, T::Stream: Sync + Send, T::TlsConnect: Sync + Send, >::Future: Send, { - tls: T, + /// The TLS connector to use for the connection. + pub tls: T, } -#[async_trait] -impl Connect for ConnectImpl +#[cfg(not(target_arch = "wasm32"))] +impl Connect for ConfigConnectImpl where T: MakeTlsConnect + Clone + Sync + Send + 'static, T::Stream: Sync + Send, T::TlsConnect: Sync + Send, >::Future: Send, { - async fn connect(&self, pg_config: &PgConfig) -> Result<(PgClient, JoinHandle<()>), Error> { - let (client, connection) = pg_config.connect(self.tls.clone()).await?; - let conn_task = spawn(async move { - if let Err(e) = connection.await { - tracing::warn!(target: "deadpool.postgres", "Connection error: {}", e); - } - }); - Ok((client, conn_task)) + fn connect( + &self, + pg_config: &PgConfig, + ) -> BoxFuture<'_, Result<(PgClient, JoinHandle<()>), Error>> { + let tls = self.tls.clone(); + let pg_config = pg_config.clone(); + Box::pin(async move { + let fut = pg_config.connect(tls); + let (client, connection) = fut.await?; + let conn_task = spawn(async move { + if let Err(e) = connection.await { + tracing::warn!(target: "deadpool.postgres", "Connection error: {}", e); + } + }); + Ok((client, conn_task)) + }) } } diff --git a/postgres/tests/async_trait.rs b/postgres/tests/async_trait.rs new file mode 100644 index 00000000..018ac0d0 --- /dev/null +++ b/postgres/tests/async_trait.rs @@ -0,0 +1,26 @@ +// This code must compile even without the async_trait crate +// See: https://github.com/bikeshedder/deadpool/issues/323 + +use deadpool_postgres::{tokio_postgres::Row, GenericClient}; +use futures_util::{Stream, StreamExt}; +use std::future::Future; +use tokio_postgres::types::ToSql; + +// this function borrowed from tokio_postgres source code +fn slice_iter<'a>( + s: &'a [&'a (dyn ToSql + Sync)], +) -> impl ExactSizeIterator + 'a { + s.iter().map(|s| *s as _) +} + +pub trait PgQuery { + fn query_raw( + db: &impl GenericClient, + params: &[&(dyn ToSql + Sync)], + ) -> impl Future> + Send { + async { + let rows = db.query_raw("SELECT 1", slice_iter(params)).await.unwrap(); + rows.map(|row| row.unwrap()) + } + } +} diff --git a/postgres/tests/postgres.rs b/postgres/tests/postgres.rs index 0ea04856..7e64b42a 100644 --- a/postgres/tests/postgres.rs +++ b/postgres/tests/postgres.rs @@ -1,13 +1,12 @@ use std::{collections::HashMap, env, time::Duration}; use futures::future; -use serde_1::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; use tokio_postgres::{types::Type, IsolationLevel}; use deadpool_postgres::{ManagerConfig, Pool, RecyclingMethod, Runtime}; #[derive(Debug, Deserialize, Serialize)] -#[serde(crate = "serde_1")] struct Config { #[serde(default)] pg: deadpool_postgres::Config, @@ -115,7 +114,7 @@ async fn transaction_pipeline() { let stmt = client.prepare_cached("SELECT 1 + $1").await.unwrap(); let txn = client.transaction().await.unwrap(); let mut futures = vec![]; - for i in 0..100 { + for i in 0..100i32 { let stmt = stmt.clone(); let txn = &txn; futures.push(async move { @@ -274,3 +273,36 @@ fn config_from_env() { assert_eq!(pool_cfg.timeouts.create, Some(Duration::from_secs(2))); assert_eq!(pool_cfg.timeouts.recycle, Some(Duration::from_secs(3))); } + +#[test] +fn config_url() { + let mut cfg = deadpool_postgres::Config { + url: Some("postgresql://zombie@localhost/deadpool".into()), + ..Default::default() + }; + { + let pg_cfg = cfg.get_pg_config().unwrap(); + assert_eq!(pg_cfg.get_dbname(), Some("deadpool")); + assert_eq!(pg_cfg.get_user(), Some("zombie")); + assert_eq!( + pg_cfg.get_hosts(), + &[tokio_postgres::config::Host::Tcp("localhost".into())] + ); + } + // now apply some overrides + { + cfg.dbname = Some("livepool".into()); + cfg.host = Some("remotehost".into()); + cfg.user = Some("human".into()); + let pg_cfg = cfg.get_pg_config().unwrap(); + assert_eq!(pg_cfg.get_dbname(), Some("livepool")); + assert_eq!(pg_cfg.get_user(), Some("human")); + assert_eq!( + pg_cfg.get_hosts(), + &[ + tokio_postgres::config::Host::Tcp("localhost".into()), + tokio_postgres::config::Host::Tcp("remotehost".into()), + ] + ); + } +} diff --git a/r2d2/CHANGELOG.md b/r2d2/CHANGELOG.md index 7229e9cb..077166d7 100644 --- a/r2d2/CHANGELOG.md +++ b/r2d2/CHANGELOG.md @@ -1,17 +1,45 @@ -# Change Log +# Changelog -## v0.3.0 +All notable changes to this project will be documented in this file. -* Update `deadpool` dependency to version `0.10` -* Add `tracing` feature -* Bump up MSRV to `1.63` to match the one of `tokio` +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.2.0 + -* __Breaking:__ Replace `deadpool::managed::sync` by +## [Unreleased] + +## [0.4.1] - 2024-05-04 + +- Update `deadpool` dependency to version `0.12` +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates + +## [0.4.0] - 2024-04-01 + +- Update `deadpool` dependency to version `0.11` +- Remove `async_trait` dependency +- Bump up MSRV to `1.75` + +## [0.3.0] - 2023-09-26 + +- Update `deadpool` dependency to version `0.10` +- Add `tracing` feature +- Bump up MSRV to `1.63` to match the one of `tokio` + +## [0.2.0] - 2021-10-26 + +- __Breaking:__ Replace `deadpool::managed::sync` by `deadpool-sync::SyncWrapper` which fixes the return type of the `interact` method. -## v0.1.0 +## [0.1.0] - 2021-10-18 + +- First release -* First release + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-r2d2-v0.4.1...HEAD +[0.4.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-r2d2-v0.4.0...deadpool-r2d2-v0.4.1 +[0.4.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-r2d2-v0.3.0...deadpool-r2d2-v0.4.0 +[0.3.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-r2d2-v0.2.0...deadpool-r2d2-v0.3.0 +[0.2.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-r2d2-v0.1.0...deadpool-r2d2-v0.2.0 +[0.1.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-r2d2-v0.1.0 \ No newline at end of file diff --git a/r2d2/Cargo.toml b/r2d2/Cargo.toml index e13c7012..e87f12c8 100644 --- a/r2d2/Cargo.toml +++ b/r2d2/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-r2d2" -version = "0.3.0" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.4.1" +edition = "2021" +rust-version = "1.75" authors = ["Michael P. Jung "] description = "Dead simple async pool for r2d2 managers" keywords = ["async", "database", "pool", "r2d2"] @@ -23,7 +22,7 @@ serde = ["deadpool/serde"] tracing = ["deadpool-sync/tracing"] [dependencies] -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ +deadpool = { path = "../", version = "0.12.0", default-features = false, features = [ "managed", ] } deadpool-sync = { path = "../sync", version = "0.1.1" } @@ -31,5 +30,5 @@ r2d2 = { version = "0.8.9", default-features = false } [dev-dependencies] tokio = { version = "1.0", features = ["macros", "rt", "rt-multi-thread"] } -deadpool = { path = "../", version = "0.10.0", features = ["rt_tokio_1"] } +deadpool = { path = "../", version = "0.12", features = ["rt_tokio_1"] } r2d2_postgres = "0.18" diff --git a/r2d2/LICENSE-APACHE b/r2d2/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/r2d2/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/r2d2/LICENSE-MIT b/r2d2/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/r2d2/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/r2d2/README.md b/r2d2/README.md index 0737abed..6f9d541f 100644 --- a/r2d2/README.md +++ b/r2d2/README.md @@ -1,4 +1,4 @@ -# Deadpool for R2D2 Managers [![Latest Version](https://img.shields.io/crates/v/deadpool-r2d2.svg)](https://crates.io/crates/deadpool-r2d2) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for R2D2 Managers [![Latest Version](https://img.shields.io/crates/v/deadpool-r2d2.svg)](https://crates.io/crates/deadpool-r2d2) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. diff --git a/r2d2/src/manager.rs b/r2d2/src/manager.rs index f3337bf2..834833da 100644 --- a/r2d2/src/manager.rs +++ b/r2d2/src/manager.rs @@ -1,7 +1,6 @@ use std::{fmt, sync::Arc}; use deadpool::{ - async_trait, managed::{self, Metrics, RecycleError, RecycleResult}, Runtime, }; @@ -41,7 +40,6 @@ impl Manager { } } -#[async_trait] impl managed::Manager for Manager where M::Error: Send, @@ -56,19 +54,19 @@ where async fn recycle(&self, obj: &mut Self::Type, _: &Metrics) -> RecycleResult { if obj.is_mutex_poisoned() { - return Err(RecycleError::StaticMessage( + return Err(RecycleError::message( "Mutex is poisoned. Connection is considered unusable.", )); } let r2d2_manager = self.r2d2_manager.clone(); obj.interact::<_, RecycleResult>(move |obj| { if r2d2_manager.has_broken(obj) { - Err(RecycleError::StaticMessage("Connection is broken")) + Err(RecycleError::message("Connection is broken")) } else { r2d2_manager.is_valid(obj).map_err(RecycleError::Backend) } }) .await - .map_err(|e| RecycleError::Message(format!("Interaction failed: {}", e)))? + .map_err(|e| RecycleError::message(format!("Interaction failed: {}", e)))? } } diff --git a/redis-cluster/CHANGELOG.md b/redis-cluster/CHANGELOG.md deleted file mode 100644 index 502a9739..00000000 --- a/redis-cluster/CHANGELOG.md +++ /dev/null @@ -1,5 +0,0 @@ -# Change Log - -## v0.1.0 - -* First release diff --git a/redis-cluster/Cargo.toml b/redis-cluster/Cargo.toml deleted file mode 100644 index 60e37690..00000000 --- a/redis-cluster/Cargo.toml +++ /dev/null @@ -1,42 +0,0 @@ -[package] -name = "deadpool-redis-cluster" -version = "0.1.0" -edition = "2021" -resolver = "2" -rust-version = "1.63" -authors = [ - "Michael P. Jung ", - "Subeom Choi ", -] -description = "Dead simple async pool for redis-cluster" -keywords = ["async", "redis-cluster", "pool"] -license = "MIT OR Apache-2.0" -repository = "https://github.com/bikeshedder/deadpool" -readme = "README.md" - -[package.metadata.docs.rs] -all-features = true -rustdoc-args = ["--cfg", "docsrs"] - -[features] -default = ["rt_tokio_1"] -rt_tokio_1 = ["deadpool/rt_tokio_1", "redis/tokio-comp"] -rt_async-std_1 = ["deadpool/rt_async-std_1", "redis/async-std-comp"] -serde = ["deadpool/serde", "serde_1"] - -[dependencies] -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ - "managed", -] } -redis = { version = "0.23.0", default-features = false, features = ["aio"] } -redis_cluster_async = "0.8.0" -serde_1 = { package = "serde", version = "1.0.145", features = [ - "derive", -], optional = true } - -[dev-dependencies] -config = { version = "0.13.2", features = ["json"] } -dotenv = "0.15.0" -futures = "0.3.24" -redis = { version = "0.23.0", default-features = false, features = ["aio"] } -tokio = { version = "1.21.2", features = ["full"] } diff --git a/redis-cluster/README.md b/redis-cluster/README.md deleted file mode 100644 index 422c31e8..00000000 --- a/redis-cluster/README.md +++ /dev/null @@ -1,122 +0,0 @@ -# Deadpool for Redis Cluster [![Latest Version](https://img.shields.io/crates/v/deadpool-redis-cluster.svg)](https://crates.io/crates/deadpool-redis-cluster) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) - -Deadpool is a dead simple async pool for connections and objects -of any type. - -This crate implements a [`deadpool`](https://crates.io/crates/deadpool) -manager for [`redis-cluster`](https://crates.io/crates/redis_cluster_async). - -## Features - -| Feature | Description | Extra dependencies | Default | -| ---------------- | --------------------------------------------------------------------- | ------------------------------------------------- | ------- | -| `rt_tokio_1` | Enable support for [tokio](https://crates.io/crates/tokio) crate | `deadpool/rt_tokio_1`, `redis/tokio-comp` | yes | -| `rt_async-std_1` | Enable support for [async-std](https://crates.io/crates/config) crate | `deadpool/rt_async-std_1`, `redis/async-std-comp` | no | -| `serde` | Enable support for [serde](https://crates.io/crates/serde) crate | `deadpool/serde`, `serde/derive` | no | - -## Example - -```rust -use std::env; -use deadpool_redis_cluster::{redis::{cmd, FromRedisValue}, Config, Runtime}; - -#[tokio::main] -async fn main() { - let redis_urls = env::var("REDIS_CLUSTER__URLS") - .unwrap() - .split(',') - .map(String::from) - .collect::>(); - let mut cfg = Config::from_urls(redis_urls); - let pool = cfg.create_pool(Some(Runtime::Tokio1)).unwrap(); - { - let mut conn = pool.get().await.unwrap(); - cmd("SET") - .arg(&["deadpool/test_key", "42"]) - .query_async::<_, ()>(&mut conn) - .await.unwrap(); - } - { - let mut conn = pool.get().await.unwrap(); - let value: String = cmd("GET") - .arg(&["deadpool/test_key"]) - .query_async(&mut conn) - .await.unwrap(); - assert_eq!(value, "42".to_string()); - } -} -``` - -## Example with `config` and `dotenv` crate - -```rust -use deadpool_redis_cluster::{redis::{cmd, FromRedisValue}, Runtime}; -use dotenv::dotenv; -# use serde_1 as serde; - -#[derive(Debug, serde::Deserialize)] -# #[serde(crate = "serde_1")] -struct Config { - #[serde(default)] - redis_cluster: deadpool_redis_cluster::Config -} - -impl Config { - pub fn from_env() -> Result { - config::Config::builder() - .add_source( - config::Environment::default() - .separator("__") - .try_parsing(true) - .list_separator(","), - ) - .build()? - .try_deserialize() - } -} - -#[tokio::main] -async fn main() { - dotenv().ok(); - let cfg = Config::from_env().unwrap(); - let pool = cfg.redis_cluster.create_pool(Some(Runtime::Tokio1)).unwrap(); - { - let mut conn = pool.get().await.unwrap(); - cmd("SET") - .arg(&["deadpool/test_key", "42"]) - .query_async::<_, ()>(&mut conn) - .await.unwrap(); - } - { - let mut conn = pool.get().await.unwrap(); - let value: String = cmd("GET") - .arg(&["deadpool/test_key"]) - .query_async(&mut conn) - .await.unwrap(); - assert_eq!(value, "42".to_string()); - } -} -``` - -## FAQ - -- **How can I enable features of the `redis` crate?** - - Make sure that you depend on the same version of `redis` as - `deadpool-redis-cluster` does and enable the needed features in your own - `Crate.toml` file: - - ```toml - [dependencies] - deadpool-redis-cluster = { version = "0.9", features = ["serde"] } - redis = { version = "0.21", default-features = false, features = ["tls"] } - ``` - -## License - -Licensed under either of - -- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) -- MIT license ([LICENSE-MIT](LICENSE-MIT) or ) - -at your option. diff --git a/redis-cluster/src/config.rs b/redis-cluster/src/config.rs deleted file mode 100644 index 6339a630..00000000 --- a/redis-cluster/src/config.rs +++ /dev/null @@ -1,299 +0,0 @@ -use std::{fmt, path::PathBuf}; - -use redis::RedisError; -#[cfg(feature = "serde")] -use serde_1::{Deserialize, Serialize}; - -use crate::{CreatePoolError, Pool, PoolBuilder, PoolConfig, RedisResult, Runtime}; - -/// Configuration object. -/// -/// # Example (from environment) -/// -/// By enabling the `serde` feature you can read the configuration using the -/// [`config`](https://crates.io/crates/config) crate as following: -/// ```env -/// REDIS_CLUSTER__URLS=redis://127.0.0.1:7000,redis://127.0.0.1:7001 -/// REDIS_CLUSTER__POOL__MAX_SIZE=16 -/// REDIS_CLUSTER__POOL__TIMEOUTS__WAIT__SECS=2 -/// REDIS_CLUSTER__POOL__TIMEOUTS__WAIT__NANOS=0 -/// ``` -/// ```rust -/// # use serde_1 as serde; -/// # -/// #[derive(serde::Deserialize)] -/// # #[serde(crate = "serde_1")] -/// struct Config { -/// redis_cluster: deadpool_redis_cluster::Config, -/// } -/// -/// impl Config { -/// pub fn from_env() -> Result { -/// let mut cfg = config::Config::builder() -/// .add_source( -/// config::Environment::default() -/// .separator("__") -/// .try_parsing(true) -/// .list_separator(","), -/// ) -/// .build()?; -/// cfg.try_deserialize() -/// } -/// } -/// ``` -#[derive(Clone, Debug)] -#[cfg_attr(feature = "serde", derive(serde_1::Deserialize, serde_1::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] -pub struct Config { - /// Redis URLs. - /// - /// See [Connection Parameters](redis#connection-parameters). - pub urls: Option>, - - /// [`redis::ConnectionInfo`] structures. - pub connections: Option>, - - /// Pool configuration. - pub pool: Option, -} - -impl Config { - /// Creates a new [`Pool`] using this [`Config`]. - /// - /// # Errors - /// - /// See [`CreatePoolError`] for details. - pub fn create_pool(&self, runtime: Option) -> Result { - let mut builder = self.builder().map_err(CreatePoolError::Config)?; - if let Some(runtime) = runtime { - builder = builder.runtime(runtime); - } - builder.build().map_err(CreatePoolError::Build) - } - - /// Creates a new [`PoolBuilder`] using this [`Config`]. - /// - /// # Errors - /// - /// See [`ConfigError`] for details. - pub fn builder(&self) -> Result { - let manager = match (&self.urls, &self.connections) { - (Some(urls), None) => { - crate::Manager::new(urls.iter().map(|url| url.as_str()).collect())? - } - (None, Some(connections)) => crate::Manager::new(connections.clone())?, - (None, None) => crate::Manager::new(vec![ConnectionInfo::default()])?, - (Some(_), Some(_)) => return Err(ConfigError::UrlAndConnectionSpecified), - }; - let pool_config = self.get_pool_config(); - Ok(Pool::builder(manager).config(pool_config)) - } - - /// Returns [`deadpool::managed::PoolConfig`] which can be used to construct - /// a [`deadpool::managed::Pool`] instance. - #[must_use] - pub fn get_pool_config(&self) -> PoolConfig { - self.pool.unwrap_or_default() - } - - /// Creates a new [`Config`] from the given Redis URL (like - /// `redis://127.0.0.1`). - #[must_use] - pub fn from_urls>>(urls: T) -> Config { - Config { - urls: Some(urls.into()), - connections: None, - pool: None, - } - } -} - -impl Default for Config { - fn default() -> Self { - Self { - urls: None, - connections: Some(vec![ConnectionInfo::default()]), - pool: None, - } - } -} - -/// This is a 1:1 copy of the [`redis::ConnectionAddr`] enumeration. -/// This is duplicated here in order to add support for the -/// [`serde::Deserialize`] trait which is required for the [`serde`] support. -#[derive(Clone, Debug)] -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] -pub enum ConnectionAddr { - /// Format for this is `(host, port)`. - Tcp(String, u16), - - /// Format for this is `(host, port)`. - TcpTls { - /// Hostname. - host: String, - - /// Port. - port: u16, - - /// Disable hostname verification when connecting. - /// - /// # Warning - /// - /// You should think very carefully before you use this method. If - /// hostname verification is not used, any valid certificate for any - /// site will be trusted for use from any other. This introduces a - /// significant vulnerability to man-in-the-middle attacks. - insecure: bool, - }, - - /// Format for this is the path to the unix socket. - Unix(PathBuf), -} - -impl Default for ConnectionAddr { - fn default() -> Self { - Self::Tcp("127.0.0.1".to_string(), 6379) - } -} - -impl From for redis::ConnectionAddr { - fn from(addr: ConnectionAddr) -> Self { - match addr { - ConnectionAddr::Tcp(host, port) => Self::Tcp(host, port), - ConnectionAddr::TcpTls { - host, - port, - insecure, - } => Self::TcpTls { - host, - port, - insecure, - }, - ConnectionAddr::Unix(path) => Self::Unix(path), - } - } -} - -impl From for ConnectionAddr { - fn from(addr: redis::ConnectionAddr) -> Self { - match addr { - redis::ConnectionAddr::Tcp(host, port) => Self::Tcp(host, port), - redis::ConnectionAddr::TcpTls { - host, - port, - insecure, - } => ConnectionAddr::TcpTls { - host, - port, - insecure, - }, - redis::ConnectionAddr::Unix(path) => Self::Unix(path), - } - } -} - -/// This is a 1:1 copy of the [`redis::ConnectionInfo`] struct. -/// This is duplicated here in order to add support for the -/// [`serde::Deserialize`] trait which is required for the [`serde`] support. -#[derive(Clone, Debug, Default)] -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] -pub struct ConnectionInfo { - /// A connection address for where to connect to. - pub addr: ConnectionAddr, - - /// A boxed connection address for where to connect to. - #[cfg_attr(feature = "serde", serde(flatten))] - pub redis: RedisConnectionInfo, -} - -impl From for redis::ConnectionInfo { - fn from(info: ConnectionInfo) -> Self { - Self { - addr: info.addr.into(), - redis: info.redis.into(), - } - } -} - -impl From for ConnectionInfo { - fn from(info: redis::ConnectionInfo) -> Self { - Self { - addr: info.addr.into(), - redis: info.redis.into(), - } - } -} - -impl redis::IntoConnectionInfo for ConnectionInfo { - fn into_connection_info(self) -> RedisResult { - Ok(self.into()) - } -} - -/// This is a 1:1 copy of the [`redis::RedisConnectionInfo`] struct. -/// This is duplicated here in order to add support for the -/// [`serde::Deserialize`] trait which is required for the [`serde`] support. -#[derive(Clone, Debug, Default)] -#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] -pub struct RedisConnectionInfo { - /// The database number to use. This is usually `0`. - pub db: i64, - - /// Optionally a username that should be used for connection. - pub username: Option, - - /// Optionally a password that should be used for connection. - pub password: Option, -} - -impl From for redis::RedisConnectionInfo { - fn from(info: RedisConnectionInfo) -> Self { - Self { - db: info.db, - username: info.username, - password: info.password, - } - } -} - -impl From for RedisConnectionInfo { - fn from(info: redis::RedisConnectionInfo) -> Self { - Self { - db: info.db, - username: info.username, - password: info.password, - } - } -} - -/// This error is returned if the configuration contains an error -#[derive(Debug)] -pub enum ConfigError { - /// Both url and connection were specified in the config - UrlAndConnectionSpecified, - /// The [`redis`] crate returned an error when parsing the config - Redis(RedisError), -} - -impl From for ConfigError { - fn from(e: RedisError) -> Self { - Self::Redis(e) - } -} - -impl fmt::Display for ConfigError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::UrlAndConnectionSpecified => write!( - f, - "url and connection must not be specified at the same time." - ), - Self::Redis(e) => write!(f, "Redis: {}", e), - } - } -} - -impl std::error::Error for ConfigError {} diff --git a/redis/CHANGELOG.md b/redis/CHANGELOG.md index a203dde2..2f69aa8e 100644 --- a/redis/CHANGELOG.md +++ b/redis/CHANGELOG.md @@ -1,15 +1,43 @@ -# Change Log +# Changelog -## v0.13.0 +All notable changes to this project will be documented in this file. -* Update `deadpool` dependency to version `0.10` -* Bump up MSRV to `1.63` to match the one of `tokio` +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## v0.12.0 + + +## [Unreleased] + +## [0.15.1] - 2024-05-04 + +- Update `deadpool` dependency to version `0.12` +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates + +## [0.15.0] - 2024-04-01 + +- Update `redis` dependency to version `0.25` +- Update `deadpool` dependency to version `0.11` +- Remove `async_trait` dependency +- Bump up MSRV to `1.75` + +## [0.14.0] - 2023-12-15 + +- Merge `deadpool-redis-cluster` into `deadpool-redis`. +- Remove `redis_cluster_async` dependency in favor of `redis::cluster` / `redis::cluster_async`. +- Update `redis` dependency to version `0.24` +- Bump up MSRV to `1.63` to match the one of `redis` + +## [0.13.0] - 2023-09-26 + +- Update `deadpool` dependency to version `0.10` +- Bump up MSRV to `1.63` to match the one of `tokio` + +## [0.12.0] - 2023-04-24 - Update `redis` dependency to version `0.23` -## v0.11.1 +## [0.11.1] - 2022-12-09 - Export missing config structures: - `ConnectionAddr` @@ -17,36 +45,44 @@ - `RedisConnectionInfo` - Add `Config::from_connection_info` method -## v0.11.0 +## [0.11.0] - 2022-10-26 - Update `redis` dependency to version `0.22` -## v0.10.2 +## [0.10.2] - 2022-01-03 - Fix bug causing connections not to be recycled -## v0.10.1 +## [0.10.1] - 2021-11-15 - Config structs now implement `Serialize` -## v0.10.0 +## [0.10.0] - 2021-10-18 - **Breaking:** Replace `config` feature with `serde` (opted out by default) - Fix `std::error::Error::source` implementations for library errors - Remove unused `log` dependency -## v0.9.0 +## [0.9.0] - 2021-08-19 - Remove `deadpool_redis::Connection` type alias - Rename `deadpool_redis::ConnectionWrapper` to `Connection` - Update `redis` dependency to version `0.21` - Add `Config::from_url` method -## v0.8.1 +## [0.8.1] - 2021-06-01 - Export `PoolCreateError` -## v0.8.0 +## [0.6.2] and [0.7.2] - 2021-06-01 + +Release of 0.6 and 0.7 with the following feature backported: + +- Make connection recycling more robust by checking the PING + response. This works around `Cmd::query_async` not being drop + safe in `redis` version `0.10` and earlier. + +## [0.8.0] - 2021-05-21 - Update `config` dependency to version `0.11` - Remove deprecated `from_env` methods @@ -61,11 +97,11 @@ safe in `redis` version `0.10` and earlier. - Add `rt_tokio_1` and `rt_async-std_1` features -## v0.7.1 +## [0.7.1] - 2021-02-22 - Change `redis` dependency to version range `0.19` to `0.20` -## v0.7.0 +## [0.7.0] - 2020-12-26 - Update `deadpool` dependency to version `0.3` - Update `redis` dependency to version `0.19` @@ -73,42 +109,42 @@ - Mark `Config::from_env` as deprecated - Re-export `deadpool::managed::PoolConfig` -## v0.6.1 +## [0.6.1] - 2020-08-27 - Change `redis` dependency to version range `0.15` to `0.17` -## v0.6.0 +## [0.6.0] - 2020-07-14 - Update `redis` dependency to version `0.16.0` - Re-export `redis` crate -## v0.5.2 +## [0.5.2] - 2020-02-04 - Update `redis` dependency to version `0.15.1` - Add `#[derive(Clone)]` to `Config` struct - Add `Connection` type alias -## v0.5.1 +## [0.5.1] - 2020-01-18 - Disable `default-features` for `deadpool` dependency -## v0.5.0 +## [0.5.0] - 2020-01-16 - Update `redis` dependency to version `0.14.0` - Rename `query` to `query_async` to match API of `redis` crate - Rename `execute` to `execute_async` to match API of `redis` crate - Add support for `config` crate -## v0.4.1 +## [0.4.1] - 2019-12-31 - Add `PoolError` type alias -## v0.4.0 +## [0.4.0] - 2019-12-16 - Rename `Connection` to `ConnectionWrapper` - Add `Connection` type alias -## v0.3.0 +## [0.3.0] - 2019-12-13 - Add pipeline support - Add wrappers for `Cmd` and `Pipeline` to mimick the API of the `redis` crate @@ -116,6 +152,35 @@ consuming API. - Add proper connection using the `PING` command -## v0.2.0 +## [0.2.0] - 2019-12-03 - First release + + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.15.1...HEAD +[0.15.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.15.0...deadpool-redis-v0.15.1 +[0.15.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.14.0...deadpool-redis-v0.15.0 +[0.14.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.13.0...deadpool-redis-v0.14.0 +[0.13.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.12.0...deadpool-redis-v0.13.0 +[0.12.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.11.1...deadpool-redis-v0.12.0 +[0.11.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.11.0...deadpool-redis-v0.11.1 +[0.11.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.10.2...deadpool-redis-v0.11.0 +[0.10.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.10.1...deadpool-redis-v0.10.2 +[0.10.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.10.0...deadpool-redis-v0.10.1 +[0.10.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.9.0...deadpool-redis-v0.10.0 +[0.9.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.8.1...deadpool-redis-v0.9.0 +[0.8.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.8.0...deadpool-redis-v0.8.1 +[0.8.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.7.1...deadpool-redis-v0.8.0 +[0.7.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.7.1...deadpool-redis-v0.7.2 +[0.7.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.7.0...deadpool-redis-v0.7.1 +[0.7.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.6.1...deadpool-redis-v0.7.0 +[0.6.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.6.1...deadpool-redis-v0.6.2 +[0.6.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.6.0...deadpool-redis-v0.6.1 +[0.6.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.5.2...deadpool-redis-v0.6.0 +[0.5.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.5.1...deadpool-redis-v0.5.2 +[0.5.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.5.0...deadpool-redis-v0.5.1 +[0.5.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.4.1...deadpool-redis-v0.5.0 +[0.4.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.4.0...deadpool-redis-v0.4.1 +[0.4.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.3.0...deadpool-redis-v0.4.0 +[0.3.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-redis-v0.2.0...deadpool-redis-v0.3.0 +[0.2.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-redis-v0.2.0 \ No newline at end of file diff --git a/redis/Cargo.toml b/redis/Cargo.toml index f51313b8..7f6ea4f3 100644 --- a/redis/Cargo.toml +++ b/redis/Cargo.toml @@ -1,10 +1,12 @@ [package] name = "deadpool-redis" -version = "0.13.0" -edition = "2018" -resolver = "2" -rust-version = "1.63" -authors = ["Michael P. Jung "] +version = "0.15.1" +edition = "2021" +rust-version = "1.75" +authors = [ + "Michael P. Jung ", + "Subeom Choi ", +] description = "Dead simple async pool for redis" keywords = ["async", "redis", "pool"] license = "MIT OR Apache-2.0" @@ -19,22 +21,23 @@ rustdoc-args = ["--cfg", "docsrs"] default = ["rt_tokio_1"] rt_tokio_1 = ["deadpool/rt_tokio_1", "redis/tokio-comp"] rt_async-std_1 = ["deadpool/rt_async-std_1", "redis/async-std-comp"] -serde = ["deadpool/serde", "serde_1"] +serde = ["deadpool/serde", "dep:serde"] +cluster = ["redis/cluster-async"] [dependencies] -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ +deadpool = { path = "../", version = "0.12.0", default-features = false, features = [ "managed", ] } -redis = { version = "0.23", default-features = false, features = ["aio"] } -serde_1 = { package = "serde", version = "1.0", features = [ +redis = { version = "0.25", default-features = false, features = ["aio"] } +serde = { package = "serde", version = "1.0", features = [ "derive", ], optional = true } [dev-dependencies] -config = { version = "0.13", features = ["json"] } -dotenv = "0.15.0" +config = { version = "0.14", features = ["json"] } +dotenvy = "0.15.0" futures = "0.3.15" -redis = { version = "0.23", default-features = false, features = [ +redis = { version = "0.25", default-features = false, features = [ "tokio-comp", ] } tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } diff --git a/redis/LICENSE-APACHE b/redis/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/redis/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/redis/LICENSE-MIT b/redis/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/redis/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/redis/README.md b/redis/README.md index 5402f6df..0c93c708 100644 --- a/redis/README.md +++ b/redis/README.md @@ -1,4 +1,4 @@ -# Deadpool for Redis [![Latest Version](https://img.shields.io/crates/v/deadpool-redis.svg)](https://crates.io/crates/deadpool-redis) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for Redis [![Latest Version](https://img.shields.io/crates/v/deadpool-redis.svg)](https://crates.io/crates/deadpool-redis) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. @@ -13,6 +13,7 @@ manager for [`redis`](https://crates.io/crates/redis). | `rt_tokio_1` | Enable support for [tokio](https://crates.io/crates/tokio) crate | `deadpool/rt_tokio_1`, `redis/tokio-comp` | yes | | `rt_async-std_1` | Enable support for [async-std](https://crates.io/crates/config) crate | `deadpool/rt_async-std_1`, `redis/async-std-comp` | no | | `serde` | Enable support for [serde](https://crates.io/crates/serde) crate | `deadpool/serde`, `serde/derive` | no | +| `cluster` | Enable support for Redis Cluster | `redis/cluster-async` | no | ## Example @@ -43,15 +44,13 @@ async fn main() { } ``` -## Example with `config` and `dotenv` crate +### Example with `config` and `dotenvy` crate ```rust use deadpool_redis::{redis::{cmd, FromRedisValue}, Runtime}; -use dotenv::dotenv; -# use serde_1 as serde; +use dotenvy::dotenv; #[derive(Debug, serde::Deserialize)] -# #[serde(crate = "serde_1")] struct Config { #[serde(default)] redis: deadpool_redis::Config @@ -89,6 +88,90 @@ async fn main() { } ``` +## Example (Cluster) + +```rust +use std::env; +use deadpool_redis::{redis::{cmd, FromRedisValue}}; +use deadpool_redis::cluster::{Config, Runtime}; + +#[tokio::main] +async fn main() { + let redis_urls = env::var("REDIS_CLUSTER__URLS") + .unwrap() + .split(',') + .map(String::from) + .collect::>(); + let mut cfg = Config::from_urls(redis_urls); + let pool = cfg.create_pool(Some(Runtime::Tokio1)).unwrap(); + { + let mut conn = pool.get().await.unwrap(); + cmd("SET") + .arg(&["deadpool/test_key", "42"]) + .query_async::<_, ()>(&mut conn) + .await.unwrap(); + } + { + let mut conn = pool.get().await.unwrap(); + let value: String = cmd("GET") + .arg(&["deadpool/test_key"]) + .query_async(&mut conn) + .await.unwrap(); + assert_eq!(value, "42".to_string()); + } +} +``` + +### Example with `config` and `dotenvy` crate + +```rust +use deadpool_redis::redis::{cmd, FromRedisValue}; +use deadpool_redis::cluster::{Runtime}; +use dotenvy::dotenv; + +#[derive(Debug, serde::Deserialize)] +struct Config { + #[serde(default)] + redis_cluster: deadpool_redis::cluster::Config +} + +impl Config { + pub fn from_env() -> Result { + config::Config::builder() + .add_source( + config::Environment::default() + .separator("__") + .try_parsing(true) + .list_separator(","), + ) + .build()? + .try_deserialize() + } +} + +#[tokio::main] +async fn main() { + dotenv().ok(); + let cfg = Config::from_env().unwrap(); + let pool = cfg.redis_cluster.create_pool(Some(Runtime::Tokio1)).unwrap(); + { + let mut conn = pool.get().await.unwrap(); + cmd("SET") + .arg(&["deadpool/test_key", "42"]) + .query_async::<_, ()>(&mut conn) + .await.unwrap(); + } + { + let mut conn = pool.get().await.unwrap(); + let value: String = cmd("GET") + .arg(&["deadpool/test_key"]) + .query_async(&mut conn) + .await.unwrap(); + assert_eq!(value, "42".to_string()); + } +} +``` + ## FAQ - **How can I enable features of the `redis` crate?** diff --git a/redis/src/cluster/config.rs b/redis/src/cluster/config.rs new file mode 100644 index 00000000..d45b91ed --- /dev/null +++ b/redis/src/cluster/config.rs @@ -0,0 +1,112 @@ +pub use crate::config::ConfigError; +use crate::ConnectionInfo; + +use super::{CreatePoolError, Pool, PoolBuilder, PoolConfig, Runtime}; + +/// Configuration object. +/// +/// # Example (from environment) +/// +/// By enabling the `serde` feature you can read the configuration using the +/// [`config`](https://crates.io/crates/config) crate as following: +/// ```env +/// REDIS_CLUSTER__URLS=redis://127.0.0.1:7000,redis://127.0.0.1:7001 +/// REDIS_CLUSTER__POOL__MAX_SIZE=16 +/// REDIS_CLUSTER__POOL__TIMEOUTS__WAIT__SECS=2 +/// REDIS_CLUSTER__POOL__TIMEOUTS__WAIT__NANOS=0 +/// ``` +/// ```rust +/// #[derive(serde::Deserialize)] +/// struct Config { +/// redis_cluster: deadpool_redis::cluster::Config, +/// } +/// +/// impl Config { +/// pub fn from_env() -> Result { +/// let mut cfg = config::Config::builder() +/// .add_source( +/// config::Environment::default() +/// .separator("__") +/// .try_parsing(true) +/// .list_separator(","), +/// ) +/// .build()?; +/// cfg.try_deserialize() +/// } +/// } +/// ``` +#[derive(Clone, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +pub struct Config { + /// Redis URLs. + /// + /// See [Connection Parameters](redis#connection-parameters). + pub urls: Option>, + + /// [`redis::ConnectionInfo`] structures. + pub connections: Option>, + + /// Pool configuration. + pub pool: Option, +} + +impl Config { + /// Creates a new [`Pool`] using this [`Config`]. + /// + /// # Errors + /// + /// See [`CreatePoolError`] for details. + pub fn create_pool(&self, runtime: Option) -> Result { + let mut builder = self.builder().map_err(CreatePoolError::Config)?; + if let Some(runtime) = runtime { + builder = builder.runtime(runtime); + } + builder.build().map_err(CreatePoolError::Build) + } + + /// Creates a new [`PoolBuilder`] using this [`Config`]. + /// + /// # Errors + /// + /// See [`ConfigError`] for details. + pub fn builder(&self) -> Result { + let manager = match (&self.urls, &self.connections) { + (Some(urls), None) => { + super::Manager::new(urls.iter().map(|url| url.as_str()).collect())? + } + (None, Some(connections)) => super::Manager::new(connections.clone())?, + (None, None) => super::Manager::new(vec![ConnectionInfo::default()])?, + (Some(_), Some(_)) => return Err(ConfigError::UrlAndConnectionSpecified), + }; + let pool_config = self.get_pool_config(); + Ok(Pool::builder(manager).config(pool_config)) + } + + /// Returns [`deadpool::managed::PoolConfig`] which can be used to construct + /// a [`deadpool::managed::Pool`] instance. + #[must_use] + pub fn get_pool_config(&self) -> PoolConfig { + self.pool.unwrap_or_default() + } + + /// Creates a new [`Config`] from the given Redis URL (like + /// `redis://127.0.0.1`). + #[must_use] + pub fn from_urls>>(urls: T) -> Config { + Config { + urls: Some(urls.into()), + connections: None, + pool: None, + } + } +} + +impl Default for Config { + fn default() -> Self { + Self { + urls: None, + connections: Some(vec![ConnectionInfo::default()]), + pool: None, + } + } +} diff --git a/redis-cluster/src/lib.rs b/redis/src/cluster/mod.rs similarity index 58% rename from redis-cluster/src/lib.rs rename to redis/src/cluster/mod.rs index 29b35eff..c9e44b99 100644 --- a/redis-cluster/src/lib.rs +++ b/redis/src/cluster/mod.rs @@ -1,26 +1,4 @@ -#![doc = include_str!("../README.md")] -#![cfg_attr(docsrs, feature(doc_cfg))] -#![deny( - nonstandard_style, - rust_2018_idioms, - rustdoc::broken_intra_doc_links, - rustdoc::private_intra_doc_links -)] -#![forbid(non_ascii_idents, unsafe_code)] -#![warn( - deprecated_in_future, - missing_copy_implementations, - missing_debug_implementations, - missing_docs, - unreachable_pub, - unused_import_braces, - unused_labels, - unused_lifetimes, - unused_qualifications, - unused_results -)] -#![allow(clippy::uninlined_format_args)] - +//! This module extends the library to support Redis Cluster. mod config; use std::{ @@ -28,11 +6,12 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, }; -use deadpool::{async_trait, managed}; +use deadpool::managed; use redis::{aio::ConnectionLike, IntoConnectionInfo, RedisError, RedisResult}; -pub use redis; -pub use redis_cluster_async::{Client, Connection as RedisConnection}; +use redis; +pub use redis::cluster::ClusterClient; +pub use redis::cluster_async::ClusterConnection; pub use self::config::{Config, ConfigError}; @@ -47,11 +26,11 @@ deadpool::managed_reexports!( type RecycleResult = managed::RecycleResult; -/// Wrapper around [`redis_cluster_async::Connection`]. +/// Wrapper around [`redis::cluster_async::ClusterConnection`]. /// /// This structure implements [`redis::aio::ConnectionLike`] and can therefore -/// be used just like a regular [`redis_cluster_async::Connection`]. -#[allow(missing_debug_implementations)] // `redis_cluster_async::Connection: !Debug` +/// be used just like a regular [`redis::cluster_async::ClusterConnection`]. +#[allow(missing_debug_implementations)] // `redis::cluster_async::ClusterConnection: !Debug` pub struct Connection { conn: Object, } @@ -61,7 +40,7 @@ impl Connection { /// /// This reduces the size of the [`Pool`]. #[must_use] - pub fn take(this: Self) -> RedisConnection { + pub fn take(this: Self) -> ClusterConnection { Object::take(this.conn) } } @@ -73,27 +52,27 @@ impl From for Connection { } impl Deref for Connection { - type Target = RedisConnection; + type Target = ClusterConnection; - fn deref(&self) -> &RedisConnection { + fn deref(&self) -> &ClusterConnection { &self.conn } } impl DerefMut for Connection { - fn deref_mut(&mut self) -> &mut RedisConnection { + fn deref_mut(&mut self) -> &mut ClusterConnection { &mut self.conn } } -impl AsRef for Connection { - fn as_ref(&self) -> &RedisConnection { +impl AsRef for Connection { + fn as_ref(&self) -> &ClusterConnection { &self.conn } } -impl AsMut for Connection { - fn as_mut(&mut self) -> &mut RedisConnection { +impl AsMut for Connection { + fn as_mut(&mut self) -> &mut ClusterConnection { &mut self.conn } } @@ -120,15 +99,15 @@ impl ConnectionLike for Connection { } } -/// [`Manager`] for creating and recycling [`redis_cluster_async`] connections. +/// [`Manager`] for creating and recycling [`redis::cluster_async`] connections. /// /// [`Manager`]: managed::Manager pub struct Manager { - client: Client, + client: ClusterClient, ping_number: AtomicUsize, } -// `redis_cluster_async::Client: !Debug` +// `redis::cluster_async::ClusterClient: !Debug` impl std::fmt::Debug for Manager { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Manager") @@ -143,26 +122,25 @@ impl Manager { /// /// # Errors /// - /// If establishing a new [`Client`] fails. + /// If establishing a new [`ClusterClient`] fails. pub fn new(params: Vec) -> RedisResult { Ok(Self { - client: Client::open(params)?, + client: ClusterClient::new(params)?, ping_number: AtomicUsize::new(0), }) } } -#[async_trait] impl managed::Manager for Manager { - type Type = RedisConnection; + type Type = ClusterConnection; type Error = RedisError; - async fn create(&self) -> Result { - let conn = self.client.get_connection().await?; + async fn create(&self) -> Result { + let conn = self.client.get_async_connection().await?; Ok(conn) } - async fn recycle(&self, conn: &mut RedisConnection, _: &Metrics) -> RecycleResult { + async fn recycle(&self, conn: &mut ClusterConnection, _: &Metrics) -> RecycleResult { let ping_number = self.ping_number.fetch_add(1, Ordering::Relaxed).to_string(); let n = redis::cmd("PING") .arg(&ping_number) @@ -171,9 +149,7 @@ impl managed::Manager for Manager { if n == ping_number { Ok(()) } else { - Err(managed::RecycleError::StaticMessage( - "Invalid PING response", - )) + Err(managed::RecycleError::message("Invalid PING response")) } } } diff --git a/redis/src/config.rs b/redis/src/config.rs index 3a25d298..98ae8512 100644 --- a/redis/src/config.rs +++ b/redis/src/config.rs @@ -3,8 +3,6 @@ use std::{fmt, path::PathBuf}; use redis::RedisError; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; -#[cfg(feature = "serde")] -use serde_1 as serde; use crate::{CreatePoolError, Pool, PoolBuilder, PoolConfig, RedisResult, Runtime}; @@ -15,16 +13,13 @@ use crate::{CreatePoolError, Pool, PoolBuilder, PoolConfig, RedisResult, Runtime /// By enabling the `serde` feature you can read the configuration using the /// [`config`](https://crates.io/crates/config) crate as following: /// ```env -/// REDIS__CONNECTION__ADDR=redis.example.com +/// REDIS__URL=redis.example.com /// REDIS__POOL__MAX_SIZE=16 /// REDIS__POOL__TIMEOUTS__WAIT__SECS=2 /// REDIS__POOL__TIMEOUTS__WAIT__NANOS=0 /// ``` /// ```rust -/// # use serde_1 as serde; -/// /// #[derive(serde::Deserialize)] -/// # #[serde(crate = "serde_1")] /// struct Config { /// redis: deadpool_redis::Config, /// } @@ -124,7 +119,8 @@ impl Default for Config { } } -/// This is a 1:1 copy of the [`redis::ConnectionAddr`] enumeration. +/// This is a 1:1 copy of the [`redis::ConnectionAddr`] enumeration (excluding `tls_params` since it is entirely opaque to consumers). +/// /// This is duplicated here in order to add support for the /// [`serde::Deserialize`] trait which is required for the [`serde`] support. #[derive(Clone, Debug)] @@ -175,6 +171,7 @@ impl From for redis::ConnectionAddr { host, port, insecure, + tls_params: None, }, ConnectionAddr::Unix(path) => Self::Unix(path), } @@ -189,6 +186,7 @@ impl From for ConnectionAddr { host, port, insecure, + .. } => ConnectionAddr::TcpTls { host, port, diff --git a/redis/src/lib.rs b/redis/src/lib.rs index 7305b0d3..84ed2954 100644 --- a/redis/src/lib.rs +++ b/redis/src/lib.rs @@ -21,6 +21,8 @@ )] #![allow(clippy::uninlined_format_args)] +#[cfg(feature = "cluster")] +pub mod cluster; mod config; use std::{ @@ -28,9 +30,9 @@ use std::{ sync::atomic::{AtomicUsize, Ordering}, }; -use deadpool::{async_trait, managed}; +use deadpool::managed; use redis::{ - aio::{Connection as RedisConnection, ConnectionLike}, + aio::{ConnectionLike, MultiplexedConnection}, Client, IntoConnectionInfo, RedisError, RedisResult, }; @@ -44,11 +46,11 @@ deadpool::managed_reexports!("redis", Manager, Connection, RedisError, ConfigErr /// Type alias for using [`deadpool::managed::RecycleResult`] with [`redis`]. type RecycleResult = managed::RecycleResult; -/// Wrapper around [`redis::aio::Connection`]. +/// Wrapper around [`redis::aio::MultiplexedConnection`]. /// /// This structure implements [`redis::aio::ConnectionLike`] and can therefore -/// be used just like a regular [`redis::aio::Connection`]. -#[allow(missing_debug_implementations)] // `redis::aio::Connection: !Debug` +/// be used just like a regular [`redis::aio::MultiplexedConnection`]. +#[allow(missing_debug_implementations)] // `redis::aio::MultiplexedConnection: !Debug` pub struct Connection { conn: Object, } @@ -58,7 +60,7 @@ impl Connection { /// /// This reduces the size of the [`Pool`]. #[must_use] - pub fn take(this: Self) -> RedisConnection { + pub fn take(this: Self) -> MultiplexedConnection { Object::take(this.conn) } } @@ -70,27 +72,27 @@ impl From for Connection { } impl Deref for Connection { - type Target = RedisConnection; + type Target = MultiplexedConnection; - fn deref(&self) -> &RedisConnection { + fn deref(&self) -> &MultiplexedConnection { &self.conn } } impl DerefMut for Connection { - fn deref_mut(&mut self) -> &mut RedisConnection { + fn deref_mut(&mut self) -> &mut MultiplexedConnection { &mut self.conn } } -impl AsRef for Connection { - fn as_ref(&self) -> &redis::aio::Connection { +impl AsRef for Connection { + fn as_ref(&self) -> &MultiplexedConnection { &self.conn } } -impl AsMut for Connection { - fn as_mut(&mut self) -> &mut redis::aio::Connection { +impl AsMut for Connection { + fn as_mut(&mut self) -> &mut MultiplexedConnection { &mut self.conn } } @@ -140,17 +142,16 @@ impl Manager { } } -#[async_trait] impl managed::Manager for Manager { - type Type = RedisConnection; + type Type = MultiplexedConnection; type Error = RedisError; - async fn create(&self) -> Result { - let conn = self.client.get_async_connection().await?; + async fn create(&self) -> Result { + let conn = self.client.get_multiplexed_async_connection().await?; Ok(conn) } - async fn recycle(&self, conn: &mut RedisConnection, _: &Metrics) -> RecycleResult { + async fn recycle(&self, conn: &mut MultiplexedConnection, _: &Metrics) -> RecycleResult { let ping_number = self.ping_number.fetch_add(1, Ordering::Relaxed).to_string(); // Using pipeline to avoid roundtrip for UNWATCH let (n,) = redis::Pipeline::with_capacity(2) @@ -163,9 +164,7 @@ impl managed::Manager for Manager { if n == ping_number { Ok(()) } else { - Err(managed::RecycleError::StaticMessage( - "Invalid PING response", - )) + Err(managed::RecycleError::message("Invalid PING response")) } } } diff --git a/redis/tests/redis.rs b/redis/tests/redis.rs index 9599f3a3..4fc8c205 100644 --- a/redis/tests/redis.rs +++ b/redis/tests/redis.rs @@ -3,10 +3,9 @@ use deadpool_redis::Runtime; use futures::FutureExt; use redis::cmd; -use serde_1::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Deserialize, Serialize)] -#[serde(crate = "serde_1")] struct Config { #[serde(default)] redis: deadpool_redis::Config, diff --git a/redis-cluster/tests/redis.rs b/redis/tests/redis_cluster.rs similarity index 90% rename from redis-cluster/tests/redis.rs rename to redis/tests/redis_cluster.rs index f0fe0a44..9ef736ba 100644 --- a/redis-cluster/tests/redis.rs +++ b/redis/tests/redis_cluster.rs @@ -1,15 +1,14 @@ #![cfg(feature = "serde")] -use deadpool_redis_cluster::Runtime; +use deadpool_redis::cluster::Runtime; use futures::FutureExt; use redis::cmd; -use serde_1::{Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Default, Deserialize, Serialize)] -#[serde(crate = "serde_1")] struct Config { #[serde(default)] - redis_cluster: deadpool_redis_cluster::Config, + redis_cluster: deadpool_redis::cluster::Config, } impl Config { @@ -28,7 +27,7 @@ impl Config { } } -fn create_pool() -> deadpool_redis_cluster::Pool { +fn create_pool() -> deadpool_redis::cluster::Pool { let cfg = Config::from_env(); cfg.redis_cluster .create_pool(Some(Runtime::Tokio1)) @@ -37,7 +36,7 @@ fn create_pool() -> deadpool_redis_cluster::Pool { #[tokio::test] async fn test_pipeline() { - use deadpool_redis_cluster::redis::pipe; + use deadpool_redis::redis::pipe; let pool = create_pool(); let mut conn = pool.get().await.unwrap(); let (value,): (String,) = pipe() @@ -55,7 +54,7 @@ async fn test_pipeline() { #[tokio::test] async fn test_high_level_commands() { - use deadpool_redis_cluster::redis::AsyncCommands; + use deadpool_redis::redis::AsyncCommands; let pool = create_pool(); let mut conn = pool.get().await.unwrap(); let _: () = conn.set("deadpool/hlc_test_key", 42).await.unwrap(); diff --git a/release.toml b/release.toml new file mode 100644 index 00000000..10500883 --- /dev/null +++ b/release.toml @@ -0,0 +1,6 @@ +pre-release-replacements = [ + { file = "CHANGELOG.md", search = "[Unreleased]", replace = "[{{version}}] {{date}}" }, + { file = "CHANGELOG.md", search = "\\.\\.\\.HEAD", replace = "...{{tag_name}}", exactly = 1 }, + { file = "CHANGELOG.md", search = "", replace = "\n\n## [Unreleased]", exactly = 1 }, + { file = "CHANGELOG.md", search = "", replace = "\n[Unreleased]: https://github.com/bikeshedder/deadpool/compare/{{tag_name}}...HEAD", exactly = 1 }, +] diff --git a/runtime/CHANGELOG.md b/runtime/CHANGELOG.md index f7e0193d..81f44544 100644 --- a/runtime/CHANGELOG.md +++ b/runtime/CHANGELOG.md @@ -1,15 +1,38 @@ -## v0.1.3 +# Changelog -* Bump up MSRV to `1.63` to match the one of `tokio` +All notable changes to this project will be documented in this file. -## v0.1.2 +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).# Changelog -* Fix links to tokio and async-std in documentation + -## v0.1.1 +## [Unreleased] -* Fix tokio feature dependencies +## [0.1.4] - 2024-05-24 -## v0.1.0 +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates -* First release +## [0.1.3] - 2023-09-26 + +- Bump up MSRV to `1.63` to match the one of `tokio` + +## [0.1.2] - 2021-10-26 + +- Fix links to tokio and async-std in documentation + +## [0.1.1] - 2021-10-26 + +- Fix tokio feature dependencies + +## [0.1.0] - 2021-10-26 (yanked) + +- First release + + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-runtime-v0.1.4...HEAD +[0.1.4]: https://github.com/bikeshedder/deadpool/compare/deadpool-runtime-v0.1.3...deadpool-runtime-v0.1.4 +[0.1.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-runtime-v0.1.2...deadpool-runtime-v0.1.3 +[0.1.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-runtime-v0.1.1...deadpool-runtime-v0.1.2 +[0.1.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-runtime-v0.1.0...deadpool-runtime-v0.1.1 +[0.1.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-runtime-v0.1.0 \ No newline at end of file diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index bb29b20c..bd430ecb 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-runtime" -version = "0.1.3" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.1.4" +edition = "2021" +rust-version = "1.75" authors = ["Michael P. Jung "] description = "Dead simple async pool utitities for sync managers" keywords = ["async", "database", "pool", "sync", "utils"] diff --git a/runtime/LICENSE-APACHE b/runtime/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/runtime/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/runtime/LICENSE-MIT b/runtime/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/runtime/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/runtime/README.md b/runtime/README.md index a02a4c2d..0b865c52 100644 --- a/runtime/README.md +++ b/runtime/README.md @@ -1,4 +1,4 @@ -# Deadpool runtime abstraction [![Latest Version](https://img.shields.io/crates/v/deadpool-runtime.svg)](https://crates.io/crates/deadpool-runtime) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool runtime abstraction [![Latest Version](https://img.shields.io/crates/v/deadpool-runtime.svg)](https://crates.io/crates/deadpool-runtime) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. diff --git a/sqlite/CHANGELOG.md b/sqlite/CHANGELOG.md index d31cf232..6d157f75 100644 --- a/sqlite/CHANGELOG.md +++ b/sqlite/CHANGELOG.md @@ -1,36 +1,73 @@ -## v0.6.0 +# Changelog -* Update `deadpool` dependency to version `0.10` -* Update `rusqlite` dependency to version `0.29` -* Add `tracing` feature -* Bump up MSRV to `1.63` to match the one of `tokio` +All notable changes to this project will be documented in this file. -## v0.5.0 +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + + + +## [Unreleased] + +## [0.8.1] - 2024-05-04 + +- Update `deadpool` dependency to version `0.12` +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates + +## [0.8.0] - 2024-04-01 + +- Update `rusqlite` dependency to version `0.31` +- Remove `async_trait` dependency + +## [0.7.0] - 2023-11-14 + +- Update `rusqlite` dependency to version `0.30` + +## [0.6.0] - 2023-09-26 + +- Update `deadpool` dependency to version `0.10` +- Update `rusqlite` dependency to version `0.29` +- Add `tracing` feature +- Bump up MSRV to `1.63` to match the one of `tokio` + +## [0.5.0] - 2022-07-18 - Update `rusqlite` dependency to version `0.28` -## v0.4.0 +## [0.4.0] - 2022-04-04 - Update `rusqlite` dependency to version `0.27` -## v0.3.1 +## [0.3.1] - 2021-11-15 -* Config structs now implement `Serialize` +- Config structs now implement `Serialize` -## v0.3.0 +## [0.3.0] - 2021-10-26 -* __Breaking:__ Replace `deadpool::managed::sync` by +- __Breaking:__ Replace `deadpool::managed::sync` by `deadpool-sync::SyncWrapper` which fixes the return type of the `interact` method. -## v0.2.0 +## [0.2.0] - 2021-10-18 + +- __Breaking:__ Replace `config` feature with `serde` (opted out by default) +- Add support for multiple runtimes +- Fix panic handling inside the `interact` method +- Wrap blocking drop method of connections inside `spawn_blocking` +- Remove unused `futures`, `tokio` and `log` dependencies -* __Breaking:__ Replace `config` feature with `serde` (opted out by default) -* Add support for multiple runtimes -* Fix panic handling inside the `interact` method -* Wrap blocking drop method of connections inside `spawn_blocking` -* Remove unused `futures`, `tokio` and `log` dependencies +## [0.1.0] - 2021-05-30 -## v0.1.0 +- First release -* First release + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.8.1...HEAD +[0.8.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.8.0...deadpool-sqlite-v0.8.1 +[0.8.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.7.0...deadpool-sqlite-v0.8.0 +[0.7.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.6.0...deadpool-sqlite-v0.7.0 +[0.6.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.5.0...deadpool-sqlite-v0.6.0 +[0.5.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.4.0...deadpool-sqlite-v0.5.0 +[0.4.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.3.0...deadpool-sqlite-v0.4.0 +[0.3.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.2.0...deadpool-sqlite-v0.3.0 +[0.2.0]: https://github.com/bikeshedder/deadpool/compare/deadpool-sqlite-v0.1.0...deadpool-sqlite-v0.2.0 +[0.1.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-sqlite-v0.1.0 \ No newline at end of file diff --git a/sqlite/Cargo.toml b/sqlite/Cargo.toml index 02e2f43d..c55b107c 100644 --- a/sqlite/Cargo.toml +++ b/sqlite/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-sqlite" -version = "0.6.0" +version = "0.8.1" edition = "2021" -resolver = "2" -rust-version = "1.63" +rust-version = "1.75" authors = ["Michael P. Jung "] description = "Dead simple async pool for rusqlite" keywords = ["async", "database", "pool", "sqlite"] @@ -19,20 +18,19 @@ rustdoc-args = ["--cfg", "docsrs"] default = ["rt_tokio_1"] rt_tokio_1 = ["deadpool/rt_tokio_1"] rt_async-std_1 = ["deadpool/rt_async-std_1"] -serde = ["deadpool/serde", "serde_1"] +serde = ["deadpool/serde", "dep:serde"] tracing = ["deadpool-sync/tracing"] [dependencies] -deadpool = { path = "../", version = "0.10.0", default-features = false, features = [ +deadpool = { path = "../", version = "0.12.0", default-features = false, features = [ "managed", ] } deadpool-sync = { path = "../sync", version = "0.1.1" } -rusqlite = "0.29" -serde_1 = { package = "serde", version = "1.0", features = [ +rusqlite = "0.31" +serde = { package = "serde", version = "1.0", features = [ "derive", ], optional = true } [dev-dependencies] -config = { version = "0.13", features = ["json"] } -dotenv = "0.15" +config = { version = "0.14", features = ["json"] } tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] } diff --git a/sqlite/LICENSE-APACHE b/sqlite/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/sqlite/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/sqlite/LICENSE-MIT b/sqlite/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/sqlite/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/sqlite/README.md b/sqlite/README.md index e01ba43e..69781ecd 100644 --- a/sqlite/README.md +++ b/sqlite/README.md @@ -1,4 +1,4 @@ -# Deadpool for SQLite [![Latest Version](https://img.shields.io/crates/v/deadpool-sqlite.svg)](https://crates.io/crates/deadpool-sqlite) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for SQLite [![Latest Version](https://img.shields.io/crates/v/deadpool-sqlite.svg)](https://crates.io/crates/deadpool-sqlite) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. diff --git a/sqlite/src/config.rs b/sqlite/src/config.rs index c18bc207..af6be1e9 100644 --- a/sqlite/src/config.rs +++ b/sqlite/src/config.rs @@ -15,10 +15,7 @@ use crate::{CreatePoolError, Manager, Pool, PoolBuilder, PoolConfig, Runtime}; /// SQLITE__POOL__TIMEOUTS__WAIT__NANOS=0 /// ``` /// ```rust -/// # use serde_1 as serde; -/// # /// #[derive(serde::Deserialize, serde::Serialize)] -/// # #[serde(crate = "serde_1")] /// struct Config { /// sqlite: deadpool_sqlite::Config, /// } @@ -32,8 +29,7 @@ use crate::{CreatePoolError, Manager, Pool, PoolBuilder, PoolConfig, Runtime}; /// } /// ``` #[derive(Clone, Debug, Default)] -#[cfg_attr(feature = "serde", derive(serde_1::Deserialize, serde_1::Serialize))] -#[cfg_attr(feature = "serde", serde(crate = "serde_1"))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Config { /// Path to SQLite database file. pub path: PathBuf, diff --git a/sqlite/src/lib.rs b/sqlite/src/lib.rs index a5c1e2b9..11b0bf0e 100644 --- a/sqlite/src/lib.rs +++ b/sqlite/src/lib.rs @@ -25,10 +25,7 @@ mod config; use std::sync::atomic::{AtomicUsize, Ordering}; -use deadpool::{ - async_trait, - managed::{self, RecycleError}, -}; +use deadpool::managed::{self, RecycleError}; use deadpool_sync::SyncWrapper; pub use deadpool::managed::reexports::*; @@ -38,7 +35,7 @@ pub use rusqlite; deadpool::managed_reexports!( "rusqlite", Manager, - deadpool::managed::Object, + managed::Object, rusqlite::Error, ConfigError ); @@ -71,7 +68,6 @@ impl Manager { } } -#[async_trait] impl managed::Manager for Manager { type Type = SyncWrapper; type Error = rusqlite::Error; @@ -95,11 +91,11 @@ impl managed::Manager for Manager { let n: usize = conn .interact(move |conn| conn.query_row("SELECT $1", [recycle_count], |row| row.get(0))) .await - .map_err(|e| RecycleError::Message(format!("{}", e)))??; + .map_err(|e| RecycleError::message(format!("{}", e)))??; if n == recycle_count { Ok(()) } else { - Err(RecycleError::StaticMessage("Recycle count mismatch")) + Err(RecycleError::message("Recycle count mismatch")) } } } diff --git a/src/lib.rs b/src/lib.rs index 64202681..14a274d6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,14 +29,17 @@ pub mod managed; #[cfg_attr(docsrs, doc(cfg(feature = "unmanaged")))] pub mod unmanaged; -// For handy re-usage in integration crates. -#[cfg(feature = "managed")] -#[doc(hidden)] -pub use async_trait::async_trait; - pub use deadpool_runtime::{Runtime, SpawnBlockingError}; /// The current pool status. +/// +/// **The status returned by the pool is not guaranteed to be consistent!** +/// +/// While this features provides [eventual consistency][1] the numbers will be +/// off when accessing the status of a pool under heavy load. These numbers +/// are meant for an overall insight. +/// +/// [1]: (https://en.wikipedia.org/wiki/Eventual_consistency) #[derive(Clone, Copy, Debug)] pub struct Status { /// The maximum size of the pool. diff --git a/src/managed/config.rs b/src/managed/config.rs index 9d8627cb..c4d31f0b 100644 --- a/src/managed/config.rs +++ b/src/managed/config.rs @@ -75,14 +75,18 @@ pub struct Timeouts { impl Timeouts { /// Create an empty [`Timeouts`] config (no timeouts set). #[must_use] - pub fn new() -> Self { - Self::default() + pub const fn new() -> Self { + Self { + create: None, + wait: None, + recycle: None, + } } /// Creates a new [`Timeouts`] config with only the `wait` timeout being /// set. #[must_use] - pub fn wait_millis(wait: u64) -> Self { + pub const fn wait_millis(wait: u64) -> Self { Self { create: None, wait: Some(Duration::from_millis(wait)), @@ -95,11 +99,7 @@ impl Timeouts { impl Default for Timeouts { /// Creates an empty [`Timeouts`] config (no timeouts set). fn default() -> Self { - Self { - create: None, - wait: None, - recycle: None, - } + Self::new() } } diff --git a/src/managed/errors.rs b/src/managed/errors.rs index 1ab19e8c..d6c39f3e 100644 --- a/src/managed/errors.rs +++ b/src/managed/errors.rs @@ -1,4 +1,4 @@ -use std::fmt; +use std::{borrow::Cow, fmt}; use super::hooks::HookError; @@ -8,15 +8,20 @@ use super::hooks::HookError; #[derive(Debug)] pub enum RecycleError { /// Recycling failed for some other reason. - Message(String), - - /// Recycling failed for some other reason. - StaticMessage(&'static str), + Message(Cow<'static, str>), /// Error caused by the backend. Backend(E), } +impl RecycleError { + /// Convenience constructor function for the `HookError::Message` + /// variant. + pub fn message(msg: impl Into>) -> Self { + Self::Message(msg.into()) + } +} + impl From for RecycleError { fn from(e: E) -> Self { Self::Backend(e) @@ -27,9 +32,6 @@ impl fmt::Display for RecycleError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Message(msg) => write!(f, "Error occurred while recycling an object: {}", msg), - Self::StaticMessage(msg) => { - write!(f, "Error occurred while recycling an object: {}", msg) - } Self::Backend(e) => write!(f, "Error occurred while recycling an object: {}", e), } } @@ -39,7 +41,6 @@ impl std::error::Error for RecycleError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Self::Message(_) => None, - Self::StaticMessage(_) => None, Self::Backend(e) => Some(e), } } diff --git a/src/managed/hooks.rs b/src/managed/hooks.rs index 85d79941..6b016085 100644 --- a/src/managed/hooks.rs +++ b/src/managed/hooks.rs @@ -1,6 +1,6 @@ //! Hooks allowing to run code when creating and/or recycling objects. -use std::{fmt, future::Future, pin::Pin}; +use std::{borrow::Cow, fmt, future::Future, pin::Pin}; use super::{Manager, Metrics, ObjectInner}; @@ -65,20 +65,24 @@ impl fmt::Debug for Hook { #[derive(Debug)] pub enum HookError { /// Hook failed for some other reason. - Message(String), - - /// Hook failed for some other reason. - StaticMessage(&'static str), + Message(Cow<'static, str>), /// Error caused by the backend. Backend(E), } +impl HookError { + /// Convenience constructor function for the `HookError::Message` + /// variant. + pub fn message(msg: impl Into>) -> Self { + Self::Message(msg.into()) + } +} + impl fmt::Display for HookError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Message(msg) => write!(f, "{}", msg), - Self::StaticMessage(msg) => write!(f, "{}", msg), Self::Backend(e) => write!(f, "{}", e), } } @@ -88,7 +92,6 @@ impl std::error::Error for HookError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { Self::Message(_) => None, - Self::StaticMessage(_) => None, Self::Backend(e) => Some(e), } } diff --git a/src/managed/metrics.rs b/src/managed/metrics.rs index b2400621..fc41fd6f 100644 --- a/src/managed/metrics.rs +++ b/src/managed/metrics.rs @@ -1,11 +1,14 @@ +#[cfg(not(target_arch = "wasm32"))] use std::time::{Duration, Instant}; /// Statistics regarding an object returned by the pool #[derive(Clone, Copy, Debug)] #[must_use] pub struct Metrics { + #[cfg(not(target_arch = "wasm32"))] /// The instant when this object was created pub created: Instant, + #[cfg(not(target_arch = "wasm32"))] /// The instant when this object was last used pub recycled: Option, /// The number of times the objects was recycled @@ -13,10 +16,12 @@ pub struct Metrics { } impl Metrics { + #[cfg(not(target_arch = "wasm32"))] /// Access the age of this object pub fn age(&self) -> Duration { self.created.elapsed() } + #[cfg(not(target_arch = "wasm32"))] /// Get the time elapsed when this object was last used pub fn last_used(&self) -> Duration { self.recycled.unwrap_or(self.created).elapsed() @@ -26,7 +31,9 @@ impl Metrics { impl Default for Metrics { fn default() -> Self { Self { + #[cfg(not(target_arch = "wasm32"))] created: Instant::now(), + #[cfg(not(target_arch = "wasm32"))] recycled: None, recycle_count: 0, } diff --git a/src/managed/mod.rs b/src/managed/mod.rs index 6a561002..3c35ade7 100644 --- a/src/managed/mod.rs +++ b/src/managed/mod.rs @@ -6,7 +6,6 @@ //! # Example //! //! ```rust -//! use async_trait::async_trait; //! use deadpool::managed; //! //! #[derive(Debug)] @@ -22,7 +21,6 @@ //! //! struct Manager {} //! -//! #[async_trait] //! impl managed::Manager for Manager { //! type Type = Computer; //! type Error = Error; @@ -68,10 +66,12 @@ use std::{ atomic::{AtomicUsize, Ordering}, Arc, Mutex, Weak, }, - time::{Duration, Instant}, + time::Duration, }; -use async_trait::async_trait; +#[cfg(not(target_arch = "wasm32"))] +use std::time::Instant; + use deadpool_runtime::Runtime; use tokio::sync::{Semaphore, TryAcquireError}; @@ -90,23 +90,26 @@ pub use self::{ pub type RecycleResult = Result<(), RecycleError>; /// Manager responsible for creating new [`Object`]s or recycling existing ones. -#[async_trait] pub trait Manager: Sync + Send { /// Type of [`Object`]s that this [`Manager`] creates and recycles. - type Type; + type Type: Send; /// Error that this [`Manager`] can return when creating and/or recycling /// [`Object`]s. - type Error; + type Error: Send; /// Creates a new instance of [`Manager::Type`]. - async fn create(&self) -> Result; + fn create(&self) -> impl Future> + Send; /// Tries to recycle an instance of [`Manager::Type`]. /// /// # Errors /// /// Returns [`Manager::Error`] if the instance couldn't be recycled. - async fn recycle(&self, obj: &mut Self::Type, metrics: &Metrics) -> RecycleResult; + fn recycle( + &self, + obj: &mut Self::Type, + metrics: &Metrics, + ) -> impl Future> + Send; /// Detaches an instance of [`Manager::Type`] from this [`Manager`]. /// @@ -409,7 +412,10 @@ impl>> Pool { } inner.metrics.recycle_count += 1; - inner.metrics.recycled = Some(Instant::now()); + #[cfg(not(target_arch = "wasm32"))] + { + inner.metrics.recycled = Some(Instant::now()); + } Ok(Some(unready_obj.ready())) } diff --git a/sync/CHANGELOG.md b/sync/CHANGELOG.md index b97e46c8..e728c4b9 100644 --- a/sync/CHANGELOG.md +++ b/sync/CHANGELOG.md @@ -1,14 +1,41 @@ -## v0.1.2 +# Changelog -* Add `tracing` feature to `README` -* Fix MSRV (this was the reason for yanking the `0.1.1` release) and bump it up to `1.63` to match the one of `tokio` +All notable changes to this project will be documented in this file. -## v0.1.1 (yanked) +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -* Replace `deadpool` dependency by `deadpool-runtime`. This is a + + +## [Unreleased] + +## [0.1.4] - 2024-06-04 + +- Fix `panic` when dropping a `SyncWrapper` while it is still executing the `interact` method. + +## [0.1.3] - 2024-05-24 + +- Add `LICENSE-APACHE` and `LICENSE-MIT` files to published crates + +## [0.1.2] - 2023-09-26 + +- Add `tracing` feature to `README` +- Fix MSRV (this was the reason for yanking the `0.1.1` release) and bump it up to `1.63` to match the one of `tokio` + +## [0.1.1] - 2023-09-06 (yanked) + +- Replace `deadpool` dependency by `deadpool-runtime`. This is a non-breaking change as the `Runtime` and `SpawnBlockingError` types were a re-export from `deadpool-runtime` anyways. -## v0.1.0 +## [0.1.0] - 2021-10-26 + +- First release -* First release + +[Unreleased]: https://github.com/bikeshedder/deadpool/compare/deadpool-sync-v0.1.4...HEAD +[0.1.4]: https://github.com/bikeshedder/deadpool/compare/deadpool-sync-v0.1.3...deadpool-sync-v0.1.4 +[0.1.3]: https://github.com/bikeshedder/deadpool/compare/deadpool-sync-v0.1.2...deadpool-sync-v0.1.3 +[0.1.2]: https://github.com/bikeshedder/deadpool/compare/deadpool-sync-v0.1.1...deadpool-sync-v0.1.2 +[0.1.1]: https://github.com/bikeshedder/deadpool/compare/deadpool-sync-v0.1.0...deadpool-sync-v0.1.1 +[0.1.0]: https://github.com/bikeshedder/deadpool/releases/tag/deadpool-sync-v0.1.0 \ No newline at end of file diff --git a/sync/Cargo.toml b/sync/Cargo.toml index 0ddf6198..f1d1cbf7 100644 --- a/sync/Cargo.toml +++ b/sync/Cargo.toml @@ -1,9 +1,8 @@ [package] name = "deadpool-sync" -version = "0.1.2" -edition = "2018" -resolver = "2" -rust-version = "1.63" +version = "0.1.4" +edition = "2021" +rust-version = "1.75" authors = ["Michael P. Jung "] description = "Dead simple async pool utitities for sync managers" keywords = ["async", "database", "pool", "sync", "utils"] @@ -16,3 +15,7 @@ readme = "README.md" [dependencies] deadpool-runtime = { version = "0.1.2", path = "../runtime" } tracing = { version = "0.1", optional = true } + +[dev-dependencies] +deadpool = { version = "0.12", path = "..", features = ["rt_tokio_1"] } +tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] } diff --git a/sync/LICENSE-APACHE b/sync/LICENSE-APACHE new file mode 120000 index 00000000..965b606f --- /dev/null +++ b/sync/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/sync/LICENSE-MIT b/sync/LICENSE-MIT new file mode 120000 index 00000000..76219eb7 --- /dev/null +++ b/sync/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/sync/README.md b/sync/README.md index ee63c0d0..6b740b5c 100644 --- a/sync/README.md +++ b/sync/README.md @@ -1,4 +1,4 @@ -# Deadpool for synchroneous code [![Latest Version](https://img.shields.io/crates/v/deadpool-sync.svg)](https://crates.io/crates/deadpool-sync) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.63+](https://img.shields.io/badge/rustc-1.63+-lightgray.svg "Rust 1.63+")](https://blog.rust-lang.org/2022/08/11/Rust-1.63.0.html) +# Deadpool for synchroneous code [![Latest Version](https://img.shields.io/crates/v/deadpool-sync.svg)](https://crates.io/crates/deadpool-sync) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.75+](https://img.shields.io/badge/rustc-1.75+-lightgray.svg "Rust 1.75+")](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. diff --git a/sync/src/lib.rs b/sync/src/lib.rs index aaa60cce..b6a68313 100644 --- a/sync/src/lib.rs +++ b/sync/src/lib.rs @@ -37,7 +37,9 @@ pub enum InteractError { /// Provided callback has panicked. Panic(Box), - /// Callback was aborted. + /// Callback was aborted. This variant needs to exist for technical + /// reasons but you should never actually be able to get this as a + /// return value when calling `SyncWrapper::interact`. Aborted, } @@ -119,13 +121,13 @@ where self.runtime .spawn_blocking(move || { let mut guard = arc.lock().unwrap(); - let conn = guard.as_mut().unwrap(); + let conn: &mut T = guard.as_mut().ok_or(InteractError::Aborted)?; #[cfg(feature = "tracing")] let _span = span.enter(); - f(conn) + Ok(f(conn)) }) .await - .map_err(|SpawnBlockingError::Panic(p)| InteractError::Panic(p)) + .map_err(|SpawnBlockingError::Panic(p)| InteractError::Panic(p))? } /// Indicates whether the underlying [`Mutex`] has been poisoned. diff --git a/sync/tests/sync.rs b/sync/tests/sync.rs index b5a2c7b2..b3b1f58e 100644 --- a/sync/tests/sync.rs +++ b/sync/tests/sync.rs @@ -1,8 +1,4 @@ -#![cfg(feature = "managed")] - -use async_trait::async_trait; - -use deadpool::{Manager, Pool, RecycleResult}; +use deadpool::managed::{Manager, Metrics, Pool, RecycleResult}; use deadpool_runtime::Runtime; use deadpool_sync::SyncWrapper; @@ -12,7 +8,6 @@ struct Computer { struct ComputerManager {} -#[async_trait] impl Manager for ComputerManager { type Type = SyncWrapper; type Error = (); @@ -21,7 +16,11 @@ impl Manager for ComputerManager { SyncWrapper::new(Runtime::Tokio1, || Ok(Computer { answer: 42 })).await } - async fn recycle(&self, _: &mut Self::Type) -> RecycleResult { + async fn recycle( + &self, + _obj: &mut Self::Type, + _metrics: &Metrics, + ) -> RecycleResult { Ok(()) } } diff --git a/test-build.sh b/test-build.sh index bc1b0978..5cf9b71e 100755 --- a/test-build.sh +++ b/test-build.sh @@ -24,13 +24,8 @@ cargo build --no-default-features --features managed,unmanaged cargo build cargo build --no-default-features --features rt_tokio_1 cargo build --no-default-features --features rt_async-std_1 -) - -( - cd redis-cluster - cargo build - cargo build --no-default-features --features rt_tokio_1 - cargo build --no-default-features --features rt_async-std_1 + cargo build --no-default-features --features rt_tokio_1 cluster + cargo build --no-default-features --features rt_async-std_1 cluster ) ( diff --git a/tests/managed.rs b/tests/managed.rs index 1f20f49d..adf86132 100644 --- a/tests/managed.rs +++ b/tests/managed.rs @@ -2,7 +2,6 @@ use std::{convert::Infallible, time::Duration}; -use async_trait::async_trait; use tokio::time; use deadpool::managed::{self, Metrics, Object, PoolError, RecycleResult, Timeouts}; @@ -11,7 +10,6 @@ type Pool = managed::Pool; struct Manager {} -#[async_trait] impl managed::Manager for Manager { type Type = usize; type Error = Infallible; diff --git a/tests/managed_cancellation.rs b/tests/managed_cancellation.rs index 2f6bfa84..63a57d6f 100644 --- a/tests/managed_cancellation.rs +++ b/tests/managed_cancellation.rs @@ -1,6 +1,5 @@ use std::time::Duration; -use async_trait::async_trait; use deadpool::managed::{Hook, HookError, Manager, Metrics, Pool, RecycleResult}; use itertools::Itertools; use tokio::time::{sleep, timeout}; @@ -63,7 +62,7 @@ fn pools(max_size: usize) -> impl Iterator> { .post_create .open() .await - .map_err(|_| HookError::StaticMessage("Fail"))?; + .map_err(|_| HookError::message("Fail"))?; Ok(()) }) })) @@ -73,7 +72,7 @@ fn pools(max_size: usize) -> impl Iterator> { .pre_recycle .open() .await - .map_err(|_| HookError::StaticMessage("pre_recycle gate set to error"))?; + .map_err(|_| HookError::message("pre_recycle gate set to error"))?; Ok(()) }) })) @@ -83,7 +82,7 @@ fn pools(max_size: usize) -> impl Iterator> { .post_recycle .open() .await - .map_err(|_| HookError::StaticMessage("post_recycle gate set to error"))?; + .map_err(|_| HookError::message("post_recycle gate set to error"))?; Ok(()) }) })) @@ -96,7 +95,6 @@ struct GatedManager { gates: Gates, } -#[async_trait] impl Manager for GatedManager { type Type = (); type Error = (); diff --git a/tests/managed_deadlock.rs b/tests/managed_deadlock.rs index 7a592af4..b683e8be 100644 --- a/tests/managed_deadlock.rs +++ b/tests/managed_deadlock.rs @@ -2,7 +2,6 @@ use std::{sync::Arc, time::Duration}; -use async_trait::async_trait; use tokio::{ sync::{mpsc, Mutex}, task, time, @@ -57,7 +56,6 @@ impl Manager { } } -#[async_trait] impl managed::Manager for Manager { type Type = (); type Error = (); diff --git a/tests/managed_hooks.rs b/tests/managed_hooks.rs index 00a27b29..4948a45a 100644 --- a/tests/managed_hooks.rs +++ b/tests/managed_hooks.rs @@ -2,8 +2,6 @@ use std::sync::atomic::{AtomicUsize, Ordering}; -use async_trait::async_trait; - use deadpool::managed::{Hook, HookError, Manager, Metrics, Pool, RecycleResult}; struct Computer { @@ -18,7 +16,6 @@ impl Computer { } } -#[async_trait] impl Manager for Computer { type Type = usize; type Error = (); @@ -70,7 +67,7 @@ async fn post_create_err_abort() { .post_create(Hook::sync_fn(|obj, _| { (*obj % 2 == 0) .then_some(()) - .ok_or(HookError::StaticMessage("odd creation")) + .ok_or(HookError::message("odd creation")) })) .build() .unwrap(); @@ -108,7 +105,7 @@ async fn pre_recycle_err_continue() { .max_size(1) .pre_recycle(Hook::sync_fn(|_, metrics| { if metrics.recycle_count > 0 { - Err(HookError::StaticMessage("Fail!")) + Err(HookError::message("Fail!")) } else { Ok(()) } @@ -159,7 +156,7 @@ async fn post_recycle_err_continue() { .max_size(1) .post_recycle(Hook::sync_fn(|_, metrics| { if metrics.recycle_count > 0 { - Err(HookError::StaticMessage("Fail!")) + Err(HookError::message("Fail!")) } else { Ok(()) } diff --git a/tests/managed_timeout.rs b/tests/managed_timeout.rs index a043ebf0..8d2acdd6 100644 --- a/tests/managed_timeout.rs +++ b/tests/managed_timeout.rs @@ -5,8 +5,6 @@ use std::{convert::Infallible, future::Future, pin::Pin, task, time::Duration}; -use async_trait::async_trait; - use deadpool::{ managed::{self, Metrics, Object, PoolConfig, PoolError, RecycleResult, Timeouts}, Runtime, @@ -26,7 +24,6 @@ impl Future for Never { } } -#[async_trait] impl managed::Manager for Manager { type Type = usize; type Error = Infallible; diff --git a/tests/managed_unreliable_manager.rs b/tests/managed_unreliable_manager.rs index ec31e338..dba5eb77 100644 --- a/tests/managed_unreliable_manager.rs +++ b/tests/managed_unreliable_manager.rs @@ -5,7 +5,6 @@ use std::{ time::Duration, }; -use async_trait::async_trait; use tokio::time; use deadpool::managed::{self, Metrics, RecycleError, RecycleResult}; @@ -18,7 +17,6 @@ struct Manager { detached: AtomicUsize, } -#[async_trait] impl managed::Manager for Manager { type Type = (); type Error = ();