diff --git a/Cargo.lock b/Cargo.lock index 0db43ea91..3b91c81e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,8 +14,8 @@ name = "actix" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-http 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "actix_derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -49,13 +49,13 @@ dependencies = [ [[package]] name = "actix-connect" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", @@ -67,15 +67,15 @@ dependencies = [ [[package]] name = "actix-http" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-connect 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-connect 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-server-config 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-threadpool 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -99,9 +99,9 @@ dependencies = [ "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -119,10 +119,10 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "actix-server 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "awc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -131,7 +131,7 @@ dependencies = [ "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -150,16 +150,17 @@ dependencies = [ "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "actix-rt" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-threadpool 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "copyless 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -172,7 +173,7 @@ name = "actix-server" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "actix-rt 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "actix-server-config 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", @@ -222,7 +223,7 @@ dependencies = [ [[package]] name = "actix-utils" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -237,18 +238,18 @@ dependencies = [ [[package]] name = "actix-web" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "actix-router 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-rt 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-rt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "actix-server 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-server-config 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "actix-threadpool 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-utils 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-utils 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "awc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -259,9 +260,9 @@ dependencies = [ "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -275,8 +276,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -368,7 +369,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -378,7 +379,7 @@ dependencies = [ "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -386,10 +387,10 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -397,7 +398,7 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -542,7 +543,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rust-ini 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -799,7 +800,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -976,7 +977,7 @@ dependencies = [ "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -995,7 +996,7 @@ dependencies = [ "medea-client-api-proto 0.1.0-dev", "medea-macro 0.1.0-dev", "newtype_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-futures 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1075,6 +1076,14 @@ dependencies = [ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lock_api" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.9" @@ -1114,9 +1123,9 @@ name = "medea" version = "0.1.0-dev" dependencies = [ "actix 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-http 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-http 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "actix-http-test 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "actix-web 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "actix-web 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "actix-web-actors 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "bb8 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "bb8-redis 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1134,7 +1143,7 @@ dependencies = [ "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redis 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde-humantime 0.1.1 (git+https://github.com/tailhook/serde-humantime?branch=serde_wrapper)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serial_test 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1147,6 +1156,7 @@ dependencies = [ "slog-stdlog 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "smart-default 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-signal 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1155,7 +1165,7 @@ name = "medea-client-api-proto" version = "0.1.0-dev" dependencies = [ "medea-macro 0.1.0-dev", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1358,6 +1368,16 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.4.0" @@ -1385,6 +1405,20 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "percent-encoding" version = "1.0.1" @@ -1750,10 +1784,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.95" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1774,12 +1808,12 @@ version = "0.1.1" source = "git+https://github.com/tailhook/serde-humantime?branch=serde_wrapper#36b86d5ca09db3caf2edb06e0d46b505d0915792" dependencies = [ "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.95" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1794,7 +1828,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1812,7 +1846,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1896,7 +1930,7 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "slog 2.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2260,7 +2294,7 @@ name = "toml" version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2388,7 +2422,7 @@ name = "wasm-bindgen" version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "wasm-bindgen-macro 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2566,7 +2600,7 @@ dependencies = [ [[package]] name = "winreg" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2601,17 +2635,17 @@ dependencies = [ "checksum Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" "checksum actix 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "671ce3d27313f236827a5dd153a1073ad03ef31fc77f562020263e7830cf1ef7" "checksum actix-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9f2c11af4b06dc935d8e1b1491dad56bfb32febc49096a91e773f8535c176453" -"checksum actix-connect 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d7fbab0d79b2f3415a79570e3db12eaa75c26239541e613b832655145a5e9488" -"checksum actix-http 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "29c11d33772c790e9aeb2e024834bc084f7496598482908e2424efd768c912b6" +"checksum actix-connect 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d161322a26e6b76d6598f48654afbdcfee644c900d4368e9962ec68abd0713b" +"checksum actix-http 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "47403dd5aaebc1b4ab0757f7f3c6cd92d805086293e651a91898b21dbcc24f07" "checksum actix-http-test 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "92c0b021449cb043876c30e0b555844125fefd4b90568467d12c4ba3db751a64" "checksum actix-router 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "23224bb527e204261d0291102cb9b52713084def67d94f7874923baefe04ccf7" -"checksum actix-rt 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "61e09627004cb25149fd177c4a062d2061c4ec40aae5820ecd37a87195e759f8" +"checksum actix-rt 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "18d9054b1cfacfa441846b9b99001010cb8fbb02130e6cfdb25cea36d3e98e87" "checksum actix-server 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ba8c936356c882420eab87051b12ca1926dc42348863d05fff7eb151df9cddbb" "checksum actix-server-config 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e78703f07d0bd08b426b482d53569d84f1e1929024f0431b3a5a2dc0c1c60e0f" "checksum actix-service 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "aaecc01bbc595ebd7a563a7d4f8a607d0b964bb55273c6f362b0b02c26508cf2" "checksum actix-threadpool 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1c29f7c554d56b3841f4bb85d5b3dee01ba536e1307679f56eb54de28aaec3fb" -"checksum actix-utils 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b307201d074c963041cd8858d6b6a82ca23369827d613da5d6e972de123d3c14" -"checksum actix-web 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0dc7ab62d04b9eeb0f368ad9c6ee20c2e3541fb9a25a5eb727c9118b59e8ff2" +"checksum actix-utils 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07d9689cab66e39b2d5aea5d082d10ca36193d23472a93267822599aa2e611be" +"checksum actix-web 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "864123627dea7fe20601e0d26c6c826a4f2a5d7eed87d776b53eba2064b817fa" "checksum actix-web-actors 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8197aa04b8950ed9e37340cd46fe7ad3ccb8b1c4bbcef881ee5f6d149a425608" "checksum actix-web-codegen 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe9e3cdec1e645b675f354766e0688c5705021c85ab3cf739be1c8999b91c76" "checksum actix_derive 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0bf5f6d7bf2d220ae8b4a7ae02a572bb35b7c4806b24049af905ab8110de156c" @@ -2625,8 +2659,8 @@ dependencies = [ "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" "checksum awc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4c4763e6aa29a801d761dc3464f081d439ea5249ba90c3c3bdfc8dd3f739d233" -"checksum backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "18b50f5258d1a9ad8396d2d345827875de4261b158124d4c819d9b351454fae5" -"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61" +"checksum backtrace 0.3.33 (registry+https://github.com/rust-lang/crates.io-index)" = "88fb679bc9af8fa639198790a77f52d345fe13656c08b43afa9424c206b731c6" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bb8 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6ac04c3b2d3327a583c9a93b6c5ab4316e6609f5ec84b71b89ebe518e0edbad2" "checksum bb8-redis 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9817f38c173f0da1581b923b90e66750a090413ad67a20980d5ad64141bab476" @@ -2706,6 +2740,7 @@ dependencies = [ "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed946d4529956a20f2d63ebe1b69996d5a2137c91913fe3ebbeff957f5bca7ff" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" @@ -2733,8 +2768,10 @@ dependencies = [ "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7767817701cce701d5585b9c4db3cdd02086398322c1d7e8bf5094a96a2ce7" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum parking_lot_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb88cb1cb3790baa6776844f968fea3be44956cf184fa1be5a03341f5491278c" +"checksum parking_lot_core 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a7bbaa05312363e0480e1efee133fff1a09ef4a6406b65e226b9a793c223a32" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" @@ -2780,10 +2817,10 @@ dependencies = [ "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" -"checksum serde 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)" = "e47a9fd6b2d2d2330b19b0b3e5248a170a5acd6356fd88c7bb30362ef9c70567" +"checksum serde 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "d46b3dfedb19360a74316866cef04687cd4d6a70df8e6a506c63512790769b72" "checksum serde-hjson 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0b833c5ad67d52ced5f5938b2980f32a9c1c5ef047f0b4fb3127e7a423c76153" "checksum serde-humantime 0.1.1 (git+https://github.com/tailhook/serde-humantime?branch=serde_wrapper)" = "" -"checksum serde_derive 1.0.95 (registry+https://github.com/rust-lang/crates.io-index)" = "5ea8eb91549d859275aef70c58bb30bd62ce50e5eb1a52d32b1b6886e02f7bce" +"checksum serde_derive 1.0.97 (registry+https://github.com/rust-lang/crates.io-index)" = "c22a0820adfe2f257b098714323563dd06426502abbbce4f51b72ef544c5027f" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_test 0.8.23 (registry+https://github.com/rust-lang/crates.io-index)" = "110b3dbdf8607ec493c22d5d947753282f3bae73c0f56d322af1e8c78e4c23d5" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" @@ -2866,7 +2903,7 @@ dependencies = [ "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum winreg 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "daf67b95d0b1bf421c4f11048d63110ca3719977169eec86396b614c8942b6e0" +"checksum winreg 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73f1f3c6c4d3cab118551b96c476a2caab920701e28875b64a458f2ecb96ec9d" "checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/Cargo.toml b/Cargo.toml index f6508fed3..3882377d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ slog-scope = "4.1" slog-stdlog = "3.0" smart-default = "0.5" tokio = "0.1" +tokio-signal = "0.2" toml = "0.4" [dependencies.serde-humantime] git = "https://github.com/tailhook/serde-humantime" diff --git a/config.toml b/config.toml index cb8ae5a59..3b88e034a 100644 --- a/config.toml +++ b/config.toml @@ -86,3 +86,12 @@ # # Default: # level = "INFO" + + + + +[shutdown] +# Maximum duration given to shutdown the whole application gracefully. +# +# Default: +# timeout = "1s" diff --git a/src/api/client/server.rs b/src/api/client/server.rs index fe60da288..ad8761530 100644 --- a/src/api/client/server.rs +++ b/src/api/client/server.rs @@ -2,7 +2,9 @@ use std::io; +use actix::{Actor, Addr, Handler, ResponseActFuture, WrapFuture as _}; use actix_web::{ + dev::Server as ActixServer, middleware, web::{resource, Data, Path, Payload}, App, HttpRequest, HttpResponse, HttpServer, @@ -24,6 +26,7 @@ use crate::{ }, conf::{Conf, Rpc}, log::prelude::*, + shutdown::ShutdownGracefully, signalling::{RoomId, RoomsRepository}, }; @@ -86,42 +89,64 @@ pub struct Context { pub config: Rpc, } -/// Starts HTTP server for handling WebSocket connections of Client API. -pub fn run(rooms: RoomsRepository, config: Conf) -> io::Result<()> { - let server_addr = config.server.bind_addr(); +/// HTTP server that handles WebSocket connections of Client API. +pub struct Server(ActixServer); + +impl Server { + /// Starts Client API HTTP server. + pub fn run(rooms: RoomsRepository, config: Conf) -> io::Result> { + let server_addr = config.server.bind_addr(); + + let server = HttpServer::new(move || { + App::new() + .data(Context { + rooms: rooms.clone(), + config: config.rpc.clone(), + }) + .wrap(middleware::Logger::default()) + .service( + resource("/ws/{room_id}/{member_id}/{credentials}") + .route(actix_web::web::get().to_async(ws_index)), + ) + }) + .disable_signals() + .bind(server_addr)? + .start(); - HttpServer::new(move || { - App::new() - .data(Context { - rooms: rooms.clone(), - config: config.rpc.clone(), - }) - .wrap(middleware::Logger::default()) - .service( - resource("/ws/{room_id}/{member_id}/{credentials}") - .route(actix_web::web::get().to_async(ws_index)), - ) - }) - .bind(server_addr)? - .start(); + info!("Started Client API HTTP server on {}", server_addr); + + Ok(Self(server).start()) + } +} - info!("Started HTTP server on {}", server_addr); +impl Actor for Server { + type Context = actix::Context; +} - Ok(()) +impl Handler for Server { + type Result = ResponseActFuture; + + fn handle( + &mut self, + _: ShutdownGracefully, + _: &mut Self::Context, + ) -> Self::Result { + info!("Shutting down Client API HTTP server"); + Box::new(self.0.stop(true).into_actor(self)) + } } #[cfg(test)] mod test { use std::{ops::Add, thread, time::Duration}; - use actix::Actor as _; use actix_http::{ws::Message, HttpService}; use actix_http_test::{TestServer, TestServerRuntime}; use futures::{future::IntoFuture as _, sink::Sink as _, Stream as _}; use crate::{ - api::control::Member, media::create_peers, signalling::Room, - turn::new_turn_auth_service_mock, + api::control::Member, conf::Conf, media::create_peers, + signalling::Room, turn::new_turn_auth_service_mock, }; use super::*; diff --git a/src/conf/mod.rs b/src/conf/mod.rs index 4a68fe683..454df6f9b 100644 --- a/src/conf/mod.rs +++ b/src/conf/mod.rs @@ -3,6 +3,7 @@ pub mod log; pub mod rpc; pub mod server; +pub mod shutdown; pub mod turn; use std::env; @@ -15,6 +16,7 @@ pub use self::{ log::Log, rpc::Rpc, server::Server, + shutdown::Shutdown, turn::{Redis, Turn}, }; @@ -37,6 +39,8 @@ pub struct Conf { pub turn: Turn, /// Logging settings. pub log: Log, + /// Application shutdown settings. + pub shutdown: Shutdown, } impl Conf { @@ -262,4 +266,17 @@ mod tests { assert_eq!(Conf::parse().unwrap().log.level(), None); } + + #[test] + #[serial] + fn shutdown_conf_test() { + let default_conf = Conf::default(); + + env::set_var("MEDEA_SHUTDOWN.TIMEOUT", "700ms"); + + let env_conf = Conf::parse().unwrap(); + + assert_ne!(default_conf.shutdown.timeout, env_conf.shutdown.timeout); + assert_eq!(env_conf.shutdown.timeout, Duration::from_millis(700)); + } } diff --git a/src/conf/shutdown.rs b/src/conf/shutdown.rs new file mode 100644 index 000000000..c351ca837 --- /dev/null +++ b/src/conf/shutdown.rs @@ -0,0 +1,16 @@ +//! Application shutdown settings. + +use std::time::Duration; + +use serde::{Deserialize, Serialize}; +use smart_default::SmartDefault; + +/// Application shutdown settings. +#[derive(Clone, Debug, Deserialize, Serialize, SmartDefault)] +#[serde(default)] +pub struct Shutdown { + /// Maximum duration given to shutdown the whole application gracefully. + #[default(Duration::from_secs(5))] + #[serde(with = "serde_humantime")] + pub timeout: Duration, +} diff --git a/src/main.rs b/src/main.rs index 95f71b92d..fefb2cdc1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ pub mod api; pub mod conf; pub mod log; pub mod media; +pub mod shutdown; pub mod signalling; pub mod turn; @@ -17,9 +18,10 @@ use futures::IntoFuture as _; use log::prelude::*; use crate::{ - api::{client::server, control::Member}, + api::{client::server::Server, control::Member}, conf::Conf, media::create_peers, + shutdown::GracefulShutdown, signalling::{Room, RoomsRepository}, turn::new_turn_auth_service, }; @@ -53,15 +55,48 @@ fn main() -> io::Result<()> { turn_auth_service, ) .start(); - + Ok((room, config)) + }) + .and_then(|(room, config)| { + let graceful_shutdown = + GracefulShutdown::new(config.shutdown.timeout).start(); + graceful_shutdown + .send(shutdown::Subscribe(shutdown::Subscriber { + addr: room.clone().recipient(), + priority: shutdown::Priority(2), + })) + .map_err(|e| { + error!("Shutdown subscription failed for Room: {}", e) + }) + .map(move |_| (room, graceful_shutdown, config)) + }) + .map(|(room, graceful_shutdown, config)| { let rooms = hashmap! {1 => room}; let rooms_repo = RoomsRepository::new(rooms); - - server::run(rooms_repo, config) - .map_err(|err| { - error!("Error starting application {:?}", err) + (rooms_repo, graceful_shutdown, config) + }) + .and_then(|(rooms_repo, graceful_shutdown, config)| { + Server::run(rooms_repo, config) + .map_err(|e| { + error!("Error starting Client API HTTP server {:?}", e) + }) + .map(|server| { + graceful_shutdown + .send(shutdown::Subscribe(shutdown::Subscriber { + addr: server.recipient(), + priority: shutdown::Priority(1), + })) + .map_err(|e| { + error!( + "Shutdown subscription failed for Client \ + API HTTP server: {}", + e + ) + }) + .map(|_| ()) }) .into_future() + .flatten() }) }) } diff --git a/src/shutdown.rs b/src/shutdown.rs new file mode 100644 index 000000000..eaa57df1c --- /dev/null +++ b/src/shutdown.rs @@ -0,0 +1,225 @@ +//! Graceful shutdown implementation. + +use std::{ + collections::{BTreeMap, HashSet}, + time::Duration, +}; + +use actix::{ + prelude::{Actor, Context}, + AsyncContext, Handler, Message, Recipient, ResponseActFuture, System, + WrapFuture as _, +}; +use failure::Fail; +use futures::{future, stream, Future, Stream}; +use tokio::{timer::timeout, util::FutureExt as _}; + +use crate::log::prelude::*; + +/// Priority that [`Subscriber`] should be triggered to shutdown gracefully +/// with. +#[derive(Clone, Copy, Eq, Ord, PartialOrd, PartialEq)] +pub struct Priority(pub u8); + +/// Message that [`Subscriber`] is informed with to perform its graceful +/// shutdown. +#[allow(clippy::module_name_repetitions)] +#[derive(Debug, Message)] +#[rtype(result = "Result<(), ()>")] +pub struct ShutdownGracefully; + +/// Service which listens incoming OS signals and performs graceful +/// shutdown for all its [`Subscriber`]s. +#[allow(clippy::module_name_repetitions)] +pub struct GracefulShutdown { + /// Subscribers being subscribed to [`GracefulShutdown`] service. + subs: BTreeMap>>, + /// Timeout for shutdown to complete gracefully. + timeout: Duration, + /// Current state of [`GracefulShutdown`] service. + state: State, +} + +/// Possible state of [`GracefulShutdown`] service. +enum State { + /// Service is up and listening to OS signals. + Listening, + /// Service is performing graceful shutdown at the moment. + InProgress, +} + +impl GracefulShutdown { + /// Creates new [`GracefulShutdown`] service. + #[inline] + pub fn new(timeout: Duration) -> Self { + Self { + subs: BTreeMap::new(), + timeout, + state: State::Listening, + } + } +} + +impl Actor for GracefulShutdown { + type Context = Context; + + fn started(&mut self, ctx: &mut Self::Context) { + #[cfg(not(unix))] + { + warning!( + "Graceful shutdown is disabled: only UNIX signals are \ + supported" + ); + return; + } + #[cfg(unix)] + { + use tokio_signal::unix::{ + Signal, SIGHUP, SIGINT, SIGQUIT, SIGTERM, + }; + for s in &[SIGHUP, SIGINT, SIGQUIT, SIGTERM] { + ctx.add_message_stream( + Signal::new(*s) + .flatten_stream() + .map(OsSignal) + .map_err(|_| error!("Error getting shutdown signal")), + ); + } + } + } + + fn stopped(&mut self, _: &mut Self::Context) { + if let State::Listening = self.state { + info!("Graceful shutdown has been completed"); + } + } +} + +/// Message that is received by [`GracefulShutdown`] shutdown service when +/// the process receives an OS signal. +#[cfg(unix)] +#[derive(Message)] +#[rtype(result = "Result<(), ()>")] +struct OsSignal(i32); + +#[cfg(unix)] +impl Handler for GracefulShutdown { + type Result = ResponseActFuture; + + fn handle( + &mut self, + sig: OsSignal, + _: &mut Context, + ) -> ResponseActFuture { + info!("OS signal '{}' received", sig.0); + + match self.state { + State::InProgress => { + return Box::new(future::ok(()).into_actor(self)); + } + State::Listening => { + self.state = State::InProgress; + } + } + + info!("Initiating graceful shutdown..."); + + if self.subs.is_empty() { + System::current().stop(); + return Box::new(future::ok(()).into_actor(self)); + } + + let by_priority: Vec<_> = self + .subs + .values() + .map(|addrs| { + let addrs: Vec<_> = addrs + .iter() + .map(|addr| { + addr.send(ShutdownGracefully).map(|_| ()).or_else(|e| { + error!("Error requesting shutdown: {}", e); + future::ok::<(), ()>(()) + }) + }) + .collect(); + future::join_all(addrs) + }) + .collect(); + + Box::new( + stream::unfold(by_priority, |mut v| { + v.pop().map(|fut| Ok((fut, v))) + }) + .collect() + .timeout(self.timeout) + .map_err(|e: timeout::Error<()>| { + error!("Graceful shutdown has timed out: {:?}", e) + }) + .map(|_| System::current().stop()) + .into_actor(self), + ) + } +} + +/// Subscriber to [`GracefulShutdown`] service, which is notified when +/// graceful shutdown happens. +pub struct Subscriber { + /// Priority that [`Subscriber`] should be notified with. + /// + /// Higher priority means that [`Subscriber`] will be notified sooner. + /// [`Subscriber`] won't be notified until all other [`Subscriber`]s with + /// higher priority will complete their shutdown. + pub priority: Priority, + + /// Address of [`Subscriber`] to inform it about graceful shutdown via. + pub addr: Recipient, +} + +/// Message that [`Subscriber`] subscribes to shutdown messages with. +#[derive(Message)] +#[rtype(result = "Result<(), ShuttingDownError>")] +pub struct Subscribe(pub Subscriber); + +impl Handler for GracefulShutdown { + type Result = Result<(), ShuttingDownError>; + + /// Subscribes provided [`Subscriber`] to shutdown notifications. + /// + /// Returns [`ShuttingDownError`] if shutdown happens at the moment. + fn handle(&mut self, m: Subscribe, _: &mut Context) -> Self::Result { + if let State::InProgress = self.state { + return Err(ShuttingDownError); + } + let addrs = self.subs.entry(m.0.priority).or_insert_with(HashSet::new); + addrs.insert(m.0.addr); + Ok(()) + } +} + +#[derive(Clone, Copy, Debug, Fail)] +#[fail(display = "Process is shutting down at the moment")] +pub struct ShuttingDownError; + +/// Message that [`Subscriber`] unsubscribes from receiving shutdown +/// notifications with. +#[derive(Message)] +#[rtype(result = "()")] +pub struct Unsubscribe(pub Subscriber); + +impl Handler for GracefulShutdown { + type Result = (); + + /// Unsubscribes provided [`Subscriber`] to shutdown notifications. + fn handle(&mut self, m: Unsubscribe, _: &mut Context) { + let mut remove = false; + if let Some(addrs) = self.subs.get_mut(&m.0.priority) { + addrs.remove(&m.0.addr); + if addrs.is_empty() { + remove = true; + } + } + if remove { + self.subs.remove(&m.0.priority); + } + } +} diff --git a/src/signalling/participants.rs b/src/signalling/participants.rs index 2f5df65e3..1a0f5a8cf 100644 --- a/src/signalling/participants.rs +++ b/src/signalling/participants.rs @@ -29,7 +29,7 @@ use crate::{ log::prelude::*, media::IceUser, signalling::{ - room::{ActFuture, CloseRoom, RoomError}, + room::{ActFuture, RoomError}, Room, RoomId, }, turn::{TurnAuthService, TurnServiceErr, UnreachablePolicy}, @@ -213,8 +213,6 @@ impl ParticipantService { /// with specified user [`Member`] from the storage and closes the room. /// If [`ClosedReason::Lost`], then creates delayed task that emits /// [`ClosedReason::Closed`]. - // TODO: Don't close the room. It is being closed atm, because we have - // no way to handle absence of RpcConnection. pub fn connection_closed( &mut self, ctx: &mut Context, @@ -230,7 +228,8 @@ impl ParticipantService { error!("Error deleting IceUser {:?}", err) }), )); - ctx.notify(CloseRoom {}) + // TODO: we have no way to handle absence of RpcConnection right + // now. } ClosedReason::Lost => { self.drop_connection_tasks.insert( @@ -270,7 +269,8 @@ impl ParticipantService { } } - /// Cancels all connection close tasks, closes all [`RpcConnection`]s, + /// Cancels all connection close tasks, closes all [`RpcConnection`]s and + /// deletes all [`IceUser`]s. pub fn drop_connections( &mut self, ctx: &mut Context, diff --git a/src/signalling/room.rs b/src/signalling/room.rs index 8d72dc047..46b52c99b 100644 --- a/src/signalling/room.rs +++ b/src/signalling/room.rs @@ -5,7 +5,7 @@ use std::{collections::HashMap as StdHashMap, time::Duration}; use actix::{ fut::wrap_future, Actor, ActorFuture, AsyncContext, Context, Handler, - Message, + Message, ResponseActFuture, WrapFuture as _, }; use failure::Fail; use futures::future; @@ -25,6 +25,7 @@ use crate::{ New, Peer, PeerError, PeerId, PeerStateMachine, WaitLocalHaveRemote, WaitLocalSdp, WaitRemoteSdp, }, + shutdown::ShutdownGracefully, signalling::{participants::ParticipantService, peers::PeerRepository}, turn::TurnAuthService, }; @@ -36,7 +37,7 @@ pub type Id = u64; pub type ActFuture = Box>; -#[derive(Fail, Debug)] +#[derive(Debug, Fail)] #[allow(clippy::module_name_repetitions)] pub enum RoomError { #[fail(display = "Couldn't find Peer with [id = {}]", _0)] @@ -65,6 +66,17 @@ impl From for RoomError { } } +/// Possible states of [`Room`]. +#[derive(Debug)] +enum State { + /// [`Room`] has been started and is operating at the moment. + Started, + /// [`Room`] is stopping at the moment. + Stopping, + /// [`Room`] is stopped and can be removed. + Stopped, +} + /// Media server room with its [`Member`]s. #[derive(Debug)] pub struct Room { @@ -75,6 +87,9 @@ pub struct Room { /// [`Peer`]s of [`Member`]s in this [`Room`]. peers: PeerRepository, + + /// Current state of this [`Room`]. + state: State, } impl Room { @@ -95,6 +110,7 @@ impl Room { turn, reconnect_timeout, ), + state: State::Started, } } @@ -266,11 +282,33 @@ impl Room { self.participants.send_event_to_member(to_member_id, event), ))) } + + /// Closes [`Room`] gracefully, by dropping all the connections and moving + /// into [`State::Stopped`]. + fn close_gracefully( + &mut self, + ctx: &mut Context, + ) -> ResponseActFuture { + info!("Closing Room [id = {:?}]", self.id); + self.state = State::Stopping; + + let room_id = self.id; + Box::new( + self.participants + .drop_connections(ctx) + .into_actor(self) + .map(move |_, room: &mut Self, _| { + room.state = State::Stopped; + }) + .map_err(move |_, _, _| { + error!("Error closing room {:?}", room_id); + }), + ) + } } /// [`Actor`] implementation that provides an ergonomic way /// to interact with [`Room`]. -// TODO: close connections on signal (gracefull shutdown) impl Actor for Room { type Context = Context; } @@ -307,13 +345,16 @@ impl Handler for Room { ) -> Self::Result { match self.send_peer_created(msg.0, msg.1) { Ok(res) => { - Box::new(res.map_err(|err, _, ctx: &mut Context| { + Box::new(res.then(|res, room, ctx| -> ActFuture<(), ()> { + if res.is_ok() { + return Box::new(future::ok(()).into_actor(room)); + } error!( "Failed handle command, because {}. Room will be \ stopped.", - err + res.unwrap_err(), ); - ctx.notify(CloseRoom {}) + room.close_gracefully(ctx) })) } Err(err) => { @@ -321,8 +362,7 @@ impl Handler for Room { "Failed handle command, because {}. Room will be stopped.", err ); - ctx.notify(CloseRoom {}); - Box::new(wrap_future(future::ok(()))) + self.close_gracefully(ctx) } } } @@ -355,13 +395,16 @@ impl Handler for Room { match result { Ok(res) => { - Box::new(res.map_err(|err, _, ctx: &mut Context| { + Box::new(res.then(|res, room, ctx| -> ActFuture<(), ()> { + if res.is_ok() { + return Box::new(future::ok(()).into_actor(room)); + } error!( "Failed handle command, because {}. Room will be \ stopped.", - err + res.unwrap_err(), ); - ctx.notify(CloseRoom {}) + room.close_gracefully(ctx) })) } Err(err) => { @@ -369,8 +412,7 @@ impl Handler for Room { "Failed handle command, because {}. Room will be stopped.", err ); - ctx.notify(CloseRoom {}); - Box::new(wrap_future(future::ok(()))) + self.close_gracefully(ctx) } } } @@ -417,25 +459,16 @@ impl Handler for Room { } } -/// Signal of close [`Room`]. -#[derive(Debug, Message)] -#[rtype(result = "()")] -#[allow(clippy::module_name_repetitions)] -pub struct CloseRoom {} - -impl Handler for Room { - type Result = (); +impl Handler for Room { + type Result = ResponseActFuture; - /// Sends to remote [`Member`] the [`Event`] about [`Peer`] removed. - /// Closes all active [`RpcConnection`]s. fn handle( &mut self, - _msg: CloseRoom, + _: ShutdownGracefully, ctx: &mut Self::Context, ) -> Self::Result { - info!("Closing Room [id = {:?}]", self.id); - let drop_fut = self.participants.drop_connections(ctx); - ctx.wait(wrap_future(drop_fut)); + info!("Shutdown signal received for Room: {:?}", self.id); + self.close_gracefully(ctx) } } diff --git a/src/signalling/room_repo.rs b/src/signalling/room_repo.rs index f0df8ead4..37acbe04c 100644 --- a/src/signalling/room_repo.rs +++ b/src/signalling/room_repo.rs @@ -1,10 +1,10 @@ //! Repository that stores [`Room`]s addresses. +use std::sync::{Arc, Mutex}; + use actix::Addr; use hashbrown::HashMap; -use std::sync::{Arc, Mutex}; - use crate::signalling::{Room, RoomId}; /// Repository that stores [`Room`]s addresses.