Skip to content

Commit 1d0bc40

Browse files
committed
Merge branch 'main' of github.com:sonntuet1997/rust-web-api-microservice-template into HEAD
2 parents 345b957 + 33131b1 commit 1d0bc40

File tree

11 files changed

+96
-30
lines changed

11 files changed

+96
-30
lines changed

Cargo.lock

Lines changed: 11 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/adapter/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ version = "0.6.0"
2929
features = ["postgres", "serde"]
3030

3131
[dependencies.diesel]
32-
version = "2.1.4"
32+
version = "2.1.6"
3333
features = ["postgres", "postgres_backend", "uuid"]
3434

3535
[dependencies.serde]

src/adapter/src/repositories/repository_test.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ mod question_repository_tests {
88
Manager,
99
};
1010
use diesel_migrations::MigrationHarness;
11-
use testcontainers_modules::{postgres::Postgres, testcontainers::clients::Cli};
11+
use testcontainers_modules::postgres;
12+
use testcontainers_modules::testcontainers::runners::AsyncRunner;
1213

1314
use rust_core::{
1415
entities::{
@@ -89,12 +90,11 @@ mod question_repository_tests {
8990
#[tokio::test]
9091
async fn question_postgres_repository_test() {
9192
// Set up a postgres database question port for testing
92-
let docker = Cli::default();
93-
let postgres_instance = docker.run(Postgres::default());
93+
let postgres_instance = postgres::Postgres::default().start().await;
9494

9595
let database_url = format!(
9696
"postgres://postgres:postgres@127.0.0.1:{}/postgres",
97-
postgres_instance.get_host_port_ipv4(5432)
97+
postgres_instance.get_host_port_ipv4(5432).await
9898
);
9999
let database_config = DatabaseConfig {
100100
url: database_url.clone(),

src/common/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ features = ["derive"]
4848
version = "0.3.18"
4949
features = ["env-filter"]
5050

51+
[dependencies.tokio]
52+
version = "1.37.0"
53+
5154
[dependencies.tonic]
5255
version = "0.11.0"
5356

src/common/src/kill_signals.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use tokio::signal;
2+
use tracing::info;
3+
4+
pub async fn wait_for_kill_signals() {
5+
let ctrl_c = async {
6+
signal::ctrl_c()
7+
.await
8+
.expect("Failed to install Ctrl+C handler");
9+
};
10+
11+
#[cfg(unix)]
12+
let terminate = async {
13+
signal::unix::signal(signal::unix::SignalKind::terminate())
14+
.expect("Failed to install signal handler")
15+
.recv()
16+
.await;
17+
};
18+
19+
#[cfg(not(unix))]
20+
let terminate = std::future::pending::<()>();
21+
22+
tokio::select! {
23+
_ = ctrl_c => {
24+
info!("Received ctrl_c!");
25+
},
26+
_ = terminate => {
27+
info!("Received terminate!");
28+
},
29+
}
30+
}

src/common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
pub mod grpc;
2+
pub mod kill_signals;
23
pub mod loggers;
34
pub mod options;

src/core/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ version = "1.0"
2020
features = ["derive"]
2121

2222
[dependencies.thiserror]
23-
version = "1.0.57"
23+
version = "1.0.59"
2424

2525
[dependencies.anyhow]
2626
version = "1.0.82"

src/gpt_answer_server/src/main.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,21 @@ use std::sync::Arc;
22

33
use clap::{Parser, Subcommand};
44
use opentelemetry::global;
5+
use tokio::signal;
6+
use tokio::sync::oneshot;
7+
use tokio::sync::oneshot::Receiver;
58
use tonic::transport::Server;
9+
use tracing::info;
610

711
use adapter::repositories::redis::cache::RedisCache;
812
use common::grpc::gpt_answer::gpt_answer::gpt_answer_service_server::GptAnswerServiceServer;
13+
use common::kill_signals;
914
use common::loggers::telemetry::init_telemetry;
1015
use common::options::parse_options;
1116
use gpt_answer_server::controllers::gpt_answer::GptAnswerServiceImpl;
1217
use gpt_answer_server::options::Options;
1318

14-
pub async fn serve(options: Options) {
19+
pub async fn serve(options: Options, rx: Receiver<()>) {
1520
let address = options.server_endpoint.parse().unwrap();
1621
println!("Starting GPT Answer server at {}", options.server_endpoint);
1722

@@ -23,7 +28,10 @@ pub async fn serve(options: Options) {
2328

2429
Server::builder()
2530
.add_service(GptAnswerServiceServer::new(gpt_answer_service))
26-
.serve(address)
31+
.serve_with_shutdown(address, async {
32+
rx.await.ok();
33+
info!("GRPC server shut down");
34+
})
2735
.await
2836
.unwrap();
2937
}
@@ -55,11 +63,17 @@ async fn main() {
5563
options.log.level.as_str(),
5664
);
5765

58-
let server = tokio::spawn(serve(options));
66+
let (tx, rx) = oneshot::channel();
67+
let server = tokio::spawn(serve(options, rx));
5968

60-
tokio::try_join!(server).expect("Failed to run servers");
69+
kill_signals::wait_for_kill_signals().await;
70+
71+
// Send the shutdown signal
72+
let _ = tx.send(());
73+
tokio::try_join!(server).expect("Failed to run server");
6174

6275
global::shutdown_tracer_provider();
76+
info!("Shutdown successfully!");
6377
}
6478

6579
/// GPT Answer GRPC server.

src/public/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ version = "0.6.0"
8686
features = ["postgres", "serde"]
8787

8888
[dependencies.diesel]
89-
version = "2.1.0"
89+
version = "2.1.6"
9090
features = ["postgres", "postgres_backend", "uuid"]
9191

9292
[dependencies.openssl]
@@ -108,7 +108,7 @@ version = "1.36.0"
108108
features = ["full"]
109109

110110
[dependencies.thiserror]
111-
version = "1.0.57"
111+
version = "1.0.59"
112112

113113
[dependencies.anyhow]
114114
version = "1.0.82"

src/public/src/main.rs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,17 @@ use clap::{Parser, Subcommand};
1212
use deadpool_diesel::postgres::Pool;
1313
use deadpool_diesel::{Manager, Runtime};
1414
use opentelemetry::global;
15+
use tokio::signal;
16+
use tokio::sync::oneshot;
17+
use tokio::sync::oneshot::Receiver;
1518
use tracing::info;
1619

1720
use adapter::repositories::grpc::gpt_answer_client::GptAnswerClient;
1821
use adapter::repositories::in_memory::question::QuestionInMemoryRepository;
1922
use adapter::repositories::postgres::question_db::QuestionDBRepository;
2023
use cli::options::Options;
2124
use cli::router::Router;
25+
use common::kill_signals;
2226
use common::loggers::telemetry::init_telemetry;
2327
use common::options::parse_options;
2428
use rust_core::ports::question::QuestionPort;
@@ -50,10 +54,19 @@ async fn main() {
5054
options.log.level.as_str(),
5155
);
5256

53-
let server = tokio::spawn(serve(options));
54-
tokio::try_join!(server).expect("Failed to run servers");
57+
let (tx, rx) = oneshot::channel();
58+
let server = tokio::spawn(serve(options, rx));
59+
60+
kill_signals::wait_for_kill_signals().await;
61+
62+
// Send the shutdown signal
63+
let _ = tx.send(());
64+
65+
// Wait for the server to finish shutting down
66+
tokio::try_join!(server).expect("Failed to run server");
5567

5668
global::shutdown_tracer_provider();
69+
info!("Shutdown successfully!");
5770
}
5871

5972
/// Simple REST server.
@@ -76,7 +89,7 @@ enum Commands {
7689
Config,
7790
}
7891

79-
pub async fn serve(options: Options) {
92+
pub async fn serve(options: Options, rx: Receiver<()>) {
8093
let question_port: Arc<dyn QuestionPort + Send + Sync> = if options.db.in_memory.is_some() {
8194
info!("Using in-memory database");
8295
Arc::new(QuestionInMemoryRepository::new())
@@ -103,6 +116,10 @@ pub async fn serve(options: Options) {
103116
Ipv4Addr::from_str(options.server.url.as_str()).unwrap(),
104117
options.server.port,
105118
);
119+
let (_, server) = warp::serve(routes).bind_with_graceful_shutdown(address, async {
120+
rx.await.ok();
121+
info!("Warp server shut down");
122+
});
106123

107-
warp::serve(routes).run(address).await
124+
server.await;
108125
}

src/public/tests/questions_router_test.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ mod tests {
77
};
88
use diesel_migrations::MigrationHarness;
99
use rand::Rng;
10-
use testcontainers_modules::{postgres::Postgres, testcontainers::clients::Cli};
10+
use testcontainers_modules::postgres;
11+
use testcontainers_modules::testcontainers::runners::AsyncRunner;
1112
use warp::http::StatusCode;
1213
use warp::test::request;
1314

@@ -177,12 +178,11 @@ mod tests {
177178
#[tokio::test]
178179
async fn questions_router_postgres_test() {
179180
// Set up a postgres database question port for testing
180-
let docker = Cli::default();
181-
let postgres_instance = docker.run(Postgres::default());
181+
let postgres_instance = postgres::Postgres::default().start().await;
182182

183183
let database_url = format!(
184184
"postgres://postgres:postgres@127.0.0.1:{}/postgres",
185-
postgres_instance.get_host_port_ipv4(5432)
185+
postgres_instance.get_host_port_ipv4(5432).await
186186
);
187187
let database_config = DatabaseConfig {
188188
url: database_url.clone(),

0 commit comments

Comments
 (0)