tarpc icon indicating copy to clipboard operation
tarpc copied to clipboard

How to shut down the server?

Open garious opened this issue 4 years ago • 4 comments

Looking at HelloServer in example-service, how would one add a "Press <ENTER> to shut down" feature?

garious avatar Jul 09 '20 21:07 garious

Hey! Tarpc doesn't build in any shutdown functionality, because different people may want different behavior. But, adding it yourself via native futures/streams features wouldn't be too hard; it just kind of depends what you mean by shutdown. Are you interested in...

  • an insta-kill that severs all client and server connections and drops all in-flight requests?
    • would you want outbound requests to be cancelled cleanly or to just kill those connections?
  • a lameduck mode where...
    • existing connections are honored?
    • existing requests are allowed to complete, after which connections are closed?

One simple approach is to just make your server future abortable. If you're spawning client connections onto different tasks, you'd need to take some extra steps to shut down those connections.

tikue avatar Jul 09 '20 22:07 tikue

Either approach would work for me, but with preference to the lameduck mode. I'll take a look at abortable, thanks.

Maybe this would be helpful here? https://github.com/jonhoo/stream-cancel

garious avatar Jul 09 '20 22:07 garious

stream-cancel looks very relevant -- also, jonhoo makes great stuff, so I'd trust it as a dependency. In general, I think tarpc's approach to servers is modular enough to allow fitting in custom approaches to shutdown. If you end up playing around with shutdown with tarpc, I'd be very interested in seeing some examples. Maybe we could even incorporate them into the readme or example-service/.

tikue avatar Jul 09 '20 22:07 tikue

Hey @tikue, here's what I ended up going with:

 async fn start_abortable_tcp_server(addr: SocketAddr, exit: Arc<AtomicBool>) {
     let server = start_tcp_server(addr).fuse();
     let interval = time::interval(Duration::from_millis(100)).fuse();
     pin_mut!(server, interval);
     loop {
         select! {
             _ = server => {},
             _ = interval.select_next_some() => {
                 if exit.load(Ordering::Relaxed) {
                     break;
                 }
             }
         }
     }
 }

Not a graceful shutdown, but gets the job done.

garious avatar Jul 15 '20 23:07 garious