Skip to content

Commit 87d3e74

Browse files
Merge pull request #168 from sanua356/pooling-example
#166 Diesel connection pooling example
2 parents fe08917 + dc3ce46 commit 87d3e74

File tree

7 files changed

+170
-0
lines changed

7 files changed

+170
-0
lines changed

r2d2_firebird/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,12 @@ rsfbclient = { version = "0.25.2", path = "../", default-features = false }
1717
rsfbclient-core = { version = "0.25.2", path = "../rsfbclient-core" }
1818
r2d2 = "0.8.9"
1919

20+
diesel = { version = "2.0.0", optional = true }
21+
rsfbclient-diesel = { version = "0.25.1", path = "../rsfbclient-diesel", optional = true }
22+
23+
[features]
24+
default=[]
25+
diesel_pool=["diesel", "rsfbclient-diesel"]
26+
2027
[dev-dependencies]
2128
rsfbclient = { version = "0.25.2", path = "../", features = ["pure_rust"], default-features = false }

r2d2_firebird/src/lib.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,48 @@ where
4747
false
4848
}
4949
}
50+
51+
// Implementation for Diesel
52+
#[cfg(feature = "diesel_pool")]
53+
mod diesel_manager {
54+
use diesel::prelude::*;
55+
use diesel::{sql_query, Connection, ConnectionError};
56+
use rsfbclient_diesel::FbConnection;
57+
58+
pub struct DieselConnectionManager {
59+
connection_string: String,
60+
}
61+
62+
impl DieselConnectionManager {
63+
pub fn new(database_url: &str) -> Self {
64+
Self {
65+
connection_string: database_url.to_string(),
66+
}
67+
}
68+
}
69+
70+
impl r2d2::ManageConnection for DieselConnectionManager {
71+
type Connection = FbConnection;
72+
type Error = ConnectionError;
73+
74+
fn connect(&self) -> Result<Self::Connection, Self::Error> {
75+
FbConnection::establish(&self.connection_string)
76+
}
77+
78+
fn is_valid(&self, conn: &mut Self::Connection) -> Result<(), Self::Error> {
79+
sql_query("SELECT 1 FROM RDB$DATABASE")
80+
.execute(conn)
81+
.map(|_| ())
82+
.map_err(|_| {
83+
ConnectionError::BadConnection("Diesel pooled connection check failed.".into())
84+
})
85+
}
86+
87+
fn has_broken(&self, _conn: &mut Self::Connection) -> bool {
88+
false
89+
}
90+
}
91+
}
92+
93+
#[cfg(feature = "diesel_pool")]
94+
pub use diesel_manager::DieselConnectionManager;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Generated by Cargo
2+
# will have compiled files and executables
3+
/target/
4+
lcov.info
5+
6+
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
7+
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
8+
Cargo.lock
9+
10+
# These are backup files generated by rustfmt
11+
**/*.rs.bk
12+
13+
tests/use
14+
15+
# firebird lib
16+
fbclient.lib
17+
18+
# vscode conf folder
19+
.vscode
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "employee-pool"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
8+
[dependencies]
9+
diesel = "2.0.0"
10+
rsfbclient-diesel = "0.25.0"
11+
r2d2 = "0.8.10"
12+
rsfbclient = "0.25.2"
13+
r2d2_firebird = {version="0.25.2", path="../../../r2d2_firebird", features=["diesel_pool"]}
14+
rsfbclient-core = "0.25.2"
15+
16+
[workspace]
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
# Diesel with connection pooling example.
3+
4+
This example use the `employee.fdb` database, present in your Firebird instalation. You also can get this database in `examples/empbuild` folder from the [official instalation files](https://firebirdsql.org/en/firebird-4-0/)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use diesel::{QueryDsl, RunQueryDsl};
2+
use r2d2::Pool;
3+
use r2d2_firebird::DieselConnectionManager;
4+
use std::{env, sync::Arc, thread, time::Duration};
5+
6+
use schema::{job::dsl::*, Job};
7+
8+
mod schema;
9+
10+
fn main() {
11+
12+
let connecton_string = env::var("DIESELFDB_CONN").expect("DIESELFDB_CONN env not found");
13+
14+
let manager = DieselConnectionManager::new(&connecton_string);
15+
let pool = Arc::new(
16+
Pool::builder()
17+
.max_size(4)
18+
.build(manager)
19+
.expect("Failed to build connection pooling."),
20+
);
21+
22+
let mut tasks = vec![];
23+
24+
for n in 0..3 {
25+
let pool = pool.clone();
26+
let th = thread::spawn(move || loop {
27+
28+
match pool.get() {
29+
Ok(mut conn) => match job.offset(n).limit(1).first::<Job>(&mut *conn) {
30+
Ok(model) => {
31+
println!("Thread {}: {}", n, model.title)
32+
}
33+
34+
Err(e) => println!("Execute query error in line:{} ! error: {:?}", line!(), e),
35+
},
36+
Err(e) => println!(
37+
"Get connection from pool error in line:{} ! error: {:?}",
38+
line!(),
39+
e
40+
),
41+
}
42+
43+
thread::sleep(Duration::from_secs(1));
44+
});
45+
tasks.push(th);
46+
}
47+
48+
for th in tasks {
49+
let _ = th.join();
50+
}
51+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
use diesel::{ Queryable };
2+
3+
#[allow(dead_code)]
4+
#[derive(Queryable)]
5+
#[diesel(table_name = job)]
6+
pub struct Job {
7+
#[diesel(column_name = job_code)]
8+
pub code: String,
9+
#[diesel(column_name = job_title)]
10+
pub title: String,
11+
#[diesel(column_name = job_country)]
12+
pub country: String,
13+
#[diesel(column_name = job_grade)]
14+
pub grade: i16,
15+
pub min_salary: f32,
16+
pub max_salary: f32,
17+
}
18+
19+
diesel::table! {
20+
job(job_code) {
21+
job_code -> Text,
22+
job_title -> Text,
23+
job_country -> Text,
24+
job_grade -> Smallint,
25+
min_salary -> Float,
26+
max_salary -> Float,
27+
}
28+
}

0 commit comments

Comments
 (0)