Implementing graceful shutdown - #105
Conversation
| _ = signal::ctrl_c() => (), | ||
| _ = term_signal.recv() => (), | ||
| }; | ||
| // initiate graceful shutdown sequence on sig int |
There was a problem hiding this comment.
| // initiate graceful shutdown sequence on sig int | |
| // Initiate graceful shutdown sequence on SIGINT |
|
Current issue is that a client can be connected to pgcat and not be sending any messages and pgcat will be waiting for this client to complete it's work. Need some ideas to help solve this |
| let mut term_signal = unix_signal(SignalKind::terminate()).unwrap(); | ||
|
|
||
| tokio::select! { | ||
| _ = signal::ctrl_c() => (), |
There was a problem hiding this comment.
Curious why you removed the ctrl-c and the SIGTERM handler? SIGTERM is commonly used in Docker containers to stop a container.
There was a problem hiding this comment.
Pgbouncer interprets sigterm and sigint differently. since the sigint is graceful shutdown we want to catch and handle that. for sigterm, which is immediate shutdown we don't need to do anything special
SIGINT
Safe shutdown. Same as issuing PAUSE and SHUTDOWN on the console.
SIGTERM
Immediate shutdown. Same as issuing SHUTDOWN on the console.
There was a problem hiding this comment.
I'm curious about the reasoning here. In Kuberentes SIGTERM is meant to initiate a graceful shutdown. https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/
| stream.recv().await; | ||
| client::SHUTTING_DOWN.store(true, Ordering::Relaxed); | ||
| warn!("Got SIGINT, waiting for client connection drain now"); | ||
| wg.wait(); |
There was a problem hiding this comment.
I'm wondering if just save tokio::task::spawn handles in a Vec in main.rs and then waiting for them all to exit task.await is best?
| stringprep = "0.1" | ||
| tokio-rustls = "0.23" | ||
| rustls-pemfile = "1" | ||
| wg = "0.1.0" No newline at end of file |
There was a problem hiding this comment.
Based on this, it doesn't look like a well-known crate. Are we sure we need it? I think tokio should give us the tools we need to do this task.
Interesting problem. What about using Tokio docs have some ideas for us: https://tokio.rs/tokio/topics/shutdown |
|
Used channel transmitter shutdown logic found here: https://tokio.rs/tokio/topics/shutdown |
| stringprep = "0.1" | ||
| tokio-rustls = "0.23" | ||
| rustls-pemfile = "1" | ||
| rustls-pemfile = "1" No newline at end of file |
There was a problem hiding this comment.
Can you please add a terminal new line
| // Client connection loop. | ||
| tokio::task::spawn(async move { | ||
| // Creates event subscriber for shutdown event, this is dropped when shutdown event is broadcast | ||
| let mut listener_rx = shutdown_event_tx_clone.subscribe(); |
There was a problem hiding this comment.
Please rename to shutdown_event_rx because it can be confused with TCP listener by the reader.
| // Closes transmitter | ||
| drop(shutdown_event_tx); | ||
|
|
||
| loop { |
There was a problem hiding this comment.
There should be two events that the receiver gets, the 1st is the event sent by shutdown_event_tx.send(()).unwrap(); and then the second event would be when all senders are closed and there is an error on the receive channel. made it a loop so that the timeout could be applied to all the operations.
| cleanup_conn(conn, cur) | ||
|
|
||
|
|
||
| def test_shutdown_logic(): |
There was a problem hiding this comment.
We use bash for these kind of tests, why Python?
There was a problem hiding this comment.
Since we're operating on the same postgres connection and doing things in between queries and transactions it felt easiest to do it in python.
| ); | ||
|
|
||
| bytes.put_u8(b'Z'); | ||
| bytes.put_i32(5); |
There was a problem hiding this comment.
@zainkabani I think you may want to update this 5 to also be mem::size_of::<u8>() + mem::size_of::<i32>() + mem::size_of::<u8>()
This PR attempts to implement a graceful shutdown mechanism for pgcat like pgbouncer.