Skip to content

Commit

Permalink
added async tutorial
Browse files Browse the repository at this point in the history
  • Loading branch information
yasamoka committed Mar 23, 2024
1 parent 29d0a03 commit a7aa711
Show file tree
Hide file tree
Showing 21 changed files with 597 additions and 4 deletions.
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"rust-analyzer.cargo.features": "all",
"rust-analyzer.check.command": "clippy"
"rust-analyzer.check.command": "clippy",
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
"./book/Cargo.toml"
]
}
5 changes: 5 additions & 0 deletions book/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

41 changes: 40 additions & 1 deletion book/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ edition = "2021"
[dev-dependencies]
bb8 = "0.8.3"
bb8-postgres = "0.8.1"
db-pool = { path = "..", package = "db-pool", features = ["diesel-postgres"] }
db-pool = { path = "..", package = "db-pool", features = [
"diesel-postgres",
"diesel-async-postgres",
"diesel-async-bb8",
] }
diesel = { version = "2.1.4", features = ["mysql", "postgres", "r2d2"] }
diesel-async = { version = "0.4.1", features = ["bb8", "mysql", "postgres"] }
dotenvy = "0.15.7"
Expand Down Expand Up @@ -54,3 +58,38 @@ test = true
name = "sync_tutorial_07"
path = "src/tutorials/sync/07.rs"
test = true

[[example]]
name = "async_tutorial_01"
path = "src/tutorials/async/01.rs"
test = true

[[example]]
name = "async_tutorial_02"
path = "src/tutorials/async/02.rs"
test = true

[[example]]
name = "async_tutorial_03"
path = "src/tutorials/async/03.rs"
test = true

[[example]]
name = "async_tutorial_04"
path = "src/tutorials/async/04.rs"
test = true

[[example]]
name = "async_tutorial_05"
path = "src/tutorials/async/05.rs"
test = true

[[example]]
name = "async_tutorial_06"
path = "src/tutorials/async/06.rs"
test = true

[[example]]
name = "async_tutorial_07"
path = "src/tutorials/async/07.rs"
test = true
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@
# Tutorials

- [Sync](tutorials/sync/index.md)
- [Async](tutorials/async/index.md)
4 changes: 4 additions & 0 deletions book/src/tutorials/async/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export POSTGRES_USERNAME=postgres
export POSTGRES_PASSWORD=postgres
export POSTGRES_HOST=localhost
export POSTGRES_PORT=3306
14 changes: 14 additions & 0 deletions book/src/tutorials/async/01.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
fn main() {}

#[cfg(test)]
mod tests {
#![allow(dead_code)]

// import OnceCell
use tokio::sync::OnceCell;

async fn get_connection_pool() {
// add "lazy static"
static POOL: OnceCell<()> = OnceCell::const_new();
}
}
26 changes: 26 additions & 0 deletions book/src/tutorials/async/02.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
fn main() {}

#[cfg(test)]
mod tests {
#![allow(dead_code, unused_variables)]

// import privileged configuration
use db_pool::PrivilegedPostgresConfig;
// import dotenvy
use dotenvy::dotenv;
use tokio::sync::OnceCell;

async fn get_connection_pool() {
static POOL: OnceCell<()> = OnceCell::const_new();

let db_pool = POOL
.get_or_init(|| async {
// load environment variables from .env
dotenv().ok();

// create privileged configuration from environment variables
let config = PrivilegedPostgresConfig::from_env().unwrap();
})
.await;
}
}
54 changes: 54 additions & 0 deletions book/src/tutorials/async/03.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
fn main() {}

#[cfg(test)]
mod tests {
#![allow(dead_code, unused_variables)]

use db_pool::{
// import backend
r#async::{DieselAsyncPgBackend, DieselBb8},
PrivilegedPostgresConfig,
};
// import diesel-specific constructs
use diesel::sql_query;
use diesel_async::RunQueryDsl;
use dotenvy::dotenv;
// import connection pool
use bb8::Pool;
use tokio::sync::OnceCell;

async fn get_connection_pool() {
static POOL: OnceCell<()> = OnceCell::const_new();
let db_pool = POOL
.get_or_init(|| async {
dotenv().ok();

let config = PrivilegedPostgresConfig::from_env().unwrap();

// create backend for BB8 connection pools
let backend = DieselAsyncPgBackend::<DieselBb8>::new(
config,
// create privileged connection pool with max 10 connections
|| Pool::builder().max_size(10),
// create restricted connection pool with max 2 connections
|| Pool::builder().max_size(2),
// create entities
move |mut conn| {
Box::pin(async {
sql_query(
"CREATE TABLE book(id SERIAL PRIMARY KEY, title TEXT NOT NULL)",
)
.execute(&mut conn)
.await
.unwrap();

conn
})
},
)
.await
.unwrap();
})
.await;
}
}
57 changes: 57 additions & 0 deletions book/src/tutorials/async/04.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
fn main() {}

#[cfg(test)]
mod tests {
#![allow(dead_code, unused_variables)]

use bb8::Pool;
use db_pool::{
r#async::{
// import database pool
DatabasePool,
// import database pool builder trait
DatabasePoolBuilderTrait,
DieselAsyncPgBackend,
DieselBb8,
},
PrivilegedPostgresConfig,
};
use diesel::sql_query;
use diesel_async::RunQueryDsl;
use dotenvy::dotenv;
use tokio::sync::OnceCell;

async fn get_connection_pool() {
// change OnceCell inner type
static POOL: OnceCell<DatabasePool<DieselAsyncPgBackend<DieselBb8>>> =
OnceCell::const_new();

let db_pool = POOL.get_or_init(|| async {
dotenv().ok();

let config = PrivilegedPostgresConfig::from_env().unwrap();

// Diesel pool association type can be inferred now
let backend = DieselAsyncPgBackend::new(
config,
|| Pool::builder().max_size(10),
|| Pool::builder().max_size(2),
move |mut conn| {
Box::pin(async {
sql_query("CREATE TABLE book(id SERIAL PRIMARY KEY, title TEXT NOT NULL)")
.execute(&mut conn)
.await
.unwrap();

conn
})
},
)
.await
.unwrap();

// create database pool
backend.create_database_pool().await.unwrap()
});
}
}
65 changes: 65 additions & 0 deletions book/src/tutorials/async/05.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
fn main() {}

#[cfg(test)]
mod tests {
#![allow(dead_code)]

use bb8::Pool;
use db_pool::{
r#async::{
// import connection pool
ConnectionPool,
DatabasePool,
DatabasePoolBuilderTrait,
DieselAsyncPgBackend,
DieselBb8,
// import reusable object wrapper
Reusable,
},
PrivilegedPostgresConfig,
};
use diesel::sql_query;
use diesel_async::RunQueryDsl;
use dotenvy::dotenv;
use tokio::sync::OnceCell;

// change return type
async fn get_connection_pool(
) -> Reusable<'static, ConnectionPool<DieselAsyncPgBackend<DieselBb8>>> {
static POOL: OnceCell<DatabasePool<DieselAsyncPgBackend<DieselBb8>>> =
OnceCell::const_new();

let db_pool = POOL
.get_or_init(|| async {
dotenv().ok();

let config = PrivilegedPostgresConfig::from_env().unwrap();

let backend = DieselAsyncPgBackend::new(
config,
|| Pool::builder().max_size(10),
|| Pool::builder().max_size(2),
move |mut conn| {
Box::pin(async {
sql_query(
"CREATE TABLE book(id SERIAL PRIMARY KEY, title TEXT NOT NULL)",
)
.execute(&mut conn)
.await
.unwrap();

conn
})
},
)
.await
.unwrap();

backend.create_database_pool().await.unwrap()
})
.await;

// pull connection pool
db_pool.pull().await
}
}
89 changes: 89 additions & 0 deletions book/src/tutorials/async/06.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
fn main() {}

#[cfg(test)]
mod tests {
#![allow(dead_code)]

use db_pool::{
r#async::{
ConnectionPool, DatabasePool, DatabasePoolBuilderTrait, DieselAsyncPgBackend,
DieselBb8, Reusable,
},
PrivilegedPostgresConfig,
};
// import extra diesel-specific constructs
use bb8::Pool;
use diesel::{insert_into, sql_query, table, Insertable, QueryDsl};
use diesel_async::RunQueryDsl;
use dotenvy::dotenv;
use tokio::sync::OnceCell;

async fn get_connection_pool(
) -> Reusable<'static, ConnectionPool<DieselAsyncPgBackend<DieselBb8>>> {
static POOL: OnceCell<DatabasePool<DieselAsyncPgBackend<DieselBb8>>> =
OnceCell::const_new();

let db_pool = POOL
.get_or_init(|| async {
dotenv().ok();

let config = PrivilegedPostgresConfig::from_env().unwrap();

let backend = DieselAsyncPgBackend::new(
config,
|| Pool::builder().max_size(10),
|| Pool::builder().max_size(2),
move |mut conn| {
Box::pin(async {
sql_query(
"CREATE TABLE book(id SERIAL PRIMARY KEY, title TEXT NOT NULL)",
)
.execute(&mut conn)
.await
.unwrap();

conn
})
},
)
.await
.unwrap();

backend.create_database_pool().await.unwrap()
})
.await;

db_pool.pull().await
}

// add test case
async fn test() {
table! {
book (id) {
id -> Int4,
title -> Text
}
}

#[derive(Insertable)]
#[diesel(table_name = book)]
struct NewBook<'a> {
title: &'a str,
}

// get connection pool from database pool
let conn_pool = get_connection_pool().await;
let conn = &mut conn_pool.get().await.unwrap();

let new_book = NewBook { title: "Title" };

insert_into(book::table)
.values(&new_book)
.execute(conn)
.await
.unwrap();

let count = book::table.count().get_result::<i64>(conn).await.unwrap();
assert_eq!(count, 1);
}
}
Loading

0 comments on commit a7aa711

Please sign in to comment.