Skip to content

Commit 4bf9c26

Browse files
authored
Merge pull request #23 from dimacurrentai/axum_state
Using functions and the state instead of closures with captures.
2 parents 4db1bc8 + b14771e commit 4bf9c26

File tree

1 file changed

+44
-34
lines changed

1 file changed

+44
-34
lines changed

step07_redb/code/src/main.rs

Lines changed: 44 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use axum::{routing::get, serve, Router};
1+
use axum::{extract::State, routing::get, serve, Router};
22
use hyper::header::HeaderMap;
33
use redb::{Database, ReadableTable, TableDefinition};
44
use serde::{Deserialize, Serialize};
@@ -17,6 +17,13 @@ use crate::lib::http;
1717

1818
static GLOBALS: TableDefinition<u64, u64> = TableDefinition::new("globals");
1919

20+
#[derive(Clone)]
21+
struct AppState {
22+
redb: Arc<Database>,
23+
counter_runs: u64,
24+
shutdown_tx: mpsc::Sender<()>,
25+
}
26+
2027
#[derive(Serialize, Deserialize, Debug)]
2128
#[serde(tag = "type")]
2229
enum JSONResponse {
@@ -25,13 +32,24 @@ enum JSONResponse {
2532
Counters { counter_runs: u64, counter_requests: u64 },
2633
}
2734

28-
#[tokio::main]
29-
async fn main() -> Result<(), Box<dyn Error>> {
30-
fs::create_dir_all(&Path::new("./.db"))?;
31-
let redb = Arc::new(Database::create("./.db/demo.redb")?);
32-
let initial_counter_runs_value = inc_counter(&redb, 1).await?;
33-
run_main(redb, initial_counter_runs_value).await;
34-
Ok(())
35+
async fn health_handler() -> &'static str {
36+
"OK\n"
37+
}
38+
39+
async fn hello_handler() -> &'static str {
40+
"hello this is a rust http server\n"
41+
}
42+
43+
async fn quit_handler(State(state): State<AppState>) -> &'static str {
44+
let _ = state.shutdown_tx.send(()).await;
45+
"yes i am shutting down\n"
46+
}
47+
48+
async fn json_handler(State(state): State<AppState>, headers: HeaderMap) -> impl axum::response::IntoResponse {
49+
let counter_requests = inc_counter(&state.redb, 2).await.unwrap_or(0);
50+
let response = JSONResponse::Counters { counter_runs: state.counter_runs, counter_requests };
51+
let json_string = serde_json::to_string(&response).unwrap();
52+
http::json_or_html(headers, &json_string).await
3553
}
3654

3755
async fn inc_counter(redb: &Database, idx: u64) -> Result<u64, Box<dyn Error>> {
@@ -50,34 +68,25 @@ async fn inc_counter(redb: &Database, idx: u64) -> Result<u64, Box<dyn Error>> {
5068
Ok(counter_runs)
5169
}
5270

53-
async fn run_main(redb: Arc<Database>, counter_runs: u64) {
71+
#[tokio::main]
72+
async fn main() -> Result<(), Box<dyn Error>> {
73+
fs::create_dir_all(&Path::new("./.db"))?;
74+
let redb = Arc::new(Database::create("./.db/demo.redb")?);
75+
let initial_counter_runs_value = inc_counter(&redb, 1).await?;
76+
5477
let (shutdown_tx, mut shutdown_rx) = mpsc::channel::<()>(1);
78+
let state = AppState {
79+
redb: redb.clone(),
80+
counter_runs: initial_counter_runs_value,
81+
shutdown_tx: shutdown_tx.clone(),
82+
};
5583

5684
let app = Router::new()
57-
.route("/healthz", get(|| async { "OK\n" }))
58-
.route("/", get(|| async { "hello this is a rust http server\n" }))
59-
.route(
60-
"/quit",
61-
get({
62-
let shutdown_tx = shutdown_tx.clone();
63-
|| async move {
64-
let _ = shutdown_tx.send(()).await;
65-
"yes i am shutting down\n"
66-
}
67-
}),
68-
)
69-
.route(
70-
"/json",
71-
get(move |headers: HeaderMap| {
72-
let counter_runs = counter_runs;
73-
async move {
74-
let counter_requests = inc_counter(&redb, 2).await.unwrap_or(0);
75-
let response = JSONResponse::Counters { counter_runs, counter_requests };
76-
let json_string = serde_json::to_string(&response).unwrap();
77-
http::json_or_html(headers, &json_string).await
78-
}
79-
}),
80-
);
85+
.route("/healthz", get(health_handler))
86+
.route("/", get(hello_handler))
87+
.route("/quit", get(quit_handler))
88+
.route("/json", get(json_handler))
89+
.with_state(state);
8190

8291
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
8392
let listener = TcpListener::bind(addr).await.unwrap();
@@ -90,11 +99,12 @@ async fn run_main(redb: Arc<Database>, counter_runs: u64) {
9099
let mut int_signal = signal(SignalKind::interrupt()).expect("failed to register SIGINT handler");
91100

92101
tokio::select! {
93-
_ = server.with_graceful_shutdown(async move { shutdown_rx.recv().await; }) => { println! ("done"); }
102+
_ = server.with_graceful_shutdown(async move { shutdown_rx.recv().await; }) => { println!("done"); }
94103
_ = tokio::signal::ctrl_c() => { println!("terminating due to Ctrl+C"); }
95104
_ = term_signal.recv() => { println!("terminating due to SIGTERM"); }
96105
_ = int_signal.recv() => { println!("terminating due to SIGINT"); }
97106
}
98107

99108
println!("rust http server down");
109+
Ok(())
100110
}

0 commit comments

Comments
 (0)