net.http: add graceful shutdown .stop() method to the http.Server struct (#11233)

pull/11242/head
Miccah 2021-08-19 03:19:49 -05:00 committed by GitHub
parent 7bffabbce2
commit 6991a3c8d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 41 additions and 7 deletions

View File

@ -36,6 +36,7 @@ const (
'vlib/net/http/status_test.v',
'vlib/net/http/http_httpbin_test.v',
'vlib/net/http/header_test.v',
'vlib/net/http/server_test.v',
'vlib/net/udp_test.v',
'vlib/net/tcp_test.v',
'vlib/orm/orm_test.v',
@ -87,6 +88,7 @@ const (
'vlib/net/websocket/websocket_test.v',
'vlib/net/http/http_httpbin_test.v',
'vlib/net/http/header_test.v',
'vlib/net/http/server_test.v',
]
skip_on_linux = [
'do_not_remove',

View File

@ -12,22 +12,34 @@ interface Handler {
}
pub struct Server {
stop_signal chan bool = chan bool{cap: 1}
pub mut:
port int = 8080
handler Handler = DebugHandler{}
read_timeout time.Duration = 30 * time.second
write_timeout time.Duration = 30 * time.second
port int = 8080
handler Handler = DebugHandler{}
read_timeout time.Duration = 30 * time.second
write_timeout time.Duration = 30 * time.second
accept_timeout time.Duration = 30 * time.second
}
pub fn (mut s Server) listen_and_serve() ? {
pub fn (s &Server) listen_and_serve() ? {
if s.handler is DebugHandler {
eprintln('Server handler not set, using debug handler')
}
mut l := net.listen_tcp(.ip6, ':$s.port') ?
l.set_accept_timeout(s.accept_timeout)
eprintln('Listening on :$s.port')
for {
// break if we have a stop signal (non-blocking check)
select {
_ := <-s.stop_signal {
break
}
else {}
}
mut conn := l.accept() or {
eprintln('accept() failed: $err; skipping')
if err.msg != 'net: op timed out' {
eprintln('accept() failed: $err; skipping')
}
continue
}
conn.set_read_timeout(s.read_timeout)
@ -37,7 +49,11 @@ pub fn (mut s Server) listen_and_serve() ? {
}
}
fn (mut s Server) parse_and_respond(mut conn net.TcpConn) {
pub fn (s Server) stop() {
s.stop_signal <- true
}
fn (s &Server) parse_and_respond(mut conn net.TcpConn) {
defer {
conn.close() or { eprintln('close() failed: $err') }
}

View File

@ -0,0 +1,16 @@
module http
import time
fn test_server_stop() ? {
server := &Server{
accept_timeout: 1 * time.second
}
t := go server.listen_and_serve()
time.sleep(250 * time.millisecond)
mut watch := time.new_stopwatch()
server.stop()
assert watch.elapsed() < 100 * time.millisecond
t.wait() ?
assert watch.elapsed() < 999 * time.millisecond
}