Skip to content

Commit 4da497d

Browse files
Weasy666bikeshedder
authored andcommitted
Add deadpool-arangodb
1 parent c14c7ad commit 4da497d

9 files changed

Lines changed: 464 additions & 3 deletions

File tree

.github/workflows/ci.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ jobs:
8989
fail-fast: false
9090
matrix:
9191
crate:
92+
- arangodb
9293
- diesel
9394
- lapin
9495
- postgres
@@ -136,6 +137,7 @@ jobs:
136137
# `nom = 6.0.0`. Try re-enable it on next `lapin` major version
137138
# upgrade.
138139
#- { crate: deadpool-lapin, msrv: '1.54.0' }
140+
- { crate: deadpool-arangodb, msrv: '1.54.0' }
139141
- { crate: deadpool-postgres, msrv: '1.54.0' }
140142
- { crate: deadpool-redis, msrv: '1.54.0' }
141143
- { crate: deadpool-sqlite, msrv: '1.54.0' }
@@ -165,13 +167,21 @@ jobs:
165167
matrix:
166168
crate:
167169
- deadpool
170+
- deadpool-arangodb
168171
- deadpool-diesel
169172
- deadpool-lapin
170173
- deadpool-postgres
171174
- deadpool-redis
172175
- deadpool-sqlite
173176
runs-on: ubuntu-latest
174177
services:
178+
arangodb:
179+
image: arangodb
180+
ports:
181+
- 8529:8529
182+
env:
183+
ARANGO_ROOT_PASSWORD: deadpool
184+
ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY: 500M
175185
postgres:
176186
image: postgres
177187
ports:
@@ -207,6 +217,10 @@ jobs:
207217

208218
- run: cargo test -p ${{ matrix.crate }} --all-features
209219
env:
220+
ARANGODB__URL: http://127.0.0.1:8529
221+
ARANGODB__USERNAME: root
222+
ARANGODB__PASSWORD: deadpool
223+
ARANGODB__USE_JWT: "true"
210224
PG__HOST: 127.0.0.1
211225
PG__PORT: 5432
212226
PG__USER: deadpool
@@ -231,6 +245,7 @@ jobs:
231245
matrix:
232246
crate:
233247
- deadpool
248+
- deadpool-arangodb
234249
- deadpool-diesel
235250
- deadpool-lapin
236251
- deadpool-postgres

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ harness = false
4646

4747
[workspace]
4848
members = [
49+
"arangodb",
4950
"diesel",
5051
"lapin",
5152
"postgres",

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,11 +61,11 @@ struct Manager {}
6161
impl managed::Manager for Manager {
6262
type Type = Computer;
6363
type Error = Error;
64-
64+
6565
async fn create(&self) -> Result<Computer, Error> {
6666
Ok(Computer {})
6767
}
68-
68+
6969
async fn recycle(&self, _: &mut Computer) -> managed::RecycleResult<Error> {
7070
Ok(())
7171
}
@@ -98,6 +98,7 @@ Backend | Crate | Latest Version |
9898
[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) |
9999
[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) |
100100
[r2d2](https://crates.io/crates/r2d2) | [deadpool-r2d2](https://crates.io/crates/deadpool-r2d2) | [![Latest Version](https://img.shields.io/crates/v/deadpool-r2d2.svg)](https://crates.io/crates/deadpool-r2d2) |
101+
[arangors](https://crates.io/crates/arangors) | [deadpool-arangodb](https://crates.io/crates/deadpool-arangodb) | [![Latest Version](https://img.shields.io/crates/v/deadpool-arangodb.svg)](https://crates.io/crates/deadpool-arangodb) |
101102

102103
### Reasons for yet another connection pool
103104

arangodb/Cargo.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "deadpool-arangodb"
3+
version = "0.1.0-pre"
4+
edition = "2018"
5+
resolver = "2"
6+
authors = ["Daniel Wiesenberg <weasy@hotmail.de>"]
7+
description = "Dead simple async pool for ArangoDB"
8+
keywords = ["async", "database", "pool", "arango", "arangodb"]
9+
license = "MIT/Apache-2.0"
10+
repository = "https://github.com/bikeshedder/deadpool/arangodb"
11+
readme = "README.md"
12+
13+
[package.metadata.docs.rs]
14+
all-features = true
15+
16+
[features]
17+
default = ["rt_tokio_1"]
18+
rt_tokio_1 = ["deadpool/rt_tokio_1", "arangors/reqwest_async"]
19+
rt_async-std_1 = ["deadpool/rt_async-std_1", "arangors/surf_async"]
20+
serde = ["deadpool/serde", "serde_1"]
21+
22+
[dependencies]
23+
deadpool = { path = "../", version = "0.9.0-pre", default-features = false, features = ["managed"] }
24+
arangors = { git = "https://github.com/fMeow/arangors", rev = "2c31587", default-features = false, features = ["rocksdb"] }
25+
serde_1 = { package = "serde", version = "1.0", features = ["derive"], optional = true }
26+
url = "2.2"
27+
28+
[dev-dependencies]
29+
config = { version = "0.11", default-features = false }
30+
dotenv = "0.15.0"
31+
futures = "0.3"
32+
tokio = { version = "1.0", features = ["macros", "rt-multi-thread"] }

arangodb/README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Deadpool for ArangoDB [![Latest Version](https://img.shields.io/crates/v/deadpool-arangodb.svg)](https://crates.io/crates/deadpool-arangodb) ![Unsafe forbidden](https://img.shields.io/badge/unsafe-forbidden-success.svg "Unsafe forbidden") [![Rust 1.54+](https://img.shields.io/badge/rustc-1.54+-lightgray.svg "Rust 1.54+")](https://blog.rust-lang.org/2021/07/29/Rust-1.54.0.html)
2+
3+
Deadpool is a dead simple async pool for connections and objects
4+
of any type.
5+
6+
This crate implements a [`deadpool`](https://crates.io/crates/deadpool)
7+
manager for [`ArangoDB`](https://www.arangodb.com/) using [`arangors`](https://crates.io/crates/arangors).
8+
9+
## Features
10+
11+
| Feature | Description | Extra dependencies | Default |
12+
| ------- | ----------- | ------------------ | ------- |
13+
| `rt_tokio_1` | Enable support for [tokio](https://crates.io/crates/tokio) crate,<br>through the usage of [reqwest](https://crates.io/crates/reqwest) as http client | `deadpool/rt_tokio_1`, `arangors/reqwest_async` | yes |
14+
| `rt_async-std_1` | Enable support for [async-std](https://crates.io/crates/config) crate,<br>through the usage of [surf](https://crates.io/crates/surf) as http client | `deadpool/rt_async-std_1`, `arangors/surf_async` | no |
15+
| `serde` | Enable support for [serde](https://crates.io/crates/serde) crate | `deadpool/serde`, `serde/derive` | no |
16+
17+
## Example
18+
19+
```rust
20+
use deadpool_arangodb::{Config, Runtime};
21+
22+
#[tokio::main]
23+
async fn main() {
24+
let mut cfg = Config {
25+
url: Some("http://localhost:8529".to_string()),
26+
username: Some("root".to_string()),
27+
password: Some("deadpool".to_string()),
28+
use_jwt: true,
29+
pool: None,
30+
};
31+
let pool = cfg.create_pool(Runtime::Tokio1).unwrap();
32+
let mut conn = pool.get().await.unwrap();
33+
34+
let db = conn.create_database("deadpool_favorite_foods")
35+
.await.expect("Failed to create database: {:?}");
36+
37+
// Do stuff with db...
38+
}
39+
```
40+
41+
## License
42+
43+
Licensed under either of
44+
45+
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
46+
- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
47+
48+
at your option.

arangodb/src/config.rs

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
use deadpool::{managed::BuildError, Runtime};
2+
#[cfg(feature = "serde")]
3+
use serde_1::Deserialize;
4+
use url::Url;
5+
6+
use crate::{Pool, PoolConfig};
7+
8+
/// Configuration object.
9+
///
10+
/// # Example (from environment)
11+
///
12+
/// By enabling the `serde` feature you can read the configuration using the
13+
/// [`config`](https://crates.io/crates/config) crate as following:
14+
/// ```env
15+
/// ARANGODB__URL=arangodb.example.com
16+
/// ARANGODB__USERNAME=root
17+
/// ARANGODB__PASSWORD=deadpool
18+
/// ARANGODB__USE_JWT=true
19+
/// ARANGODB__POOL__MAX_SIZE=16
20+
/// ARANGODB__POOL__TIMEOUTS__WAIT__SECS=2
21+
/// ARANGODB__POOL__TIMEOUTS__WAIT__NANOS=0
22+
/// ```
23+
/// ```rust
24+
/// # use serde_1 as serde;
25+
/// #
26+
/// #[derive(serde::Deserialize)]
27+
/// # #[serde(crate = "serde_1")]
28+
/// struct Config {
29+
/// arango: deadpool_arangodb::Config,
30+
/// }
31+
///
32+
/// impl Config {
33+
/// pub fn from_env() -> Result<Self, config::ConfigError> {
34+
/// let mut cfg = config::Config::new();
35+
/// cfg.merge(config::Environment::new().separator("__")).unwrap();
36+
/// cfg.try_into()
37+
/// }
38+
/// }
39+
/// ```
40+
#[derive(Clone, Debug)]
41+
#[cfg_attr(feature = "serde", derive(serde_1::Deserialize))]
42+
#[cfg_attr(feature = "serde", serde(crate = "serde_1"))]
43+
pub struct Config {
44+
/// ArangoDB URL.
45+
///
46+
/// See [Arangors Connection](arangors/connection/struct.GenericConnection.html#method.establish_jwt).
47+
pub url: Option<String>,
48+
/// ArangoDB username.
49+
/// If you have not manually created a new user on a ArangoDB instance, then this must be `root`.
50+
///
51+
/// See [Arangors Connection](arangors/connection/struct.GenericConnection.html#method.establish_jwt).
52+
pub username: Option<String>,
53+
/// ArangoDB password.
54+
///
55+
/// See [Arangors Connection](arangors/connection/struct.GenericConnection.html#method.establish_jwt).
56+
pub password: Option<String>,
57+
/// If jwt authentication should be used. JWT token expires after 1 month.
58+
///
59+
/// See [Arangors Connection](arangors/connection/struct.GenericConnection.html#method.establish_jwt).
60+
pub use_jwt: bool,
61+
62+
/// [`Pool`] configuration.
63+
pub pool: Option<PoolConfig>,
64+
}
65+
66+
impl Config {
67+
/// Creates a new [`Config`] from the given URL.
68+
///
69+
/// Url format is: `http://username:password@localhost:8529/?use_jwt=true`. If `use_jwt` is missing, then it defaults to `true`.
70+
pub fn from_url<U: Into<String>>(url: U) -> Result<Self, BuildError<()>> {
71+
let url = url.into();
72+
let url = Url::parse(&url)
73+
.map_err(|e| BuildError::Config(format!("Could not extract a valid config from url: `{}` - Error: {}", url, e)))?;
74+
75+
let use_jwt = url.query_pairs()
76+
.filter(|(name, _)| name == "use_jwt")
77+
.map(|(_, value)| value.to_string())
78+
.next();
79+
let use_jwt = match use_jwt {
80+
Some(use_jwt) => use_jwt.parse()
81+
.map_err(|e| BuildError::Config(format!("Could not parse `use_jwt` value: `{}` - Error: {}", use_jwt, e)))?,
82+
None => true,
83+
};
84+
85+
Ok(Config {
86+
url: Some(format!("{}://{}:{}", url.scheme(), url.host_str().unwrap(), url.port_or_known_default().unwrap())),
87+
username: Some(url.username().to_string()),
88+
password: url.password().map(ToString::to_string),
89+
use_jwt,
90+
pool: None,
91+
})
92+
}
93+
94+
95+
/// Creates a new [`Pool`] using this [`Config`].
96+
///
97+
/// # Errors
98+
///
99+
/// See [`BuildError`] and [`ClientError`] for details.
100+
///
101+
/// [`ClientError`]: arangors::ClientError
102+
pub fn create_pool(&self, runtime: Runtime) -> Result<Pool, BuildError<arangors::ClientError>> {
103+
let manager = match (&self.url, &self.username, &self.password) {
104+
(Some(_), Some(_), Some(_)) => crate::Manager::from_config(self.clone())?,
105+
_ => {
106+
return Err(BuildError::Config("url, username and password must be specified.".into()))
107+
}
108+
};
109+
110+
let pool_config = self.get_pool_config();
111+
Pool::builder(manager)
112+
.config(pool_config)
113+
.runtime(runtime)
114+
.build()
115+
}
116+
117+
/// Returns [`deadpool::managed::PoolConfig`] which can be used to construct
118+
/// a [`deadpool::managed::Pool`] instance.
119+
#[must_use]
120+
pub fn get_pool_config(&self) -> PoolConfig {
121+
self.pool.unwrap_or_default()
122+
}
123+
}
124+
125+
impl Default for Config {
126+
fn default() -> Self {
127+
Self {
128+
url: None,
129+
username: None,
130+
password: None,
131+
use_jwt: true,
132+
pool: None,
133+
}
134+
}
135+
}

0 commit comments

Comments
 (0)