@@ -11,7 +11,10 @@ use actix_files::{Files, NamedFile};
1111use actix_web:: {
1212 App , Error , HttpRequest , HttpResponse , HttpServer , Responder , middleware:: Logger , web,
1313} ;
14+ use examples_common:: { init_standard_logger, watch_shutdown_signal} ;
15+ use eyre:: WrapErr as _;
1416use ractor:: { Actor , ActorRef } ;
17+ use tokio_util:: sync:: CancellationToken ;
1518
1619mod server;
1720mod session;
@@ -24,11 +27,12 @@ async fn index() -> impl Responder {
2427async fn chat_route (
2528 req : HttpRequest ,
2629 stream : web:: Payload ,
27- srv : web:: Data < ActorRef < server:: Command > > ,
30+ web:: ThinData ( srv) : web:: ThinData < ActorRef < server:: Command > > ,
31+ web:: ThinData ( shutdown) : web:: ThinData < CancellationToken > ,
2832) -> Result < HttpResponse , Error > {
2933 let ( response, session, messages) = actix_ws:: handle ( & req, stream) ?;
3034
31- tokio:: task:: spawn_local ( session:: chat_ws ( srv. get_ref ( ) . clone ( ) , session, messages) ) ;
35+ tokio:: task:: spawn_local ( session:: chat_ws ( srv, session, messages, shutdown ) ) ;
3236
3337 Ok ( response)
3438}
@@ -40,8 +44,9 @@ async fn get_count(count: web::Data<AtomicUsize>) -> impl Responder {
4044}
4145
4246#[ tokio:: main]
43- async fn main ( ) -> std:: io:: Result < ( ) > {
44- env_logger:: init_from_env ( env_logger:: Env :: new ( ) . default_filter_or ( "info" ) ) ;
47+ async fn main ( ) -> eyre:: Result < ( ) > {
48+ color_eyre:: install ( ) ?;
49+ init_standard_logger ( ) ;
4550
4651 // set up applications state
4752 // keep a count of the number of visitors
@@ -51,27 +56,37 @@ async fn main() -> std::io::Result<()> {
5156 let ( server, server_task) =
5257 server:: ChatServer :: spawn ( None , server:: ChatServer , app_state. clone ( ) )
5358 . await
54- . map_err ( std:: io:: Error :: other) ?;
55- let shutdown = server. clone ( ) ;
59+ . wrap_err ( "failed to start chat actor" ) ?;
60+ let actor = server. clone ( ) ;
61+ let shutdown = CancellationToken :: new ( ) ;
62+ watch_shutdown_signal ( shutdown. clone ( ) ) ;
63+ let worker_shutdown = shutdown. clone ( ) ;
5664
57- log :: info!( "starting HTTP server at http://localhost:8080" ) ;
65+ tracing :: info!( "starting HTTP server at http://localhost:8080" ) ;
5866
59- let result = HttpServer :: new ( move || {
67+ let http_server = HttpServer :: new ( move || {
6068 App :: new ( )
6169 . app_data ( web:: Data :: from ( app_state. clone ( ) ) )
62- . app_data ( web:: Data :: new ( server. clone ( ) ) )
70+ . app_data ( web:: ThinData ( server. clone ( ) ) )
71+ . app_data ( web:: ThinData ( worker_shutdown. clone ( ) ) )
6372 . service ( web:: resource ( "/" ) . to ( index) )
6473 . route ( "/count" , web:: get ( ) . to ( get_count) )
6574 . route ( "/ws" , web:: get ( ) . to ( chat_route) )
6675 . service ( Files :: new ( "/static" , "./static" ) )
6776 . wrap ( Logger :: default ( ) )
6877 } )
78+ . shutdown_signal ( shutdown. clone ( ) . cancelled_owned ( ) )
6979 . workers ( 2 )
70- . bind ( ( "127.0.0.1" , 8080 ) ) ?
71- . run ( )
72- . await ;
80+ . bind ( ( "127.0.0.1" , 8080 ) ) ;
81+
82+ let result = match http_server {
83+ Ok ( http_server) => http_server. run ( ) . await . wrap_err ( "HTTP server failed" ) ,
84+ Err ( err) => Err ( err) . wrap_err ( "failed to bind HTTP server" ) ,
85+ } ;
86+
87+ shutdown. cancel ( ) ;
88+ actor. stop ( None ) ;
89+ server_task. await . wrap_err ( "chat actor task failed" ) ?;
7390
74- shutdown. stop ( None ) ;
75- server_task. await . map_err ( std:: io:: Error :: other) ?;
7691 result
7792}
0 commit comments