diff --git a/Cargo.lock b/Cargo.lock index 65775c123e4..01865d5d27e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,11 +17,6 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "adler32" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "aes" version = "0.3.2" @@ -100,6 +95,11 @@ name = "antidote" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "anyhow" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "argon2rs" version = "0.2.5" @@ -166,7 +166,7 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -302,8 +302,8 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "build_const" -version = "0.2.1" +name = "bumpalo" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -333,9 +333,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bytes" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "c2-chacha" version = "0.2.3" @@ -351,7 +356,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -418,12 +423,12 @@ dependencies = [ [[package]] name = "common-multipart-rfc7578" -version = "0.1.1" +version = "0.2.0-rc" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "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)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -433,32 +438,6 @@ name = "constant_time_eq" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cookie" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cookie_store" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "core-foundation" version = "0.5.1" @@ -476,22 +455,6 @@ dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crc32fast" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam" version = "0.2.12" @@ -502,7 +465,7 @@ name = "crossbeam" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -544,7 +507,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -564,7 +527,7 @@ name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -738,22 +701,12 @@ dependencies = [ "generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "dirs" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "dirs" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -762,7 +715,7 @@ name = "dirs-sys" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_users 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -799,7 +752,7 @@ name = "encoding_rs" version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -823,9 +776,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "ethabi" @@ -950,16 +900,6 @@ name = "fixedbitset" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "flate2" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "float-cmp" version = "0.5.3" @@ -1015,6 +955,34 @@ name = "futures" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-channel" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "futures-cpupool" version = "0.1.8" @@ -1024,6 +992,61 @@ dependencies = [ "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "futures-executor" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-io" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-macro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-sink" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "generic-array" version = "0.9.0" @@ -1090,9 +1113,10 @@ dependencies = [ "ethabi 10.0.0 (git+https://github.com/graphprotocol/ethabi.git)", "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipfs-api 0.5.1 (git+https://github.com/ferristseng/rust-ipfs-api)", + "ipfs-api 0.6.0-rc (registry+https://github.com/rust-lang/crates.io-index)", "isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "mockall 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1103,7 +1127,7 @@ dependencies = [ "priority-queue 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "prometheus 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1114,11 +1138,8 @@ dependencies = [ "slog-envlogger 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "slog-term 2.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-retry 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-retry 0.2.0 (git+https://github.com/graphprotocol/rust-tokio-retry?branch=update-to-tokio-02)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "web3 0.8.0 (git+https://github.com/graphprotocol/rust-web3)", ] @@ -1148,14 +1169,14 @@ dependencies = [ name = "graph-core" version = "0.17.1" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "graph 0.17.1", "graph-graphql 0.17.1", "graph-mock 0.17.1", "graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipfs-api 0.5.1 (git+https://github.com/ferristseng/rust-ipfs-api)", + "ipfs-api 0.6.0-rc (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "lru_time_cache 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1202,7 +1223,7 @@ dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "git-testament 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "graph 0.17.1", "graph-chain-ethereum 0.17.1", @@ -1216,8 +1237,7 @@ dependencies = [ "graph-server-websocket 0.17.1", "graph-store-postgres 0.17.1", "graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "ipfs-api 0.5.1 (git+https://github.com/ferristseng/rust-ipfs-api)", + "ipfs-api 0.6.0-rc (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "prometheus 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1245,12 +1265,13 @@ dependencies = [ "graph-runtime-derive 0.17.1", "graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ipfs-api 0.5.1 (git+https://github.com/ferristseng/rust-ipfs-api)", + "ipfs-api 0.6.0-rc (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", "pwasm-utils 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "test-store 0.1.0", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1259,13 +1280,14 @@ dependencies = [ name = "graph-server-http" version = "0.17.1" dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "graph 0.17.1", "graph-graphql 0.17.1", "graph-mock 0.17.1", "graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1273,12 +1295,13 @@ dependencies = [ name = "graph-server-index-node" version = "0.17.1" dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "graph 0.17.1", "graph-graphql 0.17.1", "graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1297,10 +1320,11 @@ dependencies = [ name = "graph-server-metrics" version = "0.17.1" dependencies = [ + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "graph 0.17.1", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "prometheus 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1314,10 +1338,12 @@ dependencies = [ "graph 0.17.1", "graph-graphql 0.17.1", "graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tungstenite 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1385,6 +1411,24 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "h2" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "heck" version = "0.3.1" @@ -1409,7 +1453,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "hex-literal-impl 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1417,7 +1461,7 @@ name = "hex-literal-impl" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1448,6 +1492,16 @@ dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "http-body" version = "0.1.0" @@ -1459,6 +1513,15 @@ dependencies = [ "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http-body" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.3" @@ -1502,7 +1565,7 @@ dependencies = [ "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1519,16 +1582,39 @@ dependencies = [ "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hyper-multipart-rfc7578" -version = "0.3.0" +version = "0.4.0-rc" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "common-multipart-rfc7578 0.1.1 (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.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "common-multipart-rfc7578 0.2.0-rc (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1543,6 +1629,18 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper-tls" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -1634,34 +1732,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ipfs-api" -version = "0.5.1" -source = "git+https://github.com/ferristseng/rust-ipfs-api#55902e98d868dcce047863859caf596a629d10ec" +version = "0.6.0-rc" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.6 (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.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-multipart-rfc7578 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-multipart-rfc7578 0.4.0-rc (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "multiaddr 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1670,7 +1765,7 @@ name = "isatty" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1681,6 +1776,14 @@ name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "js-sys" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "jsonrpc-core" version = "14.0.5" @@ -1744,11 +1847,6 @@ dependencies = [ "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "lazycell" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "libc" version = "0.2.66" @@ -1789,7 +1887,7 @@ name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1881,35 +1979,16 @@ dependencies = [ "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "miniz_oxide" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz_oxide_c_api" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mio" -version = "0.6.16" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1923,9 +2002,9 @@ name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1944,7 +2023,7 @@ name = "mockall" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "downcast 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1958,7 +2037,7 @@ name = "mockall_derive" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2014,7 +2093,7 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2024,6 +2103,15 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "normalize-line-endings" version = "0.2.2" @@ -2091,7 +2179,7 @@ version = "0.10.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2226,7 +2314,7 @@ name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (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.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2240,7 +2328,7 @@ name = "parking_lot_core" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (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.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2297,6 +2385,34 @@ dependencies = [ "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pin-project" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-internal" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pin-project-lite" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pin-utils" +version = "0.1.0-alpha.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pkg-config" version = "0.3.14" @@ -2416,14 +2532,19 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.8" +version = "0.5.11" 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)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-nested" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.30" @@ -2445,7 +2566,7 @@ name = "prometheus" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2458,18 +2579,6 @@ name = "protobuf" version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "publicsuffix" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pwasm-utils" version = "0.11.0" @@ -2766,34 +2875,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "reqwest" -version = "0.9.24" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "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)", - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.7 (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.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2978,13 +3088,13 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.5.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (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.104 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3142,12 +3252,17 @@ name = "socket2" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "sourcefile" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "spin" version = "0.5.2" @@ -3280,7 +3395,7 @@ name = "tempfile" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3385,7 +3500,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3401,6 +3516,24 @@ dependencies = [ "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-macros 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-buf" version = "0.1.1" @@ -3428,9 +3561,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3488,6 +3621,15 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-reactor" version = "0.1.8" @@ -3497,7 +3639,7 @@ dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3508,11 +3650,12 @@ dependencies = [ [[package]] name = "tokio-retry" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/graphprotocol/rust-tokio-retry?branch=update-to-tokio-02#fc0e868bdc7ff79ac84cf502d4cec20c5ce5adaf" dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3531,8 +3674,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3583,6 +3726,15 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-tls" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-tungstenite" version = "0.6.0" @@ -3606,7 +3758,7 @@ dependencies = [ "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)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3619,10 +3771,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3635,16 +3787,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "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)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tower-service" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "traitobject" version = "0.1.0" @@ -3660,14 +3830,6 @@ name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "try_from" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tungstenite" version = "0.6.1" @@ -3868,6 +4030,92 @@ dependencies = [ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "want" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "wasm-bindgen-webidl" +version = "0.2.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "wasmi" version = "0.5.1" @@ -3889,6 +4137,18 @@ dependencies = [ "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "web-sys" +version = "0.3.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "web3" version = "0.8.0" @@ -3941,6 +4201,14 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "weedle" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -4039,7 +4307,6 @@ dependencies = [ [metadata] "checksum Inflector 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" "checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" -"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aes 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "54eb1d8fe354e5fc611daf4f2ea97dd45a765f4f1e4512306ec183ae2e8f20c9" "checksum aes-ctr 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d2e5b0458ea3beae0d1d8c0f3946564f8e10f90646cf78c06b4351052058d1ee" "checksum aes-soft 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cfd7e7ae3f9a1fb5c03b389fc6bb9a51400d0c13053f0dca698c832bfd893a0d" @@ -4049,6 +4316,7 @@ dependencies = [ "checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5" +"checksum anyhow 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "7825f6833612eb2414095684fcf6c635becf3ce97fe48cf6421321e93bfbd53c" "checksum argon2rs 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3f67b0b6a86dae6e67ff4ca2b6201396074996379fba2b92ff649126f37cb392" "checksum arrayref 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0d382e583f07208808f6b1249e60848879ba3543f57c32277bf52d69c2f0f0ee" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" @@ -4075,29 +4343,26 @@ dependencies = [ "checksum block-modes 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "31aa8410095e39fdb732909fb5730a48d5bd7c2e3cd76bd1b07b3dbea130c529" "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591" "checksum bs58 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b170cd256a3f9fa6b9edae3e44a7dfdfc77e8124dbc3e2612d75f9c3e2396dae" -"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum bumpalo 3.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb8038c1ddc0a5f73787b130f4cc75151e96ed33e417fde765eb5a81e3532f4" "checksum byte-slice-cast 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b0a5e3906bcbf133e33c1d4d95afc664ad37fbdb9f6568d8043e7ea8c27d93d3" "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum bytes 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10004c15deb332055f7a4a208190aed362cf9a7c2f6ab70a305fba50e1105f38" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "31850b4a4d6bae316f7a09e691c944c28299298837edc0a03f755618c23cbc01" "checksum cid 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e37fba0087d9f3f4e269827a55dc511abf3e440cc097a0c154ff4e6584f988" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum colored 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e9a455e156a4271e12fd0246238c380b1e223e3736663c7a18ed8b6362028a9" "checksum combine 3.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d2623b3542b48f4427e15ddd4995186decb594ebbd70271463886584b4a114b9" -"checksum common-multipart-rfc7578 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd208355198cd34c14c894257d606ceaad4a5f209a2ed511a6f15e53979b245d" +"checksum common-multipart-rfc7578 0.2.0-rc (registry+https://github.com/rust-lang/crates.io-index)" = "7471b7b1588b2cda44e0cdf3fd3da5706c1b46224dbf486c3daceb6655ec191c" "checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e" -"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" -"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" -"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" "checksum crossbeam 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "bd66663db5a988098a89599d4857919b3acf7f61402e61365acfd3919857b9be" "checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" @@ -4124,7 +4389,6 @@ dependencies = [ "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" -"checksum dirs 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3fd78930633bd1c6e35c4b42b1df7b0cbc6bc191146e512bb3bedf243fcc3901" "checksum dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" "checksum dirs-sys 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" "checksum downcast 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4bb454f0228b18c7f4c3b0ebbee346ed9c52e7443b0999cd543ff3571205701d" @@ -4147,7 +4411,6 @@ dependencies = [ "checksum fallible-iterator 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eb7217124812dc5672b7476d0c2d20cfe9f7c0f1ba0904b674a9762a0212f72e" "checksum fixed-hash 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3367952ceb191f4ab95dd5685dc163ac539e36202f9fcfd0cb22f9f9c542fefc" "checksum fixedbitset 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "86d4de0081402f5e88cdac65c8dcdcc73118c1a7a465e2a05f0da05843a8ea33" -"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum float-cmp 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75224bec9bfe1a65e2d34132933f2de7fe79900c96a0174307554244ece8150e" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -4157,7 +4420,16 @@ dependencies = [ "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" +"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" +"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" +"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" "checksum generic-array 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c0f28c2f5bfb5960175af447a2da7c18900693738343dc896ffbcabd9839592" "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" @@ -4166,6 +4438,7 @@ dependencies = [ "checksum globset 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4743617a7464bbda3c8aec8558ff2f9429047e025771037df561d383337ff865" "checksum graphql-parser 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a5613c31f18676f164112732202124f373bb2103ff017b3b85ca954ea6a66ada" "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" +"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hex 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6a22814455d41612f41161581c2883c0c6a1c41852729b17d5ed88f01e153aa" "checksum hex 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e" @@ -4174,13 +4447,17 @@ dependencies = [ "checksum hmac 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44f3bdb08579d99d7dc761c0e266f13b5f2ab8c8c703b9fc9ef333cd8f48f55e" "checksum hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5dcb5e64cda4c23119ab41ba960d1e170a774c8e4b9d9e6a9bc18aabf5e59695" "checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" +"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" +"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum hyper 0.10.15 (registry+https://github.com/rust-lang/crates.io-index)" = "df0caae6b71d266b91b4a83111a61d2b94ed2e2bea024c532b933dcff867e58c" "checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -"checksum hyper-multipart-rfc7578 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "da7afa9e68d0f45a2790fe76b49b52b50db057502d839187341a7575060c65b9" +"checksum hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf49cfb32edee45d890537d9057d1b02ed55f53b7b6a30bae83a38c9231749e" +"checksum hyper-multipart-rfc7578 0.4.0-rc (registry+https://github.com/rust-lang/crates.io-index)" = "3a71feb0ce26d0e28969633c06521716b07607f58f55dff84f30214b6c6d256a" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +"checksum hyper-tls 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3adcd308402b9553630734e9c36b77a7e48b3821251ca2493e8cd596763aafaa" "checksum ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" @@ -4193,17 +4470,17 @@ dependencies = [ "checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" "checksum input_buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e1b822cc844905551931d6f81608ed5f50a79c1078a4e2b4d42dbc7c1eedfbf" "checksum integer-encoding 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26746cbc2e680af687e88d717f20ff90079bd10fc984ad57d277cd0e37309fa5" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum ipfs-api 0.5.1 (git+https://github.com/ferristseng/rust-ipfs-api)" = "" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum ipfs-api 0.6.0-rc (registry+https://github.com/rust-lang/crates.io-index)" = "6fb9d07b5642832dd10b8f712e9edd006399689523456b6c7f09a06e55d84cf9" "checksum isatty 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e31a8281fc93ec9693494da65fbf28c0c2aa60a2eaec25dc58e2f31952e95edc" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum js-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "7889c7c36282151f6bf465be4700359318aef36baa951462382eae49e9577cf9" "checksum jsonrpc-core 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3b688648f1ef5d5072229e2d672ecb92cbff7d1c79bcf3fd5898f3f3df0970" "checksum jsonrpc-http-server 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2d83d348120edee487c560b7cdd2565055d61cda053aa0d0ef0f8b6a18429048" "checksum jsonrpc-server-utils 14.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "95b7635e618a0edbbe0d2a2bbbc69874277c49383fcf6c3c0414491cfb517d22" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" @@ -4223,9 +4500,7 @@ dependencies = [ "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" -"checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" -"checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum mockall 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7601dfc82314f4e4ad844055452f71c1d5d171e4b530f817b9353bb2e63a271d" @@ -4236,6 +4511,7 @@ dependencies = [ "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" +"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" "checksum normalize-line-endings 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2e0a1a39eab95caf4f5556da9289b9e68f0aafac901b2ce80daaf020d3b733a8" "checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" @@ -4266,6 +4542,10 @@ dependencies = [ "checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +"checksum pin-project 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "94b90146c7216e4cb534069fb91366de4ea0ea353105ee45ed297e2d1619e469" +"checksum pin-project-internal 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "44ca92f893f0656d3cba8158dd0f2b99b94de256a4a54e870bd6922fcc6c8355" +"checksum pin-project-lite 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e8822eb8bb72452f038ebf6048efa02c3fe22bf83f76519c9583e47fc194a422" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum postgres 0.15.2 (registry+https://github.com/rust-lang/crates.io-index)" = "115dde90ef51af573580c035857badbece2aa5cde3de1dfb3c932969ca92a6c5" "checksum postgres-protocol 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2487e66455bf88a1b247bf08a3ce7fe5197ac6d67228d920b0ee6a0e97fd7312" @@ -4278,12 +4558,12 @@ dependencies = [ "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum primitive-types 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e4336f4f5d5524fa60bcbd6fe626f9223d8142a50e7053e979acdf0da41ab975" "checksum priority-queue 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "602c2e38842965277b124586dbc4691d83f37af5b4ecd7c9e46908e1bd7d5b35" -"checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e98a83a9f9b331f54b924e68a66acb1bb35cb01fb0a23645139967abefb697e8" "checksum prometheus 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5567486d5778e2c6455b1b90ff1c558f29e751fc018130fa182e15828e728af1" "checksum protobuf 2.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40361836defdd5871ff7e84096c6f6444af7fc157f8ef1789f54f147687caa20" -"checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum pwasm-utils 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d473123ba135028544926f7aa6f34058d8bc6f120c4fcd3777f84af724280b3" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" @@ -4317,7 +4597,7 @@ dependencies = [ "checksum regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9b01330cce219c1c6b2e209e5ed64ccd587ae5c67bed91c0b49eecf02ae40e21" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rent_to_own 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05a51ad2b1c5c710fa89e6b1631068dab84ed687bc6a5fe061ad65da3d0c25b2" -"checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" +"checksum reqwest 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0e798e19e258bf6c30a304622e3e9ac820e483b06a1857a026e1f109b113fe4" "checksum ripemd160 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad5112e0dbbb87577bfbc56c42450235e3012ce336e29c5befd7807bd626da4a" "checksum rlp 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fa2f7f9c612d133da9101ef7bcd3e603ca7098901eca852e71f87a83dd3e6b59" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" @@ -4342,7 +4622,7 @@ dependencies = [ "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" "checksum serde_json 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "1a3351dcbc1f067e2c92ab7c3c1f288ad1a4cffc470b5aaddb4c2e0a3ae80043" -"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" +"checksum serde_urlencoded 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum sha1 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "171698ce4ec7cbb93babeb3190021b4d72e96ccb98e33d277ae4ea959d6f2d9e" @@ -4362,6 +4642,7 @@ dependencies = [ "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum smallvec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44e59e0c9fa00817912ae6e4e6e3c4fe04455e75699d06eedc7d85917ed8e8f4" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" +"checksum sourcefile 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf77cb82ba8453b42b6ae1d692e4cdc92f9a47beaf89a847c8be83f4e328ad3" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum state_machine_future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "530e1d624baae485bce12e6647acb76aafa253346ee8a16751974eed5a24b13d" @@ -4390,6 +4671,7 @@ dependencies = [ "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tiny-keccak 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d8a021c69bb74a44ccedb824a046447e2c84a01df9e5c20779750acb38e11b2" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +"checksum tokio 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ffa2fdcfa937b20cb3c822a635ceecd5fc1a27a6a474527e5516aa24b8c8820a" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" @@ -4398,22 +4680,25 @@ dependencies = [ "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-macros 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "50a61f268a3db2acee8dcab514efc813dc6dbe8a00e86076f935f94304b59a7a" "checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" -"checksum tokio-retry 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c03755b956458582182941061def32b8123a26c98b08fc6ddcf49ae89d18f33" +"checksum tokio-retry 0.2.0 (git+https://github.com/graphprotocol/rust-tokio-retry?branch=update-to-tokio-02)" = "" "checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" "checksum tokio-timer 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6131e780037787ff1b3f8aad9da83bca02438b72277850dd6ad0d455e0e20efc" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum tokio-tls 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "354b8cd83825b3c20217a9dc174d6a0c67441a2fae5c41bcb1ea6679f6ae0f7c" +"checksum tokio-tls 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7bde02a3a5291395f59b06ec6945a3077602fac2b07eeeaf0dee2122f3619828" "checksum tokio-tungstenite 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4e744ff297473d047436c108c99e478fd73c1dd27e2c08e352907dcd864c720f" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "65ae5d255ce739e8537221ed2942e0445f4b3b813daebac1c0050ddaaa3587f9" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" "checksum traitobject 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" "checksum treeline 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f741b240f1a48843f9b8e0444fb55fb2a4ff67293b50a9179dfd5ea67f8d41" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum tungstenite 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9573852f935883137b7f0824832493ce7418bf290c8cf164b7aafc9b0a99aa0" "checksum typeable 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" @@ -4442,10 +4727,20 @@ dependencies = [ "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +"checksum wasm-bindgen 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "5205e9afdf42282b192e2310a5b463a6d1c1d774e30dc3c791ac37ab42d2616c" +"checksum wasm-bindgen-backend 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "11cdb95816290b525b32587d76419facd99662a07e59d3cdb560488a819d9a45" +"checksum wasm-bindgen-futures 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8bbdd49e3e28b40dec6a9ba8d17798245ce32b019513a845369c641b275135d9" +"checksum wasm-bindgen-macro 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "574094772ce6921576fb6f2e3f7497b8a76273b6db092be18fc48a082de09dc3" +"checksum wasm-bindgen-macro-support 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "e85031354f25eaebe78bb7db1c3d86140312a911a106b2e29f9cc440ce3e7668" +"checksum wasm-bindgen-shared 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e7e61fc929f4c0dddb748b102ebf9f632e2b8d739f2016542b4de2965a9601" +"checksum wasm-bindgen-webidl 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "ef012a0d93fc0432df126a8eaf547b2dce25a8ce9212e1d3cbeef5c11157975d" "checksum wasmi 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f31d26deb2d9a37e6cfed420edce3ed604eab49735ba89035e13c98f9a528313" "checksum wasmi-validation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6bc0356e3df56e639fc7f7d8a99741915531e27ed735d911ed83d7e1339c8188" +"checksum web-sys 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "aaf97caf6aa8c2b1dac90faf0db529d9d63c93846cca4911856f78a83cebf53b" "checksum web3 0.8.0 (git+https://github.com/graphprotocol/rust-web3)" = "" "checksum websocket 0.21.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c9faed2bff8af2ea6b9f8b917d3d00b467583f6781fe3def174a9e33c879703" +"checksum weedle 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3bb43f70885151e629e2a19ce9e50bd730fd436cfd4b666894c9ce4de9141164" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/chain/ethereum/src/block_ingestor.rs b/chain/ethereum/src/block_ingestor.rs index b01dce08875..957a7cdb735 100644 --- a/chain/ethereum/src/block_ingestor.rs +++ b/chain/ethereum/src/block_ingestor.rs @@ -1,7 +1,6 @@ use lazy_static; use std::collections::HashMap; use std::time::Duration; -use std::time::Instant; use graph::prelude::*; use web3::types::*; @@ -88,10 +87,9 @@ where let static_self: &'static _ = Box::leak(Box::new(self)); // Create stream that emits at polling interval - tokio::timer::Interval::new(Instant::now(), static_self.polling_interval) - .map_err(move |e| { - error!(static_self.logger, "timer::Interval failed: {:?}", e); - }) + tokio::time::interval(static_self.polling_interval) + .map(Ok) + .compat() .for_each(move |_| { // Attempt to poll static_self diff --git a/chain/ethereum/src/block_stream.rs b/chain/ethereum/src/block_stream.rs index f5a7c39cb98..4b26980508e 100644 --- a/chain/ethereum/src/block_stream.rs +++ b/chain/ethereum/src/block_stream.rs @@ -2,7 +2,7 @@ use std::cmp; use std::collections::{HashMap, HashSet, VecDeque}; use std::mem; use std::sync::Mutex; -use std::time::{Duration, Instant}; +use std::time::Duration; use graph::components::ethereum::{blocks_with_triggers, triggers_in_block}; use graph::data::subgraph::schema::{ @@ -11,7 +11,6 @@ use graph::data::subgraph::schema::{ use graph::prelude::{ BlockStream as BlockStreamTrait, BlockStreamBuilder as BlockStreamBuilderTrait, *, }; -use tokio::timer::Delay; lazy_static! { /// Maximum number of blocks to request in each chunk. @@ -881,11 +880,10 @@ where // Pause before trying again let secs = (5 * self.consecutive_err_count).max(120) as u64; - let instant = Instant::now() + Duration::from_secs(secs); state = BlockStreamState::RetryAfterDelay(Box::new( - Delay::new(instant).map_err(|err| { - format_err!("RetryAfterDelay future failed = {}", err) - }), + tokio::time::delay_for(Duration::from_secs(secs)) + .map(Ok) + .compat(), )); break Err(e); } diff --git a/chain/ethereum/src/ethereum_adapter.rs b/chain/ethereum/src/ethereum_adapter.rs index 609ea8afe49..86f923d741c 100644 --- a/chain/ethereum/src/ethereum_adapter.rs +++ b/chain/ethereum/src/ethereum_adapter.rs @@ -10,8 +10,8 @@ use std::time::Instant; use ethabi::ParamType; use graph::components::ethereum::{EthereumAdapter as EthereumAdapterTrait, *}; use graph::prelude::{ - debug, err_msg, error, ethabi, format_err, hex, retry, stream, tiny_keccak, tokio_timer, trace, - warn, web3, ChainStore, Error, EthereumCallCache, Logger, + debug, err_msg, error, ethabi, format_err, hex, retry, stream, tiny_keccak, trace, warn, web3, + ChainStore, Error, EthereumCallCache, Logger, TimeoutError, }; use web3::api::Web3; use web3::transports::batch::Batch; @@ -175,7 +175,7 @@ where to: u64, filter: EthGetLogsFilter, too_many_logs_fingerprints: &'static [&'static str], - ) -> impl Future, Error = tokio_timer::timeout::Error> { + ) -> impl Future, Error = TimeoutError> { let eth_adapter = self.clone(); retry("eth_getLogs RPC call", &logger) diff --git a/chain/ethereum/src/network_indexer/network_indexer.rs b/chain/ethereum/src/network_indexer/network_indexer.rs index f48c1632589..05d7decd140 100644 --- a/chain/ethereum/src/network_indexer/network_indexer.rs +++ b/chain/ethereum/src/network_indexer/network_indexer.rs @@ -1174,10 +1174,15 @@ impl NetworkIndexer { start_block, }); - // Launch state machine - tokio::spawn(state_machine.map_err(move |e| { - error!(logger_for_err, "Network indexer failed: {}", e); - })); + // Launch state machine. + // Blocking due to store interactions. Won't be blocking after #905. + graph::spawn_blocking( + state_machine + .map_err(move |e| { + error!(logger_for_err, "Network indexer failed: {}", e); + }) + .compat(), + ); Self { output: Some(output), diff --git a/chain/ethereum/tests/network_indexer.rs b/chain/ethereum/tests/network_indexer.rs index d6508bb2a0a..28ffcd8941e 100644 --- a/chain/ethereum/tests/network_indexer.rs +++ b/chain/ethereum/tests/network_indexer.rs @@ -76,14 +76,14 @@ fn run_network_indexer( let (event_sink, event_stream) = futures::sync::mpsc::channel(100); // Run network indexer and forward its events to the channel - tokio::spawn( + graph::spawn( indexer .take_event_stream() .expect("failed to take stream from indexer") - .timeout(timeout) .map_err(|_| ()) .forward(event_sink.sink_map_err(|_| ())) - .map(|_| ()), + .map(|_| ()) + .timeout(timeout), ); future::ok((chains, event_stream.collect())) @@ -106,13 +106,16 @@ where }; runtime - .block_on(future::lazy(move || { - // Reset store before running - remove_test_data(store.clone()); + .block_on( + future::lazy(move || { + // Reset store before running + remove_test_data(store.clone()); - // Run test - test(store.clone()) - })) + // Run test + test(store.clone()) + }) + .compat(), + ) .expect("failed to run test with clean store"); } diff --git a/core/Cargo.toml b/core/Cargo.toml index 7cb6cfaa0d5..857b19bd827 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -4,15 +4,11 @@ version = "0.17.1" edition = "2018" [dependencies] -bytes = "0.4.12" +bytes = "0.5" futures = "0.1.21" graph = { path = "../graph" } graph-graphql = { path = "../graphql" } - -# We're using the latest ipfs-api for the HTTPS support that was merged in -# https://github.com/ferristseng/rust-ipfs-api/commit/55902e98d868dcce047863859caf596a629d10ec -# but has not been released yet. -ipfs-api = { git = "https://github.com/ferristseng/rust-ipfs-api", branch = "master", features = ["hyper-tls"] } +ipfs-api = { version = "0.6.0-rc", features = ["hyper-tls"] } lazy_static = "1.2.0" lru_time_cache = "0.9" semver = "0.9.0" diff --git a/core/src/link_resolver.rs b/core/src/link_resolver.rs index 7896b860ff0..41823836224 100644 --- a/core/src/link_resolver.rs +++ b/core/src/link_resolver.rs @@ -50,7 +50,7 @@ fn read_u64_from_env(name: &str) -> Option { /// if the IPFS file at `path` is no bigger than `max_file_bytes`. /// If `max_file_bytes` is `None`, do not restrict the size of the file fn restrict_file_size( - client: &ipfs_api::IpfsClient, + client: ipfs_api::IpfsClient, path: String, timeout: Duration, max_file_bytes: Option, @@ -61,11 +61,13 @@ where { match max_file_bytes { Some(max_bytes) => Box::new( - client - .object_stat(&path) - .timeout(timeout) - .map_err(|e| failure::err_msg(e.to_string())) - .and_then(move |stat| match stat.cumulative_size > max_bytes { + Box::pin(async move { + let stat = tokio::time::timeout(timeout, client.object_stat(&path).err_into()) + .err_into() + .await + .and_then(|x| x); + + stat.and_then(move |stat| match stat.cumulative_size > max_bytes { false => Ok(()), true => Err(format_err!( "IPFS file {} is too large. It can be at most {} bytes but is {} bytes", @@ -74,7 +76,9 @@ where stat.cumulative_size )), }) - .and_then(|()| fut), + }) + .compat() + .and_then(|()| fut), ), None => fut, } @@ -151,16 +155,17 @@ impl LinkResolverTrait for LinkResolver { let cat = client_for_cat .cat(&path) - .concat2() - .map(|x| x.to_vec()) - .map_err(|e| failure::err_msg(e.to_string())); + .map_ok(|b| BytesMut::from_iter(b.into_iter())) + .try_concat() + .map_ok(|x| x.to_vec()) + .err_into(); restrict_file_size( - &client_for_file_size, + client_for_file_size.clone(), path.clone(), timeout_for_file_size, max_file_size, - Box::new(cat), + Box::new(cat.compat()), ) .map(move |data| { // Only cache files if they are not too large @@ -188,7 +193,7 @@ impl LinkResolverTrait for LinkResolver { ) -> Box + Send + 'static> { // Discard the `/ipfs/` prefix (if present) to get the hash. let path = link.link.trim_start_matches("/ipfs/").to_owned(); - let mut stream = self.client.cat(&path).fuse(); + let mut stream = self.client.cat(&path).fuse().compat(); let mut buf = BytesMut::with_capacity(1024); // Count the number of lines we've already successfully deserialized. // We need that to adjust the line number in error messages from serde_json @@ -248,7 +253,7 @@ impl LinkResolverTrait for LinkResolver { read_u64_from_env(MAX_IPFS_MAP_FILE_SIZE_VAR).unwrap_or(DEFAULT_MAX_IPFS_MAP_FILE_SIZE); restrict_file_size( - &self.client, + self.client.clone(), path, self.timeout, Some(max_file_size), @@ -262,8 +267,8 @@ mod tests { use super::*; use serde_json::json; - #[test] - fn max_file_size() { + #[tokio::test] + async fn max_file_size() { env::set_var(MAX_IPFS_FILE_SIZE_VAR, "200"); let file: &[u8] = &[0u8; 201]; let client = ipfs_api::IpfsClient::default(); @@ -271,14 +276,10 @@ mod tests { let logger = Logger::root(slog::Discard, o!()); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - let link = runtime.block_on(client.add(file)).unwrap().hash; - let err = runtime - .block_on(LinkResolver::cat( - &resolver, - &logger, - &Link { link: link.clone() }, - )) + let link = client.add(file).await.unwrap().hash; + let err = LinkResolver::cat(&resolver, &logger, &Link { link: link.clone() }) + .compat() + .await .unwrap_err(); env::remove_var(MAX_IPFS_FILE_SIZE_VAR); assert_eq!( @@ -290,47 +291,47 @@ mod tests { ); } - fn json_round_trip(text: &'static str) -> Result, failure::Error> { + async fn json_round_trip(text: &'static str) -> Result, failure::Error> { let client = ipfs_api::IpfsClient::default(); let resolver = super::LinkResolver::from(client.clone()); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - let link = runtime.block_on(client.add(text.as_bytes())).unwrap().hash; - runtime.block_on( - LinkResolver::json_stream(&resolver, &Link { link: link.clone() }) - .and_then(|stream| stream.map(|sv| sv.value).collect()), - ) + let link = client.add(text.as_bytes()).await.unwrap().hash; + + LinkResolver::json_stream(&resolver, &Link { link: link.clone() }) + .and_then(|stream| stream.map(|sv| sv.value).collect()) + .compat() + .await } - #[test] - fn read_json_stream() { - let values = json_round_trip("\"with newline\"\n"); + #[tokio::test] + async fn read_json_stream() { + let values = json_round_trip("\"with newline\"\n").await; assert_eq!(vec![json!("with newline")], values.unwrap()); - let values = json_round_trip("\"without newline\""); + let values = json_round_trip("\"without newline\"").await; assert_eq!(vec![json!("without newline")], values.unwrap()); - let values = json_round_trip("\"two\" \n \"things\""); + let values = json_round_trip("\"two\" \n \"things\"").await; assert_eq!(vec![json!("two"), json!("things")], values.unwrap()); - let values = json_round_trip("\"one\"\n \"two\" \n [\"bad\" \n \"split\"]"); + let values = json_round_trip("\"one\"\n \"two\" \n [\"bad\" \n \"split\"]").await; assert_eq!( "EOF while parsing a list at line 4 column 0: ' [\"bad\" \n'", values.unwrap_err().to_string() ); } - #[test] - fn ipfs_map_file_size() { + #[tokio::test] + async fn ipfs_map_file_size() { let file = "\"small test string that trips the size restriction\""; env::set_var(MAX_IPFS_MAP_FILE_SIZE_VAR, (file.len() - 1).to_string()); - let err = json_round_trip(file).unwrap_err(); + let err = json_round_trip(file).await.unwrap_err(); env::remove_var(MAX_IPFS_MAP_FILE_SIZE_VAR); assert!(err.to_string().contains(" is too large")); - let values = json_round_trip(file); + let values = json_round_trip(file).await; assert_eq!( vec!["small test string that trips the size restriction"], values.unwrap() diff --git a/core/src/subgraph/instance_manager.rs b/core/src/subgraph/instance_manager.rs index 4ac4e1dc3e2..40c76b9a54e 100644 --- a/core/src/subgraph/instance_manager.rs +++ b/core/src/subgraph/instance_manager.rs @@ -236,7 +236,8 @@ impl SubgraphInstanceManager { // Subgraph instance shutdown senders let instances: SharedInstanceKeepAliveMap = Default::default(); - tokio::spawn(receiver.for_each(move |event| { + // Blocking due to store interactions. Won't be blocking after #905. + graph::spawn_blocking(receiver.compat().try_for_each(move |event| { use self::SubgraphAssignmentProviderEvent::*; match event { @@ -303,7 +304,7 @@ impl SubgraphInstanceManager { } }; - Ok(()) + futures03::future::ok(()) })); } @@ -418,14 +419,11 @@ impl SubgraphInstanceManager { // forward; this is easier than updating the existing block stream. // // This task has many calls to the store, so mark it as `blocking`. - let subgraph_runner = - graph::util::futures::blocking(loop_fn(ctx, move |ctx| run_subgraph(ctx))).then( - move |res| { - subgraph_metrics_unregister.unregister(registry); - future::result(res) - }, - ); - tokio::spawn(subgraph_runner); + let subgraph_runner = loop_fn(ctx, move |ctx| run_subgraph(ctx)).then(move |res| { + subgraph_metrics_unregister.unregister(registry); + future::result(res) + }); + graph::spawn_blocking(subgraph_runner.compat()); Ok(()) } diff --git a/core/src/subgraph/registrar.rs b/core/src/subgraph/registrar.rs index 59c50a72557..6cdb58555bd 100644 --- a/core/src/subgraph/registrar.rs +++ b/core/src/subgraph/registrar.rs @@ -111,8 +111,9 @@ where // Deploy named subgraphs found in store self.start_assigned_subgraphs().and_then(move |()| { - // Spawn a task to handle assignment events - tokio::spawn(future::lazy(move || { + // Spawn a task to handle assignment events. + // Blocking due to store interactions. Won't be blocking after #905. + graph::spawn_blocking( assignment_event_stream .map_err(SubgraphAssignmentProviderError::Unknown) .map_err(CancelableError::Error) @@ -130,7 +131,8 @@ where panic!("assignment event stream failed: {}", e); } }) - })); + .compat(), + ); Ok(()) }) @@ -249,17 +251,18 @@ where // started. We wait for the spawned tasks to complete by giving // each a `sender` and waiting for all of them to be dropped, so // the receiver terminates without receiving anything. - let (sender, receiver) = tokio::sync::mpsc::channel::<()>(1); + let (sender, receiver) = futures::sync::mpsc::channel::<()>(1); for id in subgraph_ids { let sender = sender.clone(); - tokio::spawn( - graph::util::futures::blocking(start_subgraph( - id, - &*provider, - logger.clone(), - )) - .map(move |()| drop(sender)) - .map_err(|()| unreachable!()), + let provider = provider.clone(); + let logger = logger.clone(); + + // Blocking due to store interactions. Won't be blocking after #905. + graph::spawn_blocking( + start_subgraph(id, &*provider, logger) + .map(move |()| drop(sender)) + .map_err(|()| unreachable!()) + .compat(), ); } drop(sender); diff --git a/core/tests/tests.rs b/core/tests/tests.rs index 0beae79c097..971ce7c1c2a 100644 --- a/core/tests/tests.rs +++ b/core/tests/tests.rs @@ -1,9 +1,5 @@ -extern crate graph; -extern crate graph_core; -extern crate graph_mock; -extern crate ipfs_api; -extern crate semver; -extern crate walkdir; +#![allow(dead_code)] +#![allow(unused_imports)] use ipfs_api::IpfsClient; use walkdir::WalkDir; @@ -12,7 +8,6 @@ use std::collections::HashMap; use std::fs::read_to_string; use std::io::Cursor; use std::time::Duration; -use std::time::Instant; use graph::mock::MockEthereumAdapter; use graph::prelude::*; @@ -22,21 +17,23 @@ use graph_mock::MockStore; use test_store::LOGGER; -use crate::tokio::timer::Delay; - /// Adds subgraph located in `test/subgraphs/`, replacing "link to" placeholders /// in the subgraph manifest with links to files just added into a local IPFS /// daemon on port 5001. fn add_subgraph_to_ipfs( - client: Arc, + client: IpfsClient, subgraph: &str, ) -> impl Future { /// Adds string to IPFS and returns link of the form `/ipfs/`. - fn add(client: &IpfsClient, data: String) -> impl Future { - client - .add(Cursor::new(data)) - .map(|res| format!("/ipfs/{}", res.hash)) - .map_err(|err| format_err!("error adding to IPFS {}", err)) + fn add(client: IpfsClient, data: String) -> impl Future { + Box::pin(async move { + client + .add(Cursor::new(data)) + .map_ok(|res| format!("/ipfs/{}", res.hash)) + .map_err(|err| format_err!("error adding to IPFS {}", err)) + .await + }) + .compat() } let dir = format!("tests/subgraphs/{}", subgraph); @@ -54,16 +51,16 @@ fn add_subgraph_to_ipfs( { let client = client.clone(); ipfs_upload = Box::new(ipfs_upload.and_then(move |subgraph_string| { - add(&client, read_to_string(file.path()).unwrap()).map(move |link| { + add(client.clone(), read_to_string(file.path()).unwrap()).map(move |link| { subgraph_string.replace( &format!("link to {}", file.file_name().to_str().unwrap()), - &format!("/ipfs/{}", link), + &link, ) }) })) } let add_client = client.clone(); - ipfs_upload.and_then(move |subgraph_string| add(&add_client, subgraph_string)) + ipfs_upload.and_then(move |subgraph_string| add(add_client, subgraph_string)) } #[ignore] @@ -240,167 +237,169 @@ fn added_subgraph_id_eq( } } +#[tokio::test] #[ignore] -#[test] -fn subgraph_provider_events() { - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - runtime - .block_on(future::lazy(|| { - let logger = LOGGER.clone(); - let logger_factory = LoggerFactory::new(logger.clone(), None); - let ipfs = Arc::new(IpfsClient::default()); - let resolver = Arc::new(LinkResolver::from(IpfsClient::default())); - let store = Arc::new(MockStore::new()); - let stores: HashMap> = vec![store.clone()] - .into_iter() - .map(|s| ("mainnet".to_string(), s)) - .collect(); - let mock_ethereum_adapter = - Arc::new(MockEthereumAdapter::default()) as Arc; - let ethereum_adapters: HashMap> = - vec![mock_ethereum_adapter] - .into_iter() - .map(|e| ("mainnet".to_string(), e)) - .collect(); - let graphql_runner = Arc::new(graph_core::GraphQlRunner::new(&logger, store.clone())); - let mut provider = graph_core::SubgraphAssignmentProvider::new( - &logger_factory, - resolver.clone(), - store.clone(), - graphql_runner.clone(), - ); - let provider_events = provider.take_event_stream().unwrap(); - let node_id = NodeId::new("test").unwrap(); +#[cfg(any())] +async fn subgraph_provider_events() { + let logger = LOGGER.clone(); + let logger_factory = LoggerFactory::new(logger.clone(), None); + let ipfs = IpfsClient::default(); + let resolver = Arc::new(LinkResolver::from(IpfsClient::default())); + let store = Arc::new(MockStore::new(vec![])); + let stores: HashMap> = vec![store.clone()] + .into_iter() + .map(|s| ("mainnet".to_string(), s)) + .collect(); + let mock_ethereum_adapter = + Arc::new(MockEthereumAdapter::default()) as Arc; + let ethereum_adapters: HashMap> = vec![mock_ethereum_adapter] + .into_iter() + .map(|e| ("mainnet".to_string(), e)) + .collect(); + let graphql_runner = Arc::new(graph_core::GraphQlRunner::new(&logger, store.clone())); + let mut provider = graph_core::SubgraphAssignmentProvider::new( + &logger_factory, + resolver.clone(), + store.clone(), + graphql_runner.clone(), + ); + let provider_events = provider.take_event_stream().unwrap(); + let node_id = NodeId::new("test").unwrap(); + + let registrar = graph_core::SubgraphRegistrar::new( + &logger_factory, + resolver.clone(), + Arc::new(provider), + store.clone(), + stores, + ethereum_adapters, + node_id.clone(), + SubgraphVersionSwitchingMode::Instant, + ); + registrar + .start() + .and_then(move |_| { + add_subgraph_to_ipfs(ipfs.clone(), "two-datasources") + .join(add_subgraph_to_ipfs(ipfs, "dummy")) + }) + .and_then(move |(subgraph1_link, subgraph2_link)| { + let registrar = Arc::new(registrar); + let subgraph1_id = + SubgraphDeploymentId::new(subgraph1_link.trim_start_matches("/ipfs/")).unwrap(); + let subgraph2_id = + SubgraphDeploymentId::new(subgraph2_link.trim_start_matches("/ipfs/")).unwrap(); + let subgraph_name = SubgraphName::new("subgraph").unwrap(); + + // Prepare the clones + let registrar_clone1 = registrar; + let registrar_clone2 = registrar_clone1.clone(); + let registrar_clone3 = registrar_clone1.clone(); + let registrar_clone4 = registrar_clone1.clone(); + let registrar_clone5 = registrar_clone1.clone(); + let registrar_clone6 = registrar_clone1.clone(); + let subgraph1_id_clone1 = subgraph1_id; + let subgraph1_id_clone2 = subgraph1_id_clone1.clone(); + let subgraph2_id_clone1 = subgraph2_id; + let subgraph2_id_clone2 = subgraph2_id_clone1.clone(); + let subgraph_name_clone1 = subgraph_name; + let subgraph_name_clone2 = subgraph_name_clone1.clone(); + let subgraph_name_clone3 = subgraph_name_clone1.clone(); + let subgraph_name_clone4 = subgraph_name_clone1.clone(); + let subgraph_name_clone5 = subgraph_name_clone1.clone(); + let node_id_clone1 = node_id; + let node_id_clone2 = node_id_clone1.clone(); + + // Deploying to non-existant subgraph is an error. + registrar_clone1 + .create_subgraph_version( + subgraph_name_clone1.clone(), + subgraph1_id_clone1.clone(), + node_id_clone1.clone(), + ) + .then(move |result| { + assert!(result.is_err()); - let registrar = graph_core::SubgraphRegistrar::new( - &logger_factory, - resolver.clone(), - Arc::new(provider), - store.clone(), - stores, - ethereum_adapters, - node_id.clone(), - SubgraphVersionSwitchingMode::Instant, - ); - registrar - .start() + // Create subgraph + registrar_clone1.create_subgraph(subgraph_name_clone1.clone()) + }) .and_then(move |_| { - add_subgraph_to_ipfs(ipfs.clone(), "two-datasources") - .join(add_subgraph_to_ipfs(ipfs, "dummy")) + // Deploy + registrar_clone2.create_subgraph_version( + subgraph_name_clone2.clone(), + subgraph1_id_clone1.clone(), + node_id_clone1.clone(), + ) }) - .and_then(move |(subgraph1_link, subgraph2_link)| { - let registrar = Arc::new(registrar); - let subgraph1_id = - SubgraphDeploymentId::new(subgraph1_link.trim_start_matches("/ipfs/")) - .unwrap(); - let subgraph2_id = - SubgraphDeploymentId::new(subgraph2_link.trim_start_matches("/ipfs/")) - .unwrap(); - let subgraph_name = SubgraphName::new("subgraph").unwrap(); - - // Prepare the clones - let registrar_clone1 = registrar; - let registrar_clone2 = registrar_clone1.clone(); - let registrar_clone3 = registrar_clone1.clone(); - let registrar_clone4 = registrar_clone1.clone(); - let registrar_clone5 = registrar_clone1.clone(); - let registrar_clone6 = registrar_clone1.clone(); - let subgraph1_id_clone1 = subgraph1_id; - let subgraph1_id_clone2 = subgraph1_id_clone1.clone(); - let subgraph2_id_clone1 = subgraph2_id; - let subgraph2_id_clone2 = subgraph2_id_clone1.clone(); - let subgraph_name_clone1 = subgraph_name; - let subgraph_name_clone2 = subgraph_name_clone1.clone(); - let subgraph_name_clone3 = subgraph_name_clone1.clone(); - let subgraph_name_clone4 = subgraph_name_clone1.clone(); - let subgraph_name_clone5 = subgraph_name_clone1.clone(); - let node_id_clone1 = node_id; - let node_id_clone2 = node_id_clone1.clone(); - - // Deploying to non-existant subgraph is an error. - registrar_clone1 - .create_subgraph_version( - subgraph_name_clone1.clone(), - subgraph1_id_clone1.clone(), - node_id_clone1.clone(), - ) - .then(move |result| { - assert!(result.is_err()); - - // Create subgraph - registrar_clone1.create_subgraph(subgraph_name_clone1.clone()) - }) - .and_then(move |_| { - // Deploy - registrar_clone2.create_subgraph_version( - subgraph_name_clone2.clone(), - subgraph1_id_clone1.clone(), - node_id_clone1.clone(), - ) - }) - .and_then(move |()| { - // Give some time for event to be picked up. - Delay::new(Instant::now() + Duration::from_secs(2)) - .map_err(|_| panic!("time error")) - }) - .and_then(move |()| { - // Update - registrar_clone3.create_subgraph_version( - subgraph_name_clone3, - subgraph2_id_clone1, - node_id_clone2, - ) - }) - .and_then(move |()| { - // Give some time for event to be picked up. - Delay::new(Instant::now() + Duration::from_secs(2)) - .map_err(|_| panic!("time error")) - }) - .and_then(move |()| { - // Remove - registrar_clone4.remove_subgraph(subgraph_name_clone4) - }) - .and_then(move |()| { - // Give some time for event to be picked up. - Delay::new(Instant::now() + Duration::from_secs(2)) - .map_err(|_| panic!("time error")) - }) - .and_then(move |()| { - // Removing a subgraph that is not deployed is an error. - registrar_clone5.remove_subgraph(subgraph_name_clone5) - }) - .then(move |result| { - assert!(result.is_err()); - - provider_events - .take(4) - .collect() - .then(|result| Ok(result.unwrap())) - }) - .and_then(move |provider_events| -> Result<(), Error> { - // Keep named provider alive until after events have been collected - let _ = registrar_clone6; - - // Assert that the expected events were sent. - assert_eq!(provider_events.len(), 4); - assert!(provider_events - .iter() - .any(|event| added_subgraph_id_eq(event, &subgraph1_id_clone2))); - assert!(provider_events - .iter() - .any(|event| added_subgraph_id_eq(event, &subgraph2_id_clone2))); - assert!(provider_events.iter().any(|event| event - == &SubgraphAssignmentProviderEvent::SubgraphStop( - subgraph1_id_clone2.clone() - ))); - assert!(provider_events.iter().any(|event| event - == &SubgraphAssignmentProviderEvent::SubgraphStop( - subgraph2_id_clone2.clone() - ))); - Ok(()) - }) + .and_then(move |()| { + // Give some time for event to be picked up. + tokio::time::delay_for(Duration::from_secs(2)) + .never_error() + .map_err(|_| unreachable!()) + .compat() }) - .then(|result| -> Result<(), ()> { Ok(result.unwrap()) }) - })) + .and_then(move |()| { + // Update + registrar_clone3.create_subgraph_version( + subgraph_name_clone3, + subgraph2_id_clone1, + node_id_clone2, + ) + }) + .and_then(move |()| { + // Give some time for event to be picked up. + tokio::time::delay_for(Duration::from_secs(2)) + .never_error() + .map_err(|_| unreachable!()) + .compat() + }) + .and_then(move |()| { + // Remove + registrar_clone4.remove_subgraph(subgraph_name_clone4) + }) + .and_then(move |()| { + // Give some time for event to be picked up. + tokio::time::delay_for(Duration::from_secs(2)) + .never_error() + .map_err(|_| unreachable!()) + .compat() + }) + .and_then(move |()| { + // Removing a subgraph that is not deployed is an error. + registrar_clone5.remove_subgraph(subgraph_name_clone5) + }) + .then(move |result| { + assert!(result.is_err()); + + provider_events + .take(4) + .collect() + .then(|result| Ok(result.unwrap())) + }) + .and_then(move |provider_events| -> Result<(), Error> { + // Keep named provider alive until after events have been collected + let _ = registrar_clone6; + + // Assert that the expected events were sent. + assert_eq!(provider_events.len(), 4); + assert!(provider_events + .iter() + .any(|event| added_subgraph_id_eq(event, &subgraph1_id_clone2))); + assert!(provider_events + .iter() + .any(|event| added_subgraph_id_eq(event, &subgraph2_id_clone2))); + assert!(provider_events.iter().any(|event| event + == &SubgraphAssignmentProviderEvent::SubgraphStop( + subgraph1_id_clone2.clone() + ))); + assert!(provider_events.iter().any(|event| event + == &SubgraphAssignmentProviderEvent::SubgraphStop( + subgraph2_id_clone2.clone() + ))); + Ok(()) + }) + }) + .then(|result| -> Result<(), ()> { Ok(result.unwrap()) }) + .compat() + .await .unwrap(); } diff --git a/graph/Cargo.toml b/graph/Cargo.toml index b15df49fbf8..f0584674fc4 100644 --- a/graph/Cargo.toml +++ b/graph/Cargo.toml @@ -8,7 +8,7 @@ bigdecimal = { version = "0.0.14", features = ["serde"] } diesel = { version = "1.4.3", features = ["postgres", "serde_json", "numeric", "r2d2"] } chrono = "0.4" isatty = "0.1" -reqwest = "0.9" +reqwest = "0.10" # master contains changes such as # https://github.com/paritytech/ethabi/pull/140, which upstream does not want @@ -19,10 +19,7 @@ ethabi = { git = "https://github.com/graphprotocol/ethabi.git", branch = "master hex = "0.4.0" futures = "0.1.21" graphql-parser = "0.2.3" -# We're using the latest ipfs-api for the HTTPS support that was merged in -# https://github.com/ferristseng/rust-ipfs-api/commit/55902e98d868dcce047863859caf596a629d10ec -# but has not been released yet. -ipfs-api = { git = "https://github.com/ferristseng/rust-ipfs-api", branch = "master", features = ["hyper-tls"] } +ipfs-api = { version = "0.6.0-rc", features = ["hyper-tls"] } parity-wasm = "0.40" failure = "0.1.6" lazy_static = "1.2.0" @@ -41,14 +38,12 @@ slog-envlogger = "2.1.0" slog-term = "2.4.2" petgraph = "0.4.13" tiny-keccak = "1.5.0" -tokio = "0.1.22" -tokio-executor = "0.1.5" -tokio-retry = "0.2" -tokio-timer = "0.2.11" -tokio-threadpool = "0.1.14" +tokio = { version = "0.2.9", features = ["stream", "rt-threaded", "rt-util", "blocking", "time", "sync", "macros", "test-util"] } +tokio-retry = { git = "https://github.com/graphprotocol/rust-tokio-retry", branch = "update-to-tokio-02" } url = "1.7.2" prometheus = "0.7.0" priority-queue = "0.6.0" +futures03 = { version = "0.3.1", package = "futures", features = ["compat"] } # Our fork contains a small but hacky patch. web3 = { git = "https://github.com/graphprotocol/rust-web3", branch = "master" } diff --git a/graph/src/components/link_resolver.rs b/graph/src/components/link_resolver.rs index 3f43e7e63ca..d75108efefa 100644 --- a/graph/src/components/link_resolver.rs +++ b/graph/src/components/link_resolver.rs @@ -1,8 +1,8 @@ use failure; +use futures::prelude::*; use serde_json::Value; use slog::Logger; use std::time::Duration; -use tokio::prelude::*; use crate::data::subgraph::Link; diff --git a/graph/src/components/store.rs b/graph/src/components/store.rs index 8b8baa1e708..8f9d8124d55 100644 --- a/graph/src/components/store.rs +++ b/graph/src/components/store.rs @@ -577,7 +577,7 @@ where let mut pending_event: Option = None; let mut source = self.source.fuse(); let mut had_err = false; - let mut delay = tokio_timer::Delay::new(Instant::now() + interval); + let mut delay = tokio::time::delay_for(interval).unit_error().compat(); let logger = logger.clone(); let source = Box::new(poll_fn(move || -> Poll, ()> { @@ -599,12 +599,12 @@ where // Check if interval has passed since the last time we sent something. // If it has, start a new delay timer - let should_send = match delay.poll() { + let should_send = match futures::future::Future::poll(&mut delay) { Ok(Async::NotReady) => false, // Timer errors are harmless. Treat them as if the timer had // become ready. Ok(Async::Ready(())) | Err(_) => { - delay = tokio_timer::Delay::new(Instant::now() + interval); + delay = tokio::time::delay_for(interval).unit_error().compat(); true } }; diff --git a/graph/src/data/subgraph/mod.rs b/graph/src/data/subgraph/mod.rs index 8ab0dd08290..781dc5484bd 100644 --- a/graph/src/data/subgraph/mod.rs +++ b/graph/src/data/subgraph/mod.rs @@ -1,6 +1,7 @@ use ethabi::Contract; use failure; use failure::{Error, SyncFailure}; +use futures::prelude::*; use futures::stream; use parity_wasm; use parity_wasm::elements::Module; @@ -12,7 +13,6 @@ use std::fmt; use std::ops::Deref; use std::str::FromStr; use std::sync::Arc; -use tokio::prelude::*; use web3::types::{Address, H256}; use crate::components::link_resolver::LinkResolver; @@ -917,7 +917,7 @@ impl UnresolvedSubgraphManifest { // and skip to 0.0.4 to avoid ambiguity. Ok(ref ver) if *ver <= semver::Version::new(0, 0, 3) => {} _ => { - return Box::new(future::err(format_err!( + return Box::new(futures::future::err(format_err!( "This Graph Node only supports manifest spec versions <= 0.0.2, but subgraph `{}` uses `{}`", id, diff --git a/graph/src/ext/futures.rs b/graph/src/ext/futures.rs index 7ca77d8dca3..60947bf1d1d 100644 --- a/graph/src/ext/futures.rs +++ b/graph/src/ext/futures.rs @@ -1,8 +1,11 @@ use failure::Error; +use futures::future::Fuse; +use futures::prelude::{Future, Poll, Stream}; use futures::sync::oneshot; +use futures03::compat::{Compat01As03, Future01CompatExt}; use std::fmt; use std::sync::{Arc, Mutex, Weak}; -use tokio::prelude::{future::Fuse, Future, Poll, Stream}; +use std::time::Duration; /// A cancelable stream or future. /// @@ -208,6 +211,8 @@ pub trait FutureExtension: Future + Sized { guard: &impl Canceler, on_cancel: C, ) -> Cancelable; + + fn timeout(self, dur: Duration) -> tokio::time::Timeout>; } impl FutureExtension for F { @@ -224,6 +229,10 @@ impl FutureExtension for F { on_cancel, } } + + fn timeout(self, dur: Duration) -> tokio::time::Timeout> { + tokio::time::timeout(dur, self.compat()) + } } #[derive(Debug)] diff --git a/graph/src/lib.rs b/graph/src/lib.rs index 92c31e83093..69f624e3a47 100644 --- a/graph/src/lib.rs +++ b/graph/src/lib.rs @@ -19,6 +19,10 @@ pub mod mock { pub use crate::components::store::MockStore; } +/// Wrapper for spawning tasks that abort on panic, which is our default. +mod task_spawn; +pub use task_spawn::{spawn, spawn_blocking, spawn_blocking_allow_panic}; + /// A prelude that makes all system component traits and data types available. /// /// Add the following code to import all traits and data types listed below at once. @@ -30,6 +34,13 @@ pub mod prelude { pub use bigdecimal; pub use ethabi; pub use failure::{self, bail, err_msg, format_err, Error, Fail, SyncFailure}; + pub use futures::future; + pub use futures::prelude::*; + pub use futures::stream; + pub use futures03; + pub use futures03::compat::{Future01CompatExt, Sink01CompatExt, Stream01CompatExt}; + pub use futures03::future::{FutureExt as _, TryFutureExt}; + pub use futures03::stream::{StreamExt as _, TryStreamExt}; pub use hex; pub use serde_derive::{Deserialize, Serialize}; pub use serde_json; @@ -39,9 +50,6 @@ pub mod prelude { pub use std::sync::Arc; pub use tiny_keccak; pub use tokio; - pub use tokio::prelude::*; - pub use tokio_executor; - pub use tokio_timer; pub use web3; pub use crate::components::ethereum::{ @@ -115,5 +123,5 @@ pub mod prelude { ComponentLoggerConfig, ElasticComponentLoggerConfig, LoggerFactory, }; pub use crate::log::split::split_logger; - pub use crate::util::futures::retry; + pub use crate::util::futures::{retry, TimeoutError}; } diff --git a/graph/src/log/elastic.rs b/graph/src/log/elastic.rs index 4ad8d298318..f8340f57dcd 100644 --- a/graph/src/log/elastic.rs +++ b/graph/src/log/elastic.rs @@ -6,16 +6,14 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use chrono::prelude::{SecondsFormat, Utc}; -use futures::future; -use futures::{Future, Stream}; +use futures03::TryFutureExt; use reqwest; -use reqwest::r#async::Client; +use reqwest::Client; use serde::ser::Serializer as SerdeSerializer; use serde::Serialize; use serde_json::json; use slog::*; use slog_async; -use tokio::timer::Interval; /// General configuration parameters for Elasticsearch logging. #[derive(Clone, Debug)] @@ -184,20 +182,18 @@ impl ElasticDrain { } fn periodically_flush_logs(&self) { + use futures03::stream::StreamExt; + let flush_logger = self.error_logger.clone(); - let interval_error_logger = self.error_logger.clone(); let logs = self.logs.clone(); let config = self.config.clone(); - tokio::spawn( - Interval::new_interval(self.config.flush_interval) - .map_err(move |e| { - error!( - interval_error_logger, - "Error in Elasticsearch logger flush interval: {}", e - ); - }) - .for_each(move |_| { + crate::task_spawn::spawn(tokio::time::interval(self.config.flush_interval).for_each( + move |_| { + let logs = logs.clone(); + let config = config.clone(); + let flush_logger = flush_logger.clone(); + async move { let logs_to_send = { let mut logs = logs.lock().unwrap(); let logs_to_send = (*logs).clone(); @@ -208,8 +204,7 @@ impl ElasticDrain { // Do nothing if there are no logs to flush if logs_to_send.is_empty() { - return Box::new(future::ok(())) - as Box + Send>; + return; } trace!( @@ -266,28 +261,29 @@ impl ElasticDrain { // Send batch of logs to Elasticsearch let client = Client::new(); let logger_for_err = flush_logger.clone(); - Box::new( - client - .post(batch_url) - .header("Content-Type", "application/json") - .basic_auth( - config.general.username.clone().unwrap_or("".into()), - config.general.password.clone(), - ) - .body(batch_body) - .send() - .and_then(|response| response.error_for_status()) - .map(|_| ()) - .map_err(move |e| { - // Log if there was a problem sending the logs - error!( - logger_for_err, - "Failed to send logs to Elasticsearch: {}", e - ); - }), - ) - }), - ); + + client + .post(batch_url) + .header("Content-Type", "application/json") + .basic_auth( + config.general.username.clone().unwrap_or("".into()), + config.general.password.clone(), + ) + .body(batch_body) + .send() + .and_then(|response| async { response.error_for_status() }) + .map_ok(|_| ()) + .unwrap_or_else(move |e| { + // Log if there was a problem sending the logs + error!( + logger_for_err, + "Failed to send logs to Elasticsearch: {}", e + ); + }) + .await; + } + }, + )); } } diff --git a/graph/src/task_spawn.rs b/graph/src/task_spawn.rs new file mode 100644 index 00000000000..04665429e51 --- /dev/null +++ b/graph/src/task_spawn.rs @@ -0,0 +1,34 @@ +use futures03::executor::block_on; +use futures03::future::{FutureExt, TryFutureExt}; +use std::future::Future as Future03; +use std::panic::AssertUnwindSafe; +use tokio::task::JoinHandle; + +fn abort_on_panic( + f: impl Future03 + Send + 'static, +) -> impl Future03 { + // We're crashing, unwind safety doesn't matter. + AssertUnwindSafe(f).catch_unwind().unwrap_or_else(|_| { + println!("Panic in tokio task, aborting!"); + std::process::exit(1) + }) +} + +/// Aborts on panic. +pub fn spawn(f: impl Future03 + Send + 'static) -> JoinHandle { + tokio::spawn(abort_on_panic(f)) +} + +/// Aborts on panic. +pub fn spawn_blocking( + f: impl Future03 + Send + 'static, +) -> JoinHandle { + tokio::task::spawn_blocking(move || block_on(abort_on_panic(f))) +} + +/// Panics result in an `Err` in `JoinHandle`. +pub fn spawn_blocking_allow_panic( + f: impl Future03 + Send + 'static, +) -> JoinHandle { + tokio::task::spawn_blocking(move || block_on(f)) +} diff --git a/graph/src/util/futures.rs b/graph/src/util/futures.rs index 3f126561376..66388659592 100644 --- a/graph/src/util/futures.rs +++ b/graph/src/util/futures.rs @@ -1,12 +1,12 @@ +use crate::ext::futures::FutureExtension; +use failure::Fail; +use futures::prelude::*; use slog::{debug, trace, Logger}; use std::fmt::Debug; use std::marker::PhantomData; use std::sync::Arc; use std::time::Duration; -use tokio::prelude::*; -use tokio::timer::timeout; use tokio_retry::strategy::{jitter, ExponentialBackoff}; -use tokio_retry::Error as RetryError; use tokio_retry::Retry; /// Generic helper function for retrying async operations with built-in logging. @@ -27,7 +27,7 @@ use tokio_retry::Retry; /// ``` /// # extern crate graph; /// # use graph::prelude::*; -/// # use tokio::timer::timeout; +/// # use tokio::time::timeout; /// # /// # type Memes = (); // the memes are a lie :( /// # @@ -35,7 +35,7 @@ use tokio_retry::Retry; /// # future::ok(()) /// # } /// -/// fn async_function(logger: Logger) -> impl Future> { +/// fn async_function(logger: Logger) -> impl Future> { /// // Retry on error /// retry("download memes", &logger) /// .no_limit() // Retry forever @@ -70,7 +70,7 @@ pub struct RetryConfig { impl RetryConfig where I: Send, - E: Send, + E: Debug + Send + Send + Sync + 'static, { /// Sets a function used to determine if a retry is needed. /// Note: timeouts always trigger a retry. @@ -143,14 +143,16 @@ pub struct RetryConfigWithTimeout { impl RetryConfigWithTimeout where I: Debug + Send, - E: Debug + Send, + E: Debug + Send + Send + Sync + 'static, { /// Rerun the provided function as many times as needed. - pub fn run(self, try_it: F) -> impl Future> + pub fn run(self, try_it: F) -> impl Future> where F: Fn() -> R + Send, R: Future + Send, { + use futures03::future::TryFutureExt; + let operation_name = self.inner.operation_name; let logger = self.inner.logger.clone(); let condition = self.inner.condition; @@ -166,7 +168,13 @@ where condition, log_after, limit_opt, - move || try_it().timeout(timeout), + move || { + try_it() + .timeout(timeout) + .map_err(|_| TimeoutError::Elapsed) + .and_then(|res| futures03::future::ready(res.map_err(TimeoutError::Inner))) + .compat() + }, ) } } @@ -180,7 +188,7 @@ impl RetryConfigNoTimeout { pub fn run(self, try_it: F) -> impl Future where I: Debug + Send, - E: Debug + Send, + E: Debug + Send + Sync + 'static, F: Fn() -> R + Send, R: Future + Send, { @@ -198,12 +206,8 @@ impl RetryConfigNoTimeout { condition, log_after, limit_opt, - move || { - try_it().map_err(|e| { - // No timeout, so all errors are inner errors - timeout::Error::inner(e) - }) - }, + // No timeout, so all errors are inner errors + move || try_it().map_err(TimeoutError::Inner), ) .map_err(|e| { // No timeout, so all errors are inner errors @@ -212,6 +216,30 @@ impl RetryConfigNoTimeout { } } +#[derive(Fail, Debug)] +pub enum TimeoutError { + #[fail(display = "{:?}", _0)] + Inner(T), + #[fail(display = "Timeout elapsed")] + Elapsed, +} + +impl TimeoutError { + pub fn is_elapsed(&self) -> bool { + match self { + TimeoutError::Inner(_) => false, + TimeoutError::Elapsed => true, + } + } + + pub fn into_inner(self) -> Option { + match self { + TimeoutError::Inner(x) => Some(x), + TimeoutError::Elapsed => None, + } + } +} + fn run_retry( operation_name: String, logger: Logger, @@ -219,12 +247,12 @@ fn run_retry( log_after: u64, limit_opt: Option, try_it_with_timeout: F, -) -> impl Future> + Send +) -> impl Future> + Send where I: Debug + Send, - E: Debug + Send, + E: Debug + Send + Sync + 'static, F: Fn() -> R + Send, - R: Future> + Send, + R: Future> + Send, { let condition = Arc::new(condition); @@ -242,11 +270,6 @@ where .err() .map(|e| e.is_elapsed()) .unwrap_or(false); - let is_timer_err = result_with_timeout - .as_ref() - .err() - .map(|e| e.is_timer()) - .unwrap_or(false); if is_elapsed { if attempt_count >= log_after { @@ -260,10 +283,6 @@ where // Wrap in Err to force retry Err(result_with_timeout) - } else if is_timer_err { - // Should never happen - let timer_error = result_with_timeout.unwrap_err().into_timer().unwrap(); - panic!("tokio timer error: {}", timer_error) } else { // Any error must now be an inner error. // Unwrap the inner error so that the predicate doesn't need to think @@ -283,10 +302,10 @@ where } // Wrap in Err to force retry - Err(result.map_err(timeout::Error::inner)) + Err(result.map_err(TimeoutError::Inner)) } else { // Wrap in Ok to prevent retry - Ok(result.map_err(timeout::Error::inner)) + Ok(result.map_err(TimeoutError::Inner)) } } }) @@ -296,8 +315,7 @@ where // The outer Ok/Err is only used for retry control flow. match retry_result { Ok(r) => r, - Err(RetryError::OperationError(r)) => r, - Err(RetryError::TimerError(e)) => panic!("tokio timer error: {}", e), + Err(e) => e, } }) } @@ -382,119 +400,118 @@ where mod tests { use super::*; + use futures::future; + use futures03::compat::Future01CompatExt; use slog::o; use std::sync::Mutex; #[test] fn test() { let logger = Logger::root(::slog::Discard, o!()); - let mut runtime = ::tokio::runtime::Runtime::new().unwrap(); - - let result = runtime.block_on(future::lazy(move || { - let c = Mutex::new(0); - retry("test", &logger) - .no_logging() - .no_limit() - .no_timeout() - .run(move || { - let mut c_guard = c.lock().unwrap(); - *c_guard += 1; - - if *c_guard >= 10 { - future::ok(*c_guard) - } else { - future::err(()) - } - }) - })); + let mut runtime = tokio::runtime::Builder::new().enable_all().build().unwrap(); + + let result = runtime.block_on( + future::lazy(move || { + let c = Mutex::new(0); + retry("test", &logger) + .no_logging() + .no_limit() + .no_timeout() + .run(move || { + let mut c_guard = c.lock().unwrap(); + *c_guard += 1; + + if *c_guard >= 10 { + future::ok(*c_guard) + } else { + future::err(()) + } + }) + }) + .compat(), + ); assert_eq!(result, Ok(10)); } #[test] fn limit_reached() { let logger = Logger::root(::slog::Discard, o!()); - let mut runtime = ::tokio::runtime::Runtime::new().unwrap(); - - let result = runtime.block_on(future::lazy(move || { - let c = Mutex::new(0); - retry("test", &logger) - .no_logging() - .limit(5) - .no_timeout() - .run(move || { - let mut c_guard = c.lock().unwrap(); - *c_guard += 1; - - if *c_guard >= 10 { - future::ok(*c_guard) - } else { - future::err(*c_guard) - } - }) - })); + let mut runtime = tokio::runtime::Builder::new().enable_all().build().unwrap(); + + let result = runtime.block_on( + future::lazy(move || { + let c = Mutex::new(0); + retry("test", &logger) + .no_logging() + .limit(5) + .no_timeout() + .run(move || { + let mut c_guard = c.lock().unwrap(); + *c_guard += 1; + + if *c_guard >= 10 { + future::ok(*c_guard) + } else { + future::err(*c_guard) + } + }) + }) + .compat(), + ); assert_eq!(result, Err(5)); } #[test] fn limit_not_reached() { let logger = Logger::root(::slog::Discard, o!()); - let mut runtime = ::tokio::runtime::Runtime::new().unwrap(); - - let result = runtime.block_on(future::lazy(move || { - let c = Mutex::new(0); - retry("test", &logger) - .no_logging() - .limit(20) - .no_timeout() - .run(move || { - let mut c_guard = c.lock().unwrap(); - *c_guard += 1; - - if *c_guard >= 10 { - future::ok(*c_guard) - } else { - future::err(*c_guard) - } - }) - })); + let mut runtime = tokio::runtime::Builder::new().enable_all().build().unwrap(); + + let result = runtime.block_on( + future::lazy(move || { + let c = Mutex::new(0); + retry("test", &logger) + .no_logging() + .limit(20) + .no_timeout() + .run(move || { + let mut c_guard = c.lock().unwrap(); + *c_guard += 1; + + if *c_guard >= 10 { + future::ok(*c_guard) + } else { + future::err(*c_guard) + } + }) + }) + .compat(), + ); assert_eq!(result, Ok(10)); } - #[test] - fn custom_when() { + #[tokio::test] + async fn custom_when() { let logger = Logger::root(::slog::Discard, o!()); - let mut runtime = ::tokio::runtime::Runtime::new().unwrap(); - - let result = runtime.block_on(future::lazy(move || { - let c = Mutex::new(0); - - retry("test", &logger) - .when(|result| result.unwrap() < 10) - .no_logging() - .limit(20) - .no_timeout() - .run(move || { - let mut c_guard = c.lock().unwrap(); - *c_guard += 1; - if *c_guard > 30 { - future::err(()) - } else { - future::ok(*c_guard) - } - }) - })); - assert_eq!(result, Ok(10)); - } -} + let c = Mutex::new(0); + + let result = retry("test", &logger) + .when(|result| result.unwrap() < 10) + .no_logging() + .limit(20) + .no_timeout() + .run(move || { + let mut c_guard = c.lock().unwrap(); + *c_guard += 1; + if *c_guard > 30 { + future::err(()) + } else { + future::ok(*c_guard) + } + }) + .compat() + .await + .unwrap(); -/// Convenient way to annotate a future with `tokio_threadpool::blocking`. -/// -/// Panics if called from outside a tokio runtime. -pub fn blocking(mut f: impl Future) -> impl Future { - future::poll_fn(move || match tokio_threadpool::blocking(|| f.poll()) { - Ok(Async::NotReady) | Ok(Async::Ready(Ok(Async::NotReady))) => Ok(Async::NotReady), - Ok(Async::Ready(Ok(Async::Ready(t)))) => Ok(Async::Ready(t)), - Ok(Async::Ready(Err(e))) => Err(e), - Err(_) => panic!("not inside a tokio thread pool"), - }) + assert_eq!(result, 10); + } } diff --git a/graphql/tests/query.rs b/graphql/tests/query.rs index 4982bfe1bb9..be7dfe17b4c 100644 --- a/graphql/tests/query.rs +++ b/graphql/tests/query.rs @@ -775,8 +775,8 @@ fn query_complexity() { }; } -#[test] -fn query_complexity_subscriptions() { +#[tokio::test] +async fn query_complexity_subscriptions() { let logger = Logger::root(slog::Discard, o!()); let store_resolver = StoreResolver::new(&logger, STORE.clone()); @@ -1152,8 +1152,8 @@ fn cannot_filter_by_derved_relationship_fields() { }; } -#[test] -fn subscription_gets_result_even_without_events() { +#[tokio::test] +async fn subscription_gets_result_even_without_events() { let logger = Logger::root(slog::Discard, o!()); let store_resolver = StoreResolver::new(&logger, STORE.clone()); @@ -1182,9 +1182,12 @@ fn subscription_gets_result_even_without_events() { // Execute the subscription and expect at least one result to be // available in the result stream let stream = execute_subscription(&Subscription { query }, options).unwrap(); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - let results = runtime - .block_on(stream.take(1).collect().timeout(Duration::from_secs(3))) + let results = stream + .take(1) + .collect() + .timeout(Duration::from_secs(3)) + .await + .unwrap() .unwrap(); assert_eq!(results.len(), 1); diff --git a/node/Cargo.toml b/node/Cargo.toml index 6888ae44ec6..830187d2aca 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -6,16 +6,11 @@ edition = "2018" [dependencies] clap = "2.33.0" env_logger = "0.7.1" -futures = "0.1.21" git-testament = "0.1" graphql-parser = "0.2.3" -http = "0.1" prometheus = "0.7" - -# We're using the latest ipfs-api for the HTTPS support that was merged in -# https://github.com/ferristseng/rust-ipfs-api/commit/55902e98d868dcce047863859caf596a629d10ec -# but has not been released yet. -ipfs-api = { git = "https://github.com/ferristseng/rust-ipfs-api", branch = "master", features = ["hyper-tls"] } +futures = { version = "0.3.1", features = ["compat"] } +ipfs-api = { version = "0.6.0-rc", features = ["hyper-tls"] } lazy_static = "1.2.0" url = "1.7.1" crossbeam-channel = "0.3.9" diff --git a/node/src/main.rs b/node/src/main.rs index b0ad1d87a93..fd4ab314046 100644 --- a/node/src/main.rs +++ b/node/src/main.rs @@ -1,5 +1,4 @@ use clap::{App, Arg}; -use futures::sync::mpsc; use git_testament::{git_testament, render_testament}; use ipfs_api::IpfsClient; use lazy_static::lazy_static; @@ -8,6 +7,7 @@ use std::collections::HashMap; use std::env; use std::str::FromStr; use std::time::Duration; +use tokio::sync::mpsc; use graph::components::forward; use graph::log::logger; @@ -29,8 +29,6 @@ use graph_server_websocket::SubscriptionServer as GraphQLSubscriptionServer; use graph_store_postgres::connection_pool::create_connection_pool; use graph_store_postgres::{Store as DieselStore, StoreConfig}; -use tokio_timer::timer::Timer; - lazy_static! { // Default to an Ethereum reorg threshold to 50 blocks static ref REORG_THRESHOLD: u64 = env::var("ETHEREUM_REORG_THRESHOLD") @@ -45,12 +43,6 @@ lazy_static! { .map(|s| u64::from_str(&s) .unwrap_or_else(|_| panic!("failed to parse env var ETHEREUM_ANCESTOR_COUNT"))) .unwrap_or(50); - - static ref TOKIO_THREAD_COUNT: usize = env::var("GRAPH_TOKIO_THREAD_COUNT") - .ok() - .map(|s| usize::from_str(&s) - .unwrap_or_else(|_| panic!("failed to parse env var GRAPH_TOKIO_THREAD_COUNT"))) - .unwrap_or(100); } git_testament!(TESTAMENT); @@ -62,59 +54,10 @@ enum ConnectionType { WS, } -fn main() { - use std::sync::Mutex; - use tokio::runtime; - - // Create components for tokio context: multi-threaded runtime, executor - // context on the runtime, and Timer handle. - // - // Configure the runtime to shutdown after a panic. - let runtime: Arc>> = Arc::new(Mutex::new(None)); - let handler_runtime = runtime.clone(); - *runtime.lock().unwrap() = Some( - runtime::Builder::new() - .core_threads(*TOKIO_THREAD_COUNT) - .panic_handler(move |_| { - let runtime = handler_runtime.clone(); - std::thread::spawn(move || { - if let Some(runtime) = runtime.lock().unwrap().take() { - // Try to cleanly shutdown the runtime, but - // unconditionally exit after a while. - std::thread::spawn(|| { - std::thread::sleep(Duration::from_millis(3000)); - std::process::exit(1); - }); - runtime - .shutdown_now() - .wait() - .expect("Failed to shutdown Tokio Runtime"); - println!("Runtime cleaned up and shutdown successfully"); - } - }); - }) - .build() - .unwrap(), - ); - - let mut executor = runtime.lock().unwrap().as_ref().unwrap().executor(); - let mut enter = tokio_executor::enter() - .expect("Failed to enter runtime executor, multiple executors at once"); - let timer = Timer::default(); - let timer_handle = timer.handle(); - - // Setup runtime context with defaults and run the main application - tokio_executor::with_default(&mut executor, &mut enter, |enter| { - tokio_timer::with_default(&timer_handle, enter, |enter| { - enter - .block_on(future::lazy(|| async_main())) - .expect("Failed to run main function"); - }) - }); -} - -fn async_main() -> impl Future + Send + 'static { +#[tokio::main] +async fn main() { env_logger::init(); + // Setup CLI using Clap, provide general info and capture postgres url let matches = App::new("graph-node") .version("0.1.0") @@ -426,13 +369,14 @@ fn async_main() -> impl Future + Send + 'static { }; // Test the IPFS client by getting the version from the IPFS daemon - let ipfs_test = ipfs_client.version(); + let ipfs_test = ipfs_client.clone(); let ipfs_ok_logger = logger.clone(); let ipfs_err_logger = logger.clone(); let ipfs_address_for_ok = ipfs_address.clone(); let ipfs_address_for_err = ipfs_address.clone(); - tokio::spawn( + graph::spawn(async move { ipfs_test + .version() .map_err(move |e| { error!( ipfs_err_logger, @@ -441,14 +385,15 @@ fn async_main() -> impl Future + Send + 'static { ); panic!("Failed to connect to IPFS: {}", e); }) - .map(move |_| { + .map_ok(move |_| { info!( ipfs_ok_logger, "Successfully connected to IPFS node at: {}", SafeDisplay(ipfs_address_for_ok) ); - }), - ); + }) + .await + }); // Convert the client into a link resolver let link_resolver = Arc::new(LinkResolver::from(ipfs_client)); @@ -506,8 +451,8 @@ fn async_main() -> impl Future + Send + 'static { let stores_eth_adapters = eth_adapters.clone(); let contention_logger = logger.clone(); - tokio::spawn( - futures::stream::futures_ordered(stores_eth_adapters.into_iter().map( + graph::spawn( + futures::stream::FuturesOrdered::from_iter(stores_eth_adapters.into_iter().map( |(network_name, eth_adapter)| { info!( logger, "Connecting to Ethereum..."; @@ -516,8 +461,10 @@ fn async_main() -> impl Future + Send + 'static { eth_adapter .net_identifiers(&logger) .map(|network_identifier| (network_name, network_identifier)) + .compat() }, )) + .compat() .map_err(move |e| { error!(stores_error_logger, "Was a valid Ethereum node provided?"); panic!("Failed to connect to Ethereum node: {}", e); @@ -593,11 +540,17 @@ fn async_main() -> impl Future + Send + 'static { format!("network/{}", network_subgraph).into(), None, ); - tokio::spawn(indexer.take_event_stream().unwrap().for_each(|_| { - // For now we simply ignore these events; we may later use them - // to drive subgraph indexing - Ok(()) - })); + graph::spawn( + indexer + .take_event_stream() + .unwrap() + .for_each(|_| { + // For now we simply ignore these events; we may later use them + // to drive subgraph indexing + Ok(()) + }) + .compat(), + ); }) }; @@ -629,7 +582,7 @@ fn async_main() -> impl Future + Send + 'static { .expect("failed to create Ethereum block ingestor"); // Run the Ethereum block ingestor in the background - tokio::spawn(block_ingestor.into_polling_stream()); + graph::spawn(block_ingestor.into_polling_stream().compat()); }); } @@ -665,7 +618,11 @@ fn async_main() -> impl Future + Send + 'static { ); // Forward subgraph events from the subgraph provider to the subgraph instance manager - tokio::spawn(forward(&mut subgraph_provider, &subgraph_instance_manager).unwrap()); + graph::spawn( + forward(&mut subgraph_provider, &subgraph_instance_manager) + .unwrap() + .compat(), + ); // Check version switching mode environment variable let version_switching_mode = SubgraphVersionSwitchingMode::parse( @@ -686,9 +643,12 @@ fn async_main() -> impl Future + Send + 'static { node_id.clone(), version_switching_mode, )); - tokio::spawn(subgraph_registrar.start().then(|start_result| { - Ok(start_result.expect("failed to initialize subgraph provider")) - })); + graph::spawn( + subgraph_registrar + .start() + .map_err(|e| panic!("failed to initialize subgraph provider {}", e)) + .compat(), + ); // Start admin JSON-RPC server. let json_rpc_server = JsonRpcServer::serve( @@ -718,64 +678,68 @@ fn async_main() -> impl Future + Send + 'static { let subgraph_id = SubgraphDeploymentId::new(hash) .expect("Subgraph hash must be a valid IPFS hash"); - tokio::spawn( + graph::spawn( subgraph_registrar .create_subgraph(name.clone()) - .then(|result| { - Ok(result.expect("Failed to create subgraph from `--subgraph` flag")) - }) .and_then(move |_| { subgraph_registrar.create_subgraph_version(name, subgraph_id, node_id) }) - .then(|result| { - Ok(result.expect("Failed to deploy subgraph from `--subgraph` flag")) - }), + .map_err(|e| { + panic!("Failed to deploy subgraph from `--subgraph` flag: {}", e) + }) + .compat(), ); } // Serve GraphQL queries over HTTP - tokio::spawn( + graph::spawn( graphql_server .serve(http_port, ws_port) - .expect("Failed to start GraphQL query server"), + .expect("Failed to start GraphQL query server") + .compat(), ); // Serve GraphQL subscriptions over WebSockets - tokio::spawn( + graph::spawn( subscription_server .serve(ws_port) - .expect("Failed to start GraphQL subscription server"), + .expect("Failed to start GraphQL subscription server") + .compat(), ); // Run the index node server - tokio::spawn( + graph::spawn( index_node_server .serve(index_node_port) - .expect("Failed to start index node server"), + .expect("Failed to start index node server") + .compat(), ); - tokio::spawn( + graph::spawn( metrics_server .serve(metrics_port) - .expect("Failed to start metrics server"), + .expect("Failed to start metrics server") + .compat(), ); future::ok(()) - }), + }) + .compat(), ); // Periodically check for contention in the tokio threadpool. First spawn a // task that simply responds to "ping" requests. Then spawn a separate // thread to periodically ping it and check responsiveness. let (ping_send, ping_receive) = mpsc::channel::>(1); - tokio::spawn( - ping_receive - .for_each(move |pong_send| pong_send.clone().send(()).map(|_| ()).map_err(|_| ())), - ); + graph::spawn(ping_receive.for_each(move |pong_send| { + async move { + let _ = pong_send.clone().send(()); + } + })); std::thread::spawn(move || loop { std::thread::sleep(Duration::from_secs(1)); let (pong_send, pong_receive) = crossbeam_channel::bounded(1); - if ping_send.clone().send(pong_send).wait().is_err() { + if futures::executor::block_on(ping_send.clone().send(pong_send)).is_err() { debug!(contention_logger, "Shutting down contention checker thread"); break; } @@ -792,7 +756,7 @@ fn async_main() -> impl Future + Send + 'static { } }); - future::empty() + futures::future::pending::<()>().await; } /// Parses an Ethereum connection string and returns the network name and Ethereum adapter. diff --git a/runtime/wasm/Cargo.toml b/runtime/wasm/Cargo.toml index 0a154cc5d71..fb56f137290 100644 --- a/runtime/wasm/Cargo.toml +++ b/runtime/wasm/Cargo.toml @@ -17,13 +17,11 @@ semver = "0.9.0" parity-wasm = "0.40" lazy_static = "1.4" uuid = { version = "0.8.1", features = ["v4"] } +tokio01 = { package = "tokio", version = "0.1.7"} [dev-dependencies] graphql-parser = "0.2.3" graph-core = { path = "../../core" } graph-mock = { path = "../../mock" } test-store = { path = "../../store/test-store" } -# We're using the latest ipfs-api for the HTTPS support that was merged in -# https://github.com/ferristseng/rust-ipfs-api/commit/55902e98d868dcce047863859caf596a629d10ec -# but has not been released yet. -ipfs-api = { git = "https://github.com/ferristseng/rust-ipfs-api", branch = "master", features = ["hyper-tls"] } +ipfs-api = { version = "0.6.0-rc", features = ["hyper-tls"] } diff --git a/runtime/wasm/src/host.rs b/runtime/wasm/src/host.rs index d1aa7fc15b9..187c728985e 100644 --- a/runtime/wasm/src/host.rs +++ b/runtime/wasm/src/host.rs @@ -79,7 +79,13 @@ where subgraph_id: SubgraphDeploymentId, metrics: Arc, ) -> Result, Error> { - crate::mapping::spawn_module(parsed_module, logger, subgraph_id, metrics) + crate::mapping::spawn_module( + parsed_module, + logger, + subgraph_id, + metrics, + tokio::runtime::Handle::current(), + ) } fn build( diff --git a/runtime/wasm/src/host_exports.rs b/runtime/wasm/src/host_exports.rs index 46fd5b4ccbf..54b4463aab9 100644 --- a/runtime/wasm/src/host_exports.rs +++ b/runtime/wasm/src/host_exports.rs @@ -1,6 +1,5 @@ use crate::UnresolvedContractCall; use ethabi::{Address, Token}; -use futures::sync::oneshot; use graph::components::ethereum::*; use graph::components::store::EntityKey; use graph::data::store; @@ -204,7 +203,6 @@ impl HostExports { /// Returns `Ok(None)` if the call was reverted. pub(crate) fn ethereum_call( &self, - task_sink: &mut impl Sink + Send>>, logger: &Logger, block: &LightEthereumBlock, unresolved_call: UnresolvedContractCall, @@ -274,10 +272,9 @@ impl HostExports { let eth_adapter = self.ethereum_adapter.clone(); let logger1 = logger.clone(); let call_cache = self.call_cache.clone(); - let result = match block_on( - task_sink, - future::lazy(move || eth_adapter.contract_call(&logger1, call, call_cache)), - ) { + let result = match block_on(future::lazy(move || { + eth_adapter.contract_call(&logger1, call, call_cache) + })) { Ok(tokens) => Ok(Some(tokens)), Err(EthereumContractCallError::Revert(reason)) => { info!(logger, "Contract call reverted"; "reason" => reason); @@ -380,11 +377,9 @@ impl HostExports { pub(crate) fn ipfs_cat( &self, logger: &Logger, - task_sink: &mut impl Sink + Send>>, link: String, ) -> Result, HostExportError> { block_on( - task_sink, self.link_resolver .cat(logger, &Link { link }) .map_err(HostExportError), @@ -398,28 +393,20 @@ impl HostExports { // which is identical to `module` when it was first started. The signature // of the callback must be `callback(JSONValue, Value)`, and the `userData` // parameter is passed to the callback without any changes - pub(crate) fn ipfs_map( + pub(crate) fn ipfs_map( &self, - module: &WasmiModule, + module: &WasmiModule, link: String, callback: &str, user_data: store::Value, flags: Vec, - ) -> Result, HostExportError> - where - U: Sink + Send>> - + Clone - + Send - + Sync - + 'static, - { + ) -> Result, HostExportError> { const JSON_FLAG: &str = "json"; if !flags.contains(&JSON_FLAG.to_string()) { return Err(HostExportError(format!("Flags must contain 'json'"))); } let host_metrics = module.host_metrics.clone(); - let task_sink = module.task_sink.clone(); let valid_module = module.valid_module.clone(); let ctx = module.ctx.clone(); let callback = callback.to_owned(); @@ -433,7 +420,6 @@ impl HostExports { let mut last_log = Instant::now(); let logger = ctx.logger.new(o!("ipfs_map" => link.clone())); block_on( - &mut task_sink.clone(), self.link_resolver .json_stream(&Link { link }) .and_then(move |stream| { @@ -442,7 +428,6 @@ impl HostExports { let module = WasmiModule::from_valid_module_with_ctx( valid_module.clone(), ctx.clone(), - task_sink.clone(), host_metrics.clone(), )?; let result = @@ -693,16 +678,11 @@ fn test_string_to_h160_with_0x() { } fn block_on( - task_sink: &mut impl Sink + Send>>, future: impl Future + Send + 'static, ) -> Result { - let (return_sender, return_receiver) = oneshot::channel(); - task_sink - .send(Box::new(future.then(|res| { - return_sender.send(res).map_err(|_| unreachable!()) - }))) + // We don't know if the task is blocking or not, but use `blocking` to be cautious. + graph::spawn_blocking_allow_panic(future.compat()) + .compat() .wait() - .map_err(|_| panic!("task receiver dropped")) - .unwrap(); - return_receiver.wait().expect("`return_sender` dropped") + .unwrap() } diff --git a/runtime/wasm/src/mapping.rs b/runtime/wasm/src/mapping.rs index fe2c4d01b09..e1582b7e337 100644 --- a/runtime/wasm/src/mapping.rs +++ b/runtime/wasm/src/mapping.rs @@ -14,6 +14,7 @@ pub fn spawn_module( logger: Logger, subgraph_id: SubgraphDeploymentId, host_metrics: Arc, + runtime: tokio::runtime::Handle, ) -> Result, Error> { let valid_module = Arc::new(ValidModule::new(parsed_module)?); @@ -23,82 +24,76 @@ pub fn spawn_module( // wasmi modules are not `Send` therefore they cannot be scheduled by // the regular tokio executor, so we create a dedicated thread. // - // This thread can spawn tasks on the runtime by sending them to - // `task_receiver`. - let (task_sender, task_receiver) = mpsc::channel(100); - tokio::spawn(task_receiver.for_each(tokio::spawn)); - - // Spawn a dedicated thread for the runtime. - // // In case of failure, this thread may panic or simply terminate, // dropping the `mapping_request_receiver` which ultimately causes the // subgraph to fail the next time it tries to handle an event. let conf = thread::Builder::new().name(format!("mapping-{}-{}", &subgraph_id, uuid::Uuid::new_v4())); conf.spawn(move || { - // Pass incoming triggers to the WASM module and return entity changes; - // Stop when canceled because all RuntimeHosts and their senders were dropped. - match mapping_request_receiver - .map_err(|()| unreachable!()) - .for_each(move |request| -> Result<(), Error> { - let MappingRequest { - ctx, - trigger, - result_sender, - } = request; - - // Start the WASMI module runtime. - let section = host_metrics.stopwatch.start_section("module_init"); - let module = WasmiModule::from_valid_module_with_ctx( - valid_module.clone(), - ctx, - task_sender.clone(), - host_metrics.clone(), - )?; - section.end(); - - let section = host_metrics.stopwatch.start_section("run_handler"); - let result = match trigger { - MappingTrigger::Log { - transaction, - log, - params, - handler, - } => module.handle_ethereum_log( - handler.handler.as_str(), - transaction, - log, - params, - ), - MappingTrigger::Call { - transaction, - call, - inputs, - outputs, - handler, - } => module.handle_ethereum_call( - handler.handler.as_str(), - transaction, - call, - inputs, - outputs, - ), - MappingTrigger::Block { handler } => { - module.handle_ethereum_block(handler.handler.as_str()) - } - }; - section.end(); - - result_sender - .send((result, future::ok(Instant::now()))) - .map_err(|_| err_msg("WASM module result receiver dropped.")) - }) - .wait() - { - Ok(()) => debug!(logger, "Subgraph stopped, WASM runtime thread terminated"), - Err(e) => debug!(logger, "WASM runtime thread terminated abnormally"; + runtime.enter(|| { + // Pass incoming triggers to the WASM module and return entity changes; + // Stop when canceled because all RuntimeHosts and their senders were dropped. + match mapping_request_receiver + .map_err(|()| unreachable!()) + .for_each(move |request| -> Result<(), Error> { + let MappingRequest { + ctx, + trigger, + result_sender, + } = request; + + // Start the WASMI module runtime. + let section = host_metrics.stopwatch.start_section("module_init"); + let module = WasmiModule::from_valid_module_with_ctx( + valid_module.clone(), + ctx, + host_metrics.clone(), + )?; + section.end(); + + let section = host_metrics.stopwatch.start_section("run_handler"); + let result = match trigger { + MappingTrigger::Log { + transaction, + log, + params, + handler, + } => module.handle_ethereum_log( + handler.handler.as_str(), + transaction, + log, + params, + ), + MappingTrigger::Call { + transaction, + call, + inputs, + outputs, + handler, + } => module.handle_ethereum_call( + handler.handler.as_str(), + transaction, + call, + inputs, + outputs, + ), + MappingTrigger::Block { handler } => { + module.handle_ethereum_block(handler.handler.as_str()) + } + }; + section.end(); + + result_sender + .send((result, future::ok(Instant::now()))) + .map_err(|_| err_msg("WASM module result receiver dropped.")) + }) + .wait() + { + Ok(()) => debug!(logger, "Subgraph stopped, WASM runtime thread terminated"), + Err(e) => debug!(logger, "WASM runtime thread terminated abnormally"; "error" => e.to_string()), - } + } + }) }) .map(|_| ()) .map_err(|e| format_err!("Spawning WASM runtime thread failed: {}", e))?; diff --git a/runtime/wasm/src/module/mod.rs b/runtime/wasm/src/module/mod.rs index dac75c0bc6d..7cbc0b9146f 100644 --- a/runtime/wasm/src/module/mod.rs +++ b/runtime/wasm/src/module/mod.rs @@ -93,13 +93,12 @@ fn format_wasmi_error(e: Error) -> String { } /// A WASM module based on wasmi that powers a subgraph runtime. -pub(crate) struct WasmiModule { +pub(crate) struct WasmiModule { pub module: ModuleRef, memory: MemoryRef, pub ctx: MappingContext, pub(crate) valid_module: Arc, - pub(crate) task_sink: U, pub(crate) host_metrics: Arc, // Time when the current handler began processing. @@ -119,19 +118,11 @@ pub(crate) struct WasmiModule { timeout_checkpoint_count: u64, } -impl WasmiModule -where - U: Sink + Send>> - + Clone - + Send - + Sync - + 'static, -{ +impl WasmiModule { /// Creates a new wasmi module pub fn from_valid_module_with_ctx( valid_module: Arc, ctx: MappingContext, - task_sink: U, host_metrics: Arc, ) -> Result { // Build import resolver @@ -163,7 +154,6 @@ where memory, ctx, valid_module: valid_module.clone(), - task_sink, host_metrics, start_time: Instant::now(), running_start: true, @@ -328,14 +318,7 @@ where } } -impl AscHeap for WasmiModule -where - U: Sink + Send>> - + Clone - + Send - + Sync - + 'static, -{ +impl AscHeap for WasmiModule { fn raw_new(&mut self, bytes: &[u8]) -> Result { // We request large chunks from the AssemblyScript allocator to use as arenas that we // manage directly. @@ -375,14 +358,7 @@ where impl HostError for HostExportError where E: fmt::Debug + fmt::Display + Send + Sync + 'static {} // Implementation of externals. -impl WasmiModule -where - U: Sink + Send>> - + Clone - + Send - + Sync - + 'static, -{ +impl WasmiModule { fn gas(&mut self) -> Result, Trap> { // This function is called so often that the overhead of calling `Instant::now()` every // time would be significant, so we spread out the checks. @@ -494,12 +470,10 @@ where &mut self, call: UnresolvedContractCall, ) -> Result, Trap> { - let result = self.ctx.host_exports.ethereum_call( - &mut self.task_sink, - &mut self.ctx.logger, - &self.ctx.block, - call, - )?; + let result = + self.ctx + .host_exports + .ethereum_call(&mut self.ctx.logger, &self.ctx.block, call)?; Ok(Some(match result { Some(tokens) => RuntimeValue::from(self.asc_new(tokens.as_slice())), None => RuntimeValue::from(0), @@ -585,10 +559,7 @@ where /// function ipfs.cat(link: String): Bytes fn ipfs_cat(&mut self, link_ptr: AscPtr) -> Result, Trap> { let link = self.asc_get(link_ptr); - let ipfs_res = self - .ctx - .host_exports - .ipfs_cat(&self.ctx.logger, &mut self.task_sink, link); + let ipfs_res = self.ctx.host_exports.ipfs_cat(&self.ctx.logger, link); match ipfs_res { Ok(bytes) => { let bytes_obj: AscPtr = self.asc_new(&*bytes); @@ -956,14 +927,7 @@ where } } -impl Externals for WasmiModule -where - U: Sink + Send>> - + Clone - + Send - + Sync - + 'static, -{ +impl Externals for WasmiModule { fn invoke_index( &mut self, index: usize, diff --git a/runtime/wasm/src/module/test.rs b/runtime/wasm/src/module/test.rs index 42d3c6c9fca..ba5c32529bb 100644 --- a/runtime/wasm/src/module/test.rs +++ b/runtime/wasm/src/module/test.rs @@ -1,5 +1,4 @@ use ethabi::Token; -use futures::sync::mpsc::channel; use hex; use std::collections::HashMap; use std::env; @@ -27,13 +26,7 @@ fn test_valid_module_and_store( subgraph_id: &str, data_source: DataSource, ) -> ( - WasmiModule< - impl Sink + Send + 'static>> - + Clone - + Send - + Sync - + 'static, - >, + WasmiModule, Arc, ) { let store = STORE.clone(); @@ -63,14 +56,9 @@ fn test_valid_module_and_store( stopwatch_metrics, )); - let (task_sender, task_receiver) = channel(100); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - runtime.spawn(task_receiver.for_each(tokio::spawn)); - ::std::mem::forget(runtime); let module = WasmiModule::from_valid_module_with_ctx( Arc::new(ValidModule::new(data_source.mapping.runtime.as_ref().clone()).unwrap()), mock_context(deployment_id, data_source, store.clone()), - task_sender, host_metrics, ) .unwrap(); @@ -78,16 +66,7 @@ fn test_valid_module_and_store( (module, store) } -fn test_module( - subgraph_id: &str, - data_source: DataSource, -) -> WasmiModule< - impl Sink + Send + 'static>> - + Clone - + Send - + Sync - + 'static, -> { +fn test_module(subgraph_id: &str, data_source: DataSource) -> WasmiModule { test_valid_module_and_store(subgraph_id, data_source).0 } @@ -175,21 +154,14 @@ fn mock_context( store: Arc, ) -> MappingContext { MappingContext { - logger: Logger::root(slog::Discard, o!()), + logger: test_store::LOGGER.clone(), block: Default::default(), host_exports: Arc::new(mock_host_exports(subgraph_id, data_source, store)), state: BlockState::default(), } } -impl WasmiModule -where - U: Sink + Send>> - + Clone - + Send - + Sync - + 'static, -{ +impl WasmiModule { fn takes_val_returns_ptr

(&mut self, fn_name: &str, val: RuntimeValue) -> AscPtr

{ self.module .clone() @@ -298,27 +270,30 @@ fn json_conversions() { ); } -#[test] -fn ipfs_cat() { - let mut module = test_module("ipfsCat", mock_data_source("wasm_test/ipfs_cat.wasm")); - let ipfs = Arc::new(ipfs_api::IpfsClient::default()); +#[tokio::test] +async fn ipfs_cat() { + graph::spawn_blocking(async { + let ipfs = Arc::new(ipfs_api::IpfsClient::default()); + let hash = ipfs.add(Cursor::new("42")).await.unwrap().hash; - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - let hash = runtime.block_on(ipfs.add(Cursor::new("42"))).unwrap().hash; - let converted: AscPtr = module - .module - .clone() - .invoke_export( - "ipfsCatString", - &[RuntimeValue::from(module.asc_new(&hash))], - &mut module, - ) - .expect("call failed") - .expect("call returned nothing") - .try_into() - .expect("call did not return pointer"); - let data: String = module.asc_get(converted); - assert_eq!(data, "42"); + let mut module = test_module("ipfsCat", mock_data_source("wasm_test/ipfs_cat.wasm")); + let converted: AscPtr = module + .module + .clone() + .invoke_export( + "ipfsCatString", + &[RuntimeValue::from(module.asc_new(&hash))], + &mut module, + ) + .expect("call failed") + .expect("call returned nothing") + .try_into() + .expect("call did not return pointer"); + let data: String = module.asc_get(converted); + assert_eq!(data, "42"); + }) + .await + .unwrap(); } // The user_data value we use with calls to ipfs_map @@ -340,22 +315,25 @@ fn make_thing(subgraph_id: &str, id: &str, value: &str) -> (String, EntityModifi ) } -#[test] -fn ipfs_map() { +#[tokio::test(threaded_scheduler)] +async fn ipfs_map() { const BAD_IPFS_HASH: &str = "bad-ipfs-hash"; let ipfs = Arc::new(ipfs_api::IpfsClient::default()); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); let subgraph_id = "ipfsMap"; - let mut run_ipfs_map = move |json_string| -> Result, Error> { + let run_ipfs_map = move |json_string| { + let ipfs = ipfs.clone(); + let (mut module, store) = test_valid_module_and_store(subgraph_id, mock_data_source("wasm_test/ipfs_map.wasm")); let hash = if json_string == BAD_IPFS_HASH { "Qm".to_string() } else { - runtime - .block_on(ipfs.add(Cursor::new(json_string))) + graph::spawn(async move { ipfs.add(Cursor::new(json_string)).await }) + .compat() + .wait() + .unwrap() .unwrap() .hash }; @@ -392,10 +370,8 @@ fn ipfs_map() { // Valid JSON, but not what the callback expected; it will // fail on an assertion - let errmsg = run_ipfs_map(format!("{}\n[1,2]", str1)) - .unwrap_err() - .to_string(); - assert!(errmsg.contains("JSON value is not an object.")); + let err: Error = run_ipfs_map(format!("{}\n[1,2]", str1)).unwrap_err(); + assert!(err.to_string().contains("JSON value is not an object.")); // Malformed JSON let errmsg = run_ipfs_map(format!("{}\n[", str1)) @@ -420,14 +396,18 @@ fn ipfs_map() { assert!(errmsg.contains("api returned error")) } -#[test] -fn ipfs_fail() { - let mut module = test_module("ipfsFail", mock_data_source("wasm_test/ipfs_cat.wasm")); - - let hash = module.asc_new("invalid hash"); - assert!(module - .takes_ptr_returns_ptr::<_, AscString>("ipfsCat", hash,) - .is_null()); +#[tokio::test] +async fn ipfs_fail() { + graph::spawn_blocking(async { + let mut module = test_module("ipfsFail", mock_data_source("wasm_test/ipfs_cat.wasm")); + + let hash = module.asc_new("invalid hash"); + assert!(module + .takes_ptr_returns_ptr::<_, AscString>("ipfsCat", hash,) + .is_null()); + }) + .await + .unwrap(); } #[test] @@ -815,7 +795,7 @@ fn entity_store() { let subgraph_id = SubgraphDeploymentId::new("entityStore").unwrap(); test_store::insert_entities(subgraph_id, vec![("User", alex), ("User", steve)]).unwrap(); - let get_user = move |module: &mut WasmiModule<_>, id: &str| -> Option { + let get_user = move |module: &mut WasmiModule, id: &str| -> Option { let entity_ptr: AscPtr = module .module .clone() @@ -833,7 +813,7 @@ fn entity_store() { } }; - let load_and_set_user_name = |module: &mut WasmiModule<_>, id: &str, name: &str| { + let load_and_set_user_name = |module: &mut WasmiModule, id: &str, name: &str| { module .module .clone() diff --git a/server/http/Cargo.toml b/server/http/Cargo.toml index b280a6f6b34..86e8e84b75a 100644 --- a/server/http/Cargo.toml +++ b/server/http/Cargo.toml @@ -4,10 +4,11 @@ version = "0.17.1" edition = "2018" [dependencies] +failure = "0.1.6" futures = "0.1.21" graphql-parser = "0.2.3" -http = "0.1.18" -hyper = "0.12.35" +http = "0.2" +hyper = "0.13" serde = "1.0" graph = { path = "../../graph" } graph-graphql = { path = "../../graphql" } diff --git a/server/http/src/request.rs b/server/http/src/request.rs index 7eee677bafe..7422fcdff90 100644 --- a/server/http/src/request.rs +++ b/server/http/src/request.rs @@ -1,19 +1,19 @@ use graph::prelude::serde_json; use graphql_parser; -use hyper::Chunk; +use hyper::body::Bytes; use graph::components::server::query::GraphQLServerError; use graph::prelude::*; /// Future for a query parsed from an HTTP request. pub struct GraphQLRequest { - body: Chunk, + body: Bytes, schema: Arc, } impl GraphQLRequest { /// Creates a new GraphQLRequest future based on an HTTP request and a result sender. - pub fn new(body: Chunk, schema: Arc) -> Self { + pub fn new(body: Bytes, schema: Arc) -> Self { GraphQLRequest { body, schema } } } @@ -89,7 +89,7 @@ mod tests { fn rejects_invalid_json() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = GraphQLRequest::new(hyper::Chunk::from("!@#)%"), Arc::new(schema)); + let request = GraphQLRequest::new(hyper::body::Bytes::from("!@#)%"), Arc::new(schema)); request.wait().expect_err("Should reject invalid JSON"); } @@ -97,7 +97,7 @@ mod tests { fn rejects_json_without_query_field() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = GraphQLRequest::new(hyper::Chunk::from("{}"), Arc::new(schema)); + let request = GraphQLRequest::new(hyper::body::Bytes::from("{}"), Arc::new(schema)); request .wait() .expect_err("Should reject JSON without query field"); @@ -107,7 +107,8 @@ mod tests { fn rejects_json_with_non_string_query_field() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = GraphQLRequest::new(hyper::Chunk::from("{\"query\": 5}"), Arc::new(schema)); + let request = + GraphQLRequest::new(hyper::body::Bytes::from("{\"query\": 5}"), Arc::new(schema)); request .wait() .expect_err("Should reject JSON with a non-string query field"); @@ -117,8 +118,10 @@ mod tests { fn rejects_broken_queries() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = - GraphQLRequest::new(hyper::Chunk::from("{\"query\": \"foo\"}"), Arc::new(schema)); + let request = GraphQLRequest::new( + hyper::body::Bytes::from("{\"query\": \"foo\"}"), + Arc::new(schema), + ); request.wait().expect_err("Should reject broken queries"); } @@ -127,7 +130,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = GraphQLRequest::new( - hyper::Chunk::from("{\"query\": \"{ user { name } }\"}"), + hyper::body::Bytes::from("{\"query\": \"{ user { name } }\"}"), Arc::new(schema), ); let query = request.wait().expect("Should accept valid queries"); @@ -142,7 +145,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = GraphQLRequest::new( - hyper::Chunk::from( + hyper::body::Bytes::from( "\ {\ \"query\": \"{ user { name } }\", \ @@ -163,7 +166,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = GraphQLRequest::new( - hyper::Chunk::from( + hyper::body::Bytes::from( "\ {\ \"query\": \"{ user { name } }\", \ @@ -180,7 +183,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = GraphQLRequest::new( - hyper::Chunk::from( + hyper::body::Bytes::from( "\ {\ \"query\": \"{ user { name } }\", \ diff --git a/server/http/src/server.rs b/server/http/src/server.rs index 6756f532db5..ade839fa7eb 100644 --- a/server/http/src/server.rs +++ b/server/http/src/server.rs @@ -1,37 +1,19 @@ -use std::error::Error; -use std::fmt; use std::net::{Ipv4Addr, SocketAddrV4}; use hyper; +use hyper::service::make_service_fn; use hyper::Server; use crate::service::{GraphQLService, GraphQLServiceMetrics}; use graph::prelude::{GraphQLServer as GraphQLServerTrait, *}; /// Errors that may occur when starting the server. -#[derive(Debug)] +#[derive(Debug, Fail)] pub enum GraphQLServeError { + #[fail(display = "Bind error: {}", _0)] BindError(hyper::Error), } -impl Error for GraphQLServeError { - fn description(&self) -> &str { - "Failed to start the server" - } - - fn cause(&self) -> Option<&dyn Error> { - None - } -} - -impl fmt::Display for GraphQLServeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - GraphQLServeError::BindError(e) => write!(f, "Failed to bind GraphQL server: {}", e), - } - } -} - impl From for GraphQLServeError { fn from(err: hyper::Error) -> Self { GraphQLServeError::BindError(err) @@ -103,23 +85,22 @@ where let metrics = self.metrics.clone(); let store = self.store.clone(); let node_id = self.node_id.clone(); - let new_service = move || { - let service = GraphQLService::new( + let new_service = make_service_fn(move |_| { + futures03::future::ok::<_, Error>(GraphQLService::new( logger_for_service.clone(), metrics.clone(), graphql_runner.clone(), store.clone(), ws_port, node_id.clone(), - ); - future::ok::, hyper::Error>(service) - }; + )) + }); // Create a task to run the server and handle HTTP requests let task = Server::try_bind(&addr.into())? .serve(new_service) .map_err(move |e| error!(logger, "Server error"; "error" => format!("{}", e))); - Ok(Box::new(task)) + Ok(Box::new(task.compat())) } } diff --git a/server/http/src/service.rs b/server/http/src/service.rs index e2980bfeb68..6af776418b4 100644 --- a/server/http/src/service.rs +++ b/server/http/src/service.rs @@ -1,6 +1,10 @@ use std::collections::HashMap; +use std::convert::TryFrom; use std::fmt; use std::ops::Deref; +use std::pin::Pin; +use std::task::Context; +use std::task::Poll; use std::time::Instant; use graph::components::server::query::GraphQLServerError; @@ -65,9 +69,10 @@ impl GraphQLServiceMetrics { } } +pub type GraphQLServiceResult = Result, GraphQLServerError>; /// An asynchronous response to a GraphQL request. pub type GraphQLServiceResponse = - Box, Error = GraphQLServerError> + Send>; + Pin + Send>>; /// A Hyper Service that serves GraphQL over a POST / endpoint. #[derive(Debug)] @@ -122,126 +127,114 @@ where .replace("__WS_PORT__", format!("{}", self.ws_port).as_str()) } - fn index(&self) -> GraphQLServiceResponse { - let service = self.clone(); - + async fn index(self) -> GraphQLServiceResult { // Ask for two to find out if there is more than one let entity_query = SubgraphEntity::query().first(2); - Box::new( - future::result(self.store.find(entity_query)) - .map_err(|e| GraphQLServerError::InternalError(e.to_string())) - .and_then(move |mut subgraph_entities| -> GraphQLServiceResponse { - // If there is only one subgraph, redirect to it - match subgraph_entities.len() { - 0 => Box::new(future::ok( - Response::builder() - .status(200) - .body(Body::from(String::from("No subgraphs deployed yet"))) - .unwrap(), - )), - 1 => { - let subgraph_entity = subgraph_entities.pop().unwrap(); - let subgraph_name = subgraph_entity - .get("name") - .expect("subgraph entity without name"); - return service.handle_temp_redirect(&format!( - "/subgraphs/name/{}", - subgraph_name - )); - } - _ => Box::new(future::ok( - Response::builder() - .status(200) - .body(Body::from(String::from( - "Multiple subgraphs deployed. \ - Try /subgraphs/id/ or \ - /subgraphs/name/", - ))) - .unwrap(), - )), - } - }), - ) + let mut subgraph_entities = self + .store + .find(entity_query) + .map_err(|e| GraphQLServerError::InternalError(e.to_string()))?; + + // If there is only one subgraph, redirect to it + match subgraph_entities.len() { + 0 => Ok(Response::builder() + .status(200) + .body(Body::from(String::from("No subgraphs deployed yet"))) + .unwrap()), + 1 => { + let subgraph_entity = subgraph_entities.pop().unwrap(); + let subgraph_name = subgraph_entity + .get("name") + .expect("subgraph entity without name"); + let name = format!("/subgraphs/name/{}", subgraph_name); + self.handle_temp_redirect(name).await + } + _ => Ok(Response::builder() + .status(200) + .body(Body::from(String::from( + "Multiple subgraphs deployed. \ + Try /subgraphs/id/ or \ + /subgraphs/name/", + ))) + .unwrap()), + } } /// Serves a static file. fn serve_file(&self, contents: &'static str) -> GraphQLServiceResponse { - Box::new(future::ok( - Response::builder() + async move { + Ok(Response::builder() .status(200) .body(Body::from(contents)) - .unwrap(), - )) + .unwrap()) + } + .boxed() } /// Serves a dynamically created file. fn serve_dynamic_file(&self, contents: String) -> GraphQLServiceResponse { - Box::new(future::ok( - Response::builder() + async { + Ok(Response::builder() .status(200) .body(Body::from(contents)) - .unwrap(), - )) + .unwrap()) + } + .boxed() } fn handle_graphiql(&self) -> GraphQLServiceResponse { self.serve_dynamic_file(self.graphiql_html()) } - fn handle_graphql_query_by_name( - &self, + async fn handle_graphql_query_by_name( + self, subgraph_name: String, request: Request, - ) -> GraphQLServiceResponse { - let service = self.clone(); - - Box::new( - SubgraphName::new(subgraph_name.as_str()) - .map_err(|()| { - GraphQLServerError::ClientError(format!( - "Invalid subgraph name {:?}", - subgraph_name - )) - }) - .and_then(|subgraph_name| { - self.store - .resolve_subgraph_name_to_id(subgraph_name) - .map_err(|e| { - GraphQLServerError::InternalError(format!( - "Error resolving subgraph name: {}", - e - )) - }) - }) - .into_future() - .and_then(|subgraph_id_opt| { - subgraph_id_opt.ok_or(GraphQLServerError::ClientError( - "Subgraph name not found".to_owned(), - )) - }) - .and_then(move |subgraph_id| { - service.handle_graphql_query(subgraph_id, request.into_body()) - }), - ) + ) -> GraphQLServiceResult { + let subgraph_id = SubgraphName::new(subgraph_name.as_str()) + .map_err(|()| { + GraphQLServerError::ClientError(format!( + "Invalid subgraph name {:?}", + subgraph_name + )) + }) + .and_then(|subgraph_name| { + self.store + .resolve_subgraph_name_to_id(subgraph_name) + .map_err(|e| { + GraphQLServerError::InternalError(format!( + "Error resolving subgraph name: {}", + e + )) + }) + }) + .and_then(|subgraph_id_opt| { + subgraph_id_opt.ok_or(GraphQLServerError::ClientError( + "Subgraph name not found".to_owned(), + )) + })?; + + self.handle_graphql_query(subgraph_id, request.into_body()) + .await } fn handle_graphql_query_by_id( - &self, + self, id: String, request: Request, ) -> GraphQLServiceResponse { match SubgraphDeploymentId::new(id) { Err(()) => self.handle_not_found(), - Ok(id) => self.handle_graphql_query(id, request.into_body()), + Ok(id) => self.handle_graphql_query(id, request.into_body()).boxed(), } } - fn handle_graphql_query( - &self, + async fn handle_graphql_query( + self, id: SubgraphDeploymentId, request_body: Body, - ) -> GraphQLServiceResponse { + ) -> GraphQLServiceResult { let service = self.clone(); let logger = self.logger.clone(); let service_metrics = self.metrics.clone(); @@ -249,15 +242,13 @@ where match self.store.is_deployed(&id) { Err(e) => { - return Box::new(future::err(GraphQLServerError::InternalError( - e.to_string(), - ))); + return Err(GraphQLServerError::InternalError(e.to_string())); } Ok(false) => { - return Box::new(future::err(GraphQLServerError::ClientError(format!( + return Err(GraphQLServerError::ClientError(format!( "No data found for subgraph {}", id - )))); + ))); } Ok(true) => (), } @@ -265,102 +256,91 @@ where let schema = match self.store.api_schema(&id) { Ok(schema) => schema, Err(e) => { - return Box::new(future::err(GraphQLServerError::InternalError( - e.to_string(), - ))); + return Err(GraphQLServerError::InternalError(e.to_string())); } }; let start = Instant::now(); - Box::new( - request_body - .concat2() - .map_err(|_| GraphQLServerError::from("Failed to read request body")) - .and_then(move |body| GraphQLRequest::new(body, schema)) - .and_then(move |query| { - // Run the query using the query runner + hyper::body::to_bytes(request_body) + .map_err(|_| GraphQLServerError::from("Failed to read request body")) + .and_then(move |body| GraphQLRequest::new(body, schema).compat()) + .and_then(move |query| { + // Run the query using the query runner + tokio::task::block_in_place(|| { service .graphql_runner .run_query(query) .map_err(|e| GraphQLServerError::from(e)) + .compat() }) - .then( - move |result: Result| -> GraphQLResponse { - let elapsed = start.elapsed(); - match result { - Ok(_) => { - service_metrics.observe_query_execution_time( - elapsed.as_secs_f64(), - sd_id.deref().to_string(), - ); - info!( - logger, - "GraphQL query served"; - "subgraph_deployment" => sd_id.deref(), - "query_time_ms" => elapsed.as_millis(), - "code" => LogCode::GraphQlQuerySuccess, - ) - } - Err(ref e) => { - service_metrics.observe_query_execution_time( - elapsed.as_secs_f64(), - sd_id.deref().to_string(), - ); - error!( - logger, - "GraphQL query failed"; - "subgraph_deployment" => sd_id.deref(), - "error" => e.to_string(), - "query_time_ms" => elapsed.as_millis(), - "code" => LogCode::GraphQlQueryFailure, - ) - } - } - GraphQLResponse::new(result) - }, - ), - ) + }) + .then(move |result| { + service_metrics.observe_query_execution_time( + start.elapsed().as_secs_f64(), + sd_id.deref().to_string(), + ); + let elapsed = start.elapsed().as_millis(); + match result { + Ok(_) => info!( + logger, + "GraphQL query served"; + "subgraph_deployment" => sd_id.deref(), + "query_time_ms" => elapsed, + "code" => LogCode::GraphQlQuerySuccess, + ), + Err(ref e) => error!( + logger, + "GraphQL query failed"; + "subgraph_deployment" => sd_id.deref(), + "error" => e.to_string(), + "query_time_ms" => elapsed, + "code" => LogCode::GraphQlQueryFailure, + ), + } + GraphQLResponse::new(result).compat() + }) + .await } // Handles OPTIONS requests fn handle_graphql_options(&self, _request: Request) -> GraphQLServiceResponse { - Box::new(future::ok( - Response::builder() + async { + Ok(Response::builder() .status(200) .header("Access-Control-Allow-Origin", "*") .header("Access-Control-Allow-Headers", "Content-Type") .header("Access-Control-Allow-Methods", "GET, OPTIONS, POST") .body(Body::from("")) - .unwrap(), - )) + .unwrap()) + } + .boxed() } /// Handles 302 redirects - fn handle_temp_redirect(&self, destination: &str) -> GraphQLServiceResponse { - Box::new(future::result( - header::HeaderValue::from_str(destination) - .map_err(|_| GraphQLServerError::from("invalid characters in redirect URL")) - .map(|loc_header_val| { - Response::builder() - .status(StatusCode::FOUND) - .header(header::LOCATION, loc_header_val) - .body(Body::from("Redirecting...")) - .unwrap() - }), - )) + async fn handle_temp_redirect(self, destination: String) -> GraphQLServiceResult { + header::HeaderValue::try_from(destination) + .map_err(|_| GraphQLServerError::from("invalid characters in redirect URL")) + .map(|loc_header_val| { + Response::builder() + .status(StatusCode::FOUND) + .header(header::LOCATION, loc_header_val) + .body(Body::from("Redirecting...")) + .unwrap() + }) } /// Handles 404s. fn handle_not_found(&self) -> GraphQLServiceResponse { - Box::new(future::ok( - Response::builder() + async { + Ok(Response::builder() .status(StatusCode::NOT_FOUND) .body(Body::from("Not found")) - .unwrap(), - )) + .unwrap()) + } + .boxed() } - fn handle_call(&mut self, req: Request) -> GraphQLServiceResponse { + fn handle_call(self, req: Request) -> GraphQLServiceResponse { let method = req.method().clone(); let path = req.uri().path().to_owned(); @@ -374,7 +354,7 @@ where }; match (method, path_segments.as_slice()) { - (Method::GET, [""]) => self.index(), + (Method::GET, [""]) => self.index().boxed(), (Method::GET, ["graphiql.css"]) => { self.serve_file(include_str!("../assets/graphiql.css")) } @@ -394,24 +374,26 @@ where | (Method::GET, path @ ["subgraphs", "network", _, _]) | (Method::GET, path @ ["subgraphs"]) => { let dest = format!("/{}/graphql", path.join("/")); - self.handle_temp_redirect(&dest) + self.handle_temp_redirect(dest).boxed() } (Method::POST, &["subgraphs", "id", subgraph_id]) => { self.handle_graphql_query_by_id(subgraph_id.to_owned(), req) } (Method::OPTIONS, ["subgraphs", "id", _]) => self.handle_graphql_options(req), - (Method::POST, &["subgraphs", "name", subgraph_name]) => { - self.handle_graphql_query_by_name(subgraph_name.to_owned(), req) - } + (Method::POST, &["subgraphs", "name", subgraph_name]) => self + .handle_graphql_query_by_name(subgraph_name.to_owned(), req) + .boxed(), (Method::POST, ["subgraphs", "name", subgraph_name_part1, subgraph_name_part2]) => { let subgraph_name = format!("{}/{}", subgraph_name_part1, subgraph_name_part2); self.handle_graphql_query_by_name(subgraph_name, req) + .boxed() } (Method::POST, ["subgraphs", "network", subgraph_name_part1, subgraph_name_part2]) => { let subgraph_name = format!("network/{}/{}", subgraph_name_part1, subgraph_name_part2); self.handle_graphql_query_by_name(subgraph_name, req) + .boxed() } (Method::OPTIONS, ["subgraphs", "name", _]) @@ -429,60 +411,67 @@ where } } -impl Service for GraphQLService +impl Service> for GraphQLService where Q: GraphQlRunner, S: SubgraphDeploymentStore + Store, { - type ReqBody = Body; - type ResBody = Body; + type Response = Response; type Error = GraphQLServerError; type Future = GraphQLServiceResponse; - fn call(&mut self, req: Request) -> Self::Future { + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: Request) -> Self::Future { let logger = self.logger.clone(); + let service = self.clone(); // Returning Err here will prevent the client from receiving any response. // Instead, we generate a Response with an error code and return Ok - Box::new(self.handle_call(req).then(move |result| match result { - Ok(response) => Ok(response), - Err(err @ GraphQLServerError::Canceled(_)) => { - error!(logger, "GraphQLService call failed: {}", err); - - Ok(Response::builder() - .status(500) - .header("Content-Type", "text/plain") - .body(Body::from("Internal server error (operation canceled)")) - .unwrap()) - } - Err(err @ GraphQLServerError::ClientError(_)) => { - debug!(logger, "GraphQLService call failed: {}", err); - - Ok(Response::builder() - .status(400) - .header("Content-Type", "text/plain") - .body(Body::from(format!("Invalid request: {}", err))) - .unwrap()) - } - Err(err @ GraphQLServerError::QueryError(_)) => { - error!(logger, "GraphQLService call failed: {}", err); - - Ok(Response::builder() - .status(500) - .header("Content-Type", "text/plain") - .body(Body::from(format!("Query error: {}", err))) - .unwrap()) - } - Err(err @ GraphQLServerError::InternalError(_)) => { - error!(logger, "GraphQLService call failed: {}", err); - - Ok(Response::builder() - .status(500) - .header("Content-Type", "text/plain") - .body(Body::from(format!("Internal server error: {}", err))) - .unwrap()) + Box::pin(async move { + let result = service.handle_call(req).await; + match result { + Ok(response) => Ok(response), + Err(err @ GraphQLServerError::Canceled(_)) => { + error!(logger, "GraphQLService call failed: {}", err); + + Ok(Response::builder() + .status(500) + .header("Content-Type", "text/plain") + .body(Body::from("Internal server error (operation canceled)")) + .unwrap()) + } + Err(err @ GraphQLServerError::ClientError(_)) => { + debug!(logger, "GraphQLService call failed: {}", err); + + Ok(Response::builder() + .status(400) + .header("Content-Type", "text/plain") + .body(Body::from(format!("Invalid request: {}", err))) + .unwrap()) + } + Err(err @ GraphQLServerError::QueryError(_)) => { + error!(logger, "GraphQLService call failed: {}", err); + + Ok(Response::builder() + .status(500) + .header("Content-Type", "text/plain") + .body(Body::from(format!("Query error: {}", err))) + .unwrap()) + } + Err(err @ GraphQLServerError::InternalError(_)) => { + error!(logger, "GraphQLService call failed: {}", err); + + Ok(Response::builder() + .status(500) + .header("Content-Type", "text/plain") + .body(Body::from(format!("Internal server error: {}", err))) + .unwrap()) + } } - })) + }) } } @@ -554,10 +543,8 @@ mod tests { .body(Body::from("{}")) .unwrap(); - let response = service - .call(request) - .wait() - .expect("Should return a response"); + let response = + futures03::executor::block_on(service.call(request)).expect("Should return a response"); let errors = test_utils::assert_error_response(response, StatusCode::BAD_REQUEST); let message = errors[0] @@ -574,48 +561,40 @@ mod tests { ); } - #[test] - fn posting_valid_queries_yields_result_response() { + #[tokio::test(threaded_scheduler)] + async fn posting_valid_queries_yields_result_response() { let logger = Logger::root(slog::Discard, o!()); let metrics_registry = Arc::new(MockMetricsRegistry::new()); let metrics = Arc::new(GraphQLServiceMetrics::new(metrics_registry)); let (store, subgraph_id) = mock_store_with_users_subgraph(); let graphql_runner = Arc::new(TestGraphQlRunner); - let mut runtime = tokio::runtime::Runtime::new().unwrap(); - runtime - .block_on(future::lazy(move || { - let res: Result<_, ()> = Ok({ - let node_id = NodeId::new("test").unwrap(); - let mut service = - GraphQLService::new(logger, metrics, graphql_runner, store, 8001, node_id); - - let request = Request::builder() - .method(Method::POST) - .uri(format!( - "http://localhost:8000/subgraphs/id/{}", - subgraph_id - )) - .body(Body::from("{\"query\": \"{ name }\"}")) - .unwrap(); - - // The response must be a 200 - let response = service - .call(request) - .wait() - .expect("Should return a response"); - let data = test_utils::assert_successful_response(response); - - // The body should match the simulated query result - let name = data - .get("name") - .expect("Query result data has no \"name\" field") - .as_str() - .expect("Query result field \"name\" is not a string"); - assert_eq!(name, "Jordi".to_string()); - }); - res - })) + let node_id = NodeId::new("test").unwrap(); + let mut service = + GraphQLService::new(logger, metrics, graphql_runner, store, 8001, node_id); + + let request = Request::builder() + .method(Method::POST) + .uri(format!( + "http://localhost:8000/subgraphs/id/{}", + subgraph_id + )) + .body(Body::from("{\"query\": \"{ name }\"}")) + .unwrap(); + + // The response must be a 200 + let response = tokio::spawn(service.call(request)) + .await .unwrap() + .expect("Should return a response"); + let data = test_utils::assert_successful_response(response); + + // The body should match the simulated query result + let name = data + .get("name") + .expect("Query result data has no \"name\" field") + .as_str() + .expect("Query result field \"name\" is not a string"); + assert_eq!(name, "Jordi".to_string()); } } diff --git a/server/http/src/test_utils.rs b/server/http/src/test_utils.rs index fc0fc3b5157..be2b1880ab7 100644 --- a/server/http/src/test_utils.rs +++ b/server/http/src/test_utils.rs @@ -9,24 +9,23 @@ pub fn assert_successful_response( ) -> serde_json::Map { assert_eq!(response.status(), StatusCode::OK); - response - .into_body() - .concat2() - .map(|chunk| { - let json: serde_json::Value = - serde_json::from_slice(&chunk).expect("GraphQL response is not valid JSON"); + futures03::executor::block_on( + hyper::body::to_bytes(response.into_body()) + .map_ok(|chunk| { + let json: serde_json::Value = + serde_json::from_slice(&chunk).expect("GraphQL response is not valid JSON"); - json.as_object() - .expect("GraphQL response must be an object") - .get("data") - .expect("GraphQL response must contain a \"data\" field") - .as_object() - .expect("GraphQL \"data\" field must be an object") - .clone() - }) - .map_err(|e| panic!("Truncated response body {:?}", e)) - .wait() - .unwrap() + json.as_object() + .expect("GraphQL response must be an object") + .get("data") + .expect("GraphQL response must contain a \"data\" field") + .as_object() + .expect("GraphQL \"data\" field must be an object") + .clone() + }) + .map_err(|e| panic!("Truncated response body {:?}", e)), + ) + .unwrap() } /// Asserts that the response is a failed GraphQL response; returns its `"errors"` field. @@ -36,22 +35,21 @@ pub fn assert_error_response( ) -> Vec { assert_eq!(response.status(), expected_status); - response - .into_body() - .concat2() - .map(|chunk| { - let json: serde_json::Value = - serde_json::from_slice(&chunk).expect("GraphQL response is not valid JSON"); + futures03::executor::block_on( + hyper::body::to_bytes(response.into_body()) + .map_ok(|chunk| { + let json: serde_json::Value = + serde_json::from_slice(&chunk).expect("GraphQL response is not valid JSON"); - json.as_object() - .expect("GraphQL response must be an object") - .get("errors") - .expect("GraphQL error response must contain an \"errors\" field") - .as_array() - .expect("GraphQL \"errors\" field must be a vector") - .clone() - }) - .map_err(|e| panic!("Truncated response body {:?}", e)) - .wait() - .unwrap() + json.as_object() + .expect("GraphQL response must be an object") + .get("errors") + .expect("GraphQL error response must contain an \"errors\" field") + .as_array() + .expect("GraphQL \"errors\" field must be a vector") + .clone() + }) + .map_err(|e| panic!("Truncated response body {:?}", e)), + ) + .unwrap() } diff --git a/server/http/tests/server.rs b/server/http/tests/server.rs index b1201302041..cbbb5bee6fb 100644 --- a/server/http/tests/server.rs +++ b/server/http/tests/server.rs @@ -1,24 +1,15 @@ -extern crate futures; -extern crate graph; -#[cfg(test)] -extern crate graph_mock; -extern crate graph_server_http; -extern crate graphql_parser; -extern crate http; -extern crate hyper; - use graphql_parser::query as q; use http::StatusCode; use hyper::{Body, Client, Request}; use std::collections::BTreeMap; -use std::time::{Duration, Instant}; +use std::time::Duration; use graph::prelude::*; use graph_server_http::test_utils; use graph_server_http::GraphQLServer as HyperGraphQLServer; -use crate::tokio::timer::Delay; +use tokio::time::delay_for; /// A simple stupid query runner for testing. pub struct TestGraphQlRunner; @@ -80,7 +71,7 @@ mod test { fn rejects_empty_json() { let mut runtime = tokio::runtime::Runtime::new().unwrap(); runtime - .block_on(futures::lazy(|| { + .block_on(async { let logger = Logger::root(slog::Discard, o!()); let logger_factory = LoggerFactory::new(logger, None); let metrics_registry = Arc::new(MockMetricsRegistry::new()); @@ -93,11 +84,10 @@ mod test { .expect("Failed to start GraphQL server"); // Launch the server to handle a single request - tokio::spawn(http_server.fuse()); + tokio::spawn(http_server.fuse().compat()); // Give some time for the server to start. - Delay::new(Instant::now() + Duration::from_secs(2)) - .map_err(|e| panic!("failed to start server: {:?}", e)) - .and_then(move |()| { + delay_for(Duration::from_secs(2)) + .then(move |()| { // Send an empty JSON POST request let client = Client::new(); let request = @@ -108,7 +98,7 @@ mod test { // The response must be a query error client.request(request) }) - .and_then(|response| { + .map_ok(|response| { let errors = test_utils::assert_error_response(response, StatusCode::BAD_REQUEST); @@ -120,192 +110,182 @@ mod test { .as_str() .expect("Error message is not a string"); assert_eq!(message, "GraphQL server error (client error): The \"query\" field missing in request data"); - Ok(()) - }) - })) - .unwrap() + }).await.unwrap() + }) } #[test] fn rejects_invalid_queries() { let mut runtime = tokio::runtime::Runtime::new().unwrap(); - runtime - .block_on(futures::lazy(|| { - let logger = Logger::root(slog::Discard, o!()); - let logger_factory = LoggerFactory::new(logger, None); - let metrics_registry = Arc::new(MockMetricsRegistry::new()); - let query_runner = Arc::new(TestGraphQlRunner); - let (store, id) = mock_store_with_users_subgraph(); - let node_id = NodeId::new("test").unwrap(); - let mut server = HyperGraphQLServer::new( - &logger_factory, - metrics_registry, - query_runner, - store, - node_id, - ); - let http_server = server - .serve(8002, 8003) - .expect("Failed to start GraphQL server"); - - // Launch the server to handle a single request - tokio::spawn(http_server.fuse()); - // Give some time for the server to start. - Delay::new(Instant::now() + Duration::from_secs(2)) - .map_err(|e| panic!("failed to start server: {:?}", e)) - .and_then(move |()| { - // Send an broken query request - let client = Client::new(); - let request = - Request::post(format!("http://localhost:8002/subgraphs/id/{}", id)) - .body(Body::from("{\"query\": \"M>\"}")) - .unwrap(); - - // The response must be a query error - client.request(request) - }) - .and_then(|response| { - let errors = - test_utils::assert_error_response(response, StatusCode::BAD_REQUEST); - - let message = errors[0] - .as_object() - .expect("Query error is not an object") - .get("message") - .expect("Error contains no message") - .as_str() - .expect("Error message is not a string"); - - assert_eq!( - message, - "Unexpected `unexpected character \ - \'<\'`\nExpected `{`, `query`, `mutation`, \ - `subscription` or `fragment`" - ); - - let locations = errors[0] - .as_object() - .expect("Query error is not an object") - .get("locations") - .expect("Query error contains not locations") - .as_array() - .expect("Query error \"locations\" field is not an array"); - - let location = locations[0] - .as_object() - .expect("Query error location is not an object"); - - let line = location - .get("line") - .expect("Query error location is missing a \"line\" field") - .as_u64() - .expect("Query error location \"line\" field is not a u64"); - - assert_eq!(line, 1); - - let column = location - .get("column") - .expect("Query error location is missing a \"column\" field") - .as_u64() - .expect("Query error location \"column\" field is not a u64"); - - assert_eq!(column, 1); - Ok(()) - }) - })) - .unwrap() + runtime.block_on(async { + let logger = Logger::root(slog::Discard, o!()); + let logger_factory = LoggerFactory::new(logger, None); + let metrics_registry = Arc::new(MockMetricsRegistry::new()); + let (store, id) = mock_store_with_users_subgraph(); + let query_runner = Arc::new(TestGraphQlRunner); + let node_id = NodeId::new("test").unwrap(); + let mut server = HyperGraphQLServer::new( + &logger_factory, + metrics_registry, + query_runner, + store, + node_id, + ); + let http_server = server + .serve(8002, 8003) + .expect("Failed to start GraphQL server"); + + // Launch the server to handle a single request + tokio::spawn(http_server.fuse().compat()); + // Give some time for the server to start. + delay_for(Duration::from_secs(2)) + .then(move |()| { + // Send an broken query request + let client = Client::new(); + let request = + Request::post(format!("http://localhost:8002/subgraphs/id/{}", id)) + .body(Body::from("{\"query\": \"M>\"}")) + .unwrap(); + + // The response must be a query error + client.request(request) + }) + .map_ok(|response| { + let errors = + test_utils::assert_error_response(response, StatusCode::BAD_REQUEST); + + let message = errors[0] + .as_object() + .expect("Query error is not an object") + .get("message") + .expect("Error contains no message") + .as_str() + .expect("Error message is not a string"); + + assert_eq!( + message, + "Unexpected `unexpected character \ + \'<\'`\nExpected `{`, `query`, `mutation`, \ + `subscription` or `fragment`" + ); + + let locations = errors[0] + .as_object() + .expect("Query error is not an object") + .get("locations") + .expect("Query error contains not locations") + .as_array() + .expect("Query error \"locations\" field is not an array"); + + let location = locations[0] + .as_object() + .expect("Query error location is not an object"); + + let line = location + .get("line") + .expect("Query error location is missing a \"line\" field") + .as_u64() + .expect("Query error location \"line\" field is not a u64"); + + assert_eq!(line, 1); + + let column = location + .get("column") + .expect("Query error location is missing a \"column\" field") + .as_u64() + .expect("Query error location \"column\" field is not a u64"); + + assert_eq!(column, 1); + }) + .await + .unwrap() + }) } #[test] fn accepts_valid_queries() { let mut runtime = tokio::runtime::Runtime::new().unwrap(); - runtime - .block_on(futures::lazy(|| { - let logger = Logger::root(slog::Discard, o!()); - let logger_factory = LoggerFactory::new(logger, None); - let metrics_registry = Arc::new(MockMetricsRegistry::new()); - let query_runner = Arc::new(TestGraphQlRunner); - let (store, id) = mock_store_with_users_subgraph(); - let node_id = NodeId::new("test").unwrap(); - let mut server = HyperGraphQLServer::new( - &logger_factory, - metrics_registry, - query_runner, - store, - node_id, - ); - let http_server = server - .serve(8003, 8004) - .expect("Failed to start GraphQL server"); - - // Launch the server to handle a single request - tokio::spawn(http_server.fuse()); - // Give some time for the server to start. - Delay::new(Instant::now() + Duration::from_secs(2)) - .map_err(|e| panic!("failed to start server: {:?}", e)) - .and_then(move |()| { - // Send a valid example query - let client = Client::new(); - let request = - Request::post(format!("http://localhost:8003/subgraphs/id/{}", id)) - .body(Body::from("{\"query\": \"{ name }\"}")) - .unwrap(); - - // The response must be a 200 - client.request(request) - }) - .and_then(|response| { - let data = test_utils::assert_successful_response(response); - - // The JSON response should match the simulated query result - let name = data - .get("name") - .expect("Query result data has no \"name\" field") - .as_str() - .expect("Query result field \"name\" is not a string"); - assert_eq!(name, "Jordi".to_string()); - - Ok(()) - }) - })) - .unwrap() + runtime.block_on(async { + let logger = Logger::root(slog::Discard, o!()); + let logger_factory = LoggerFactory::new(logger, None); + let metrics_registry = Arc::new(MockMetricsRegistry::new()); + let (store, id) = mock_store_with_users_subgraph(); + let query_runner = Arc::new(TestGraphQlRunner); + let node_id = NodeId::new("test").unwrap(); + let mut server = HyperGraphQLServer::new( + &logger_factory, + metrics_registry, + query_runner, + store, + node_id, + ); + let http_server = server + .serve(8003, 8004) + .expect("Failed to start GraphQL server"); + + // Launch the server to handle a single request + tokio::spawn(http_server.fuse().compat()); + // Give some time for the server to start. + delay_for(Duration::from_secs(2)) + .then(move |()| { + // Send a valid example query + let client = Client::new(); + let request = + Request::post(format!("http://localhost:8003/subgraphs/id/{}", id)) + .body(Body::from("{\"query\": \"{ name }\"}")) + .unwrap(); + + // The response must be a 200 + client.request(request) + }) + .map_ok(|response| { + let data = test_utils::assert_successful_response(response); + + // The JSON response should match the simulated query result + let name = data + .get("name") + .expect("Query result data has no \"name\" field") + .as_str() + .expect("Query result field \"name\" is not a string"); + assert_eq!(name, "Jordi".to_string()); + }) + .await + .unwrap() + }); } #[test] fn accepts_valid_queries_with_variables() { let mut runtime = tokio::runtime::Runtime::new().unwrap(); - runtime - .block_on(futures::lazy(|| { - let logger = Logger::root(slog::Discard, o!()); - let logger_factory = LoggerFactory::new(logger, None); - let metrics_registry = Arc::new(MockMetricsRegistry::new()); - - let query_runner = Arc::new(TestGraphQlRunner); - let (store, id) = mock_store_with_users_subgraph(); - let node_id = NodeId::new("test").unwrap(); - let mut server = HyperGraphQLServer::new( - &logger_factory, - metrics_registry, - query_runner, - store, - node_id, - ); - let http_server = server - .serve(8005, 8006) - .expect("Failed to start GraphQL server"); - - // Launch the server to handle a single request - tokio::spawn(http_server.fuse()); - // Give some time for the server to start. - Delay::new(Instant::now() + Duration::from_secs(2)) - .map_err(|e| panic!("failed to start server: {:?}", e)) - .and_then(move |()| { - // Send a valid example query - let client = Client::new(); - let request = - Request::post(format!("http://localhost:8005/subgraphs/id/{}", id)) - .body(Body::from( - " + let _ = runtime.block_on(async { + let logger = Logger::root(slog::Discard, o!()); + let logger_factory = LoggerFactory::new(logger, None); + let metrics_registry = Arc::new(MockMetricsRegistry::new()); + let (store, id) = mock_store_with_users_subgraph(); + let query_runner = Arc::new(TestGraphQlRunner); + let node_id = NodeId::new("test").unwrap(); + let mut server = HyperGraphQLServer::new( + &logger_factory, + metrics_registry, + query_runner, + store, + node_id, + ); + let http_server = server + .serve(8005, 8006) + .expect("Failed to start GraphQL server"); + + // Launch the server to handle a single request + tokio::spawn(http_server.fuse().compat()); + // Give some time for the server to start. + delay_for(Duration::from_secs(2)) + .then(move |()| { + // Send a valid example query + let client = Client::new(); + let request = + Request::post(format!("http://localhost:8005/subgraphs/id/{}", id)) + .body(Body::from( + " { \"query\": \" \ query name($equals: String!) { \ @@ -315,13 +295,14 @@ mod test { \"variables\": { \"equals\": \"John\" } } ", - )) - .unwrap(); - - // The response must be a 200 - client.request(request) - }) - .and_then(|response| { + )) + .unwrap(); + + // The response must be a 200 + client.request(request) + }) + .map_ok(|response| { + async { let data = test_utils::assert_successful_response(response); // The JSON response should match the simulated query result @@ -331,10 +312,10 @@ mod test { .as_str() .expect("Query result field \"name\" is not a string"); assert_eq!(name, "John".to_string()); - - Ok(()) - }) - })) - .unwrap() + } + }) + .await + .unwrap() + }); } } diff --git a/server/index-node/Cargo.toml b/server/index-node/Cargo.toml index 02a958b1080..e334e74b277 100644 --- a/server/index-node/Cargo.toml +++ b/server/index-node/Cargo.toml @@ -4,11 +4,12 @@ version = "0.17.1" edition = "2018" [dependencies] +failure = "0.1.6" futures = "0.1.21" graph = { path = "../../graph" } graph-graphql = { path = "../../graphql" } graphql-parser = "0.2.3" -http = "0.1.5" -hyper = "0.12.35" +http = "0.2" +hyper = "0.13" lazy_static = "1.2.0" serde = "1.0" diff --git a/server/index-node/src/request.rs b/server/index-node/src/request.rs index d7aa98c21dc..5187477974a 100644 --- a/server/index-node/src/request.rs +++ b/server/index-node/src/request.rs @@ -1,20 +1,20 @@ use graphql_parser; -use hyper::Chunk; use graph::components::server::query::GraphQLServerError; use graph::prelude::*; +use hyper::body::Bytes; use serde_json; /// Future for a query parsed from an HTTP request. pub struct IndexNodeRequest { - body: Chunk, + body: Bytes, schema: Arc, } impl IndexNodeRequest { /// Creates a new IndexNodeRequest future based on an HTTP request and a result sender. - pub fn new(body: Chunk, schema: Arc) -> Self { + pub fn new(body: Bytes, schema: Arc) -> Self { IndexNodeRequest { body, schema } } } @@ -90,7 +90,7 @@ mod tests { fn rejects_invalid_json() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = IndexNodeRequest::new(hyper::Chunk::from("!@#)%"), Arc::new(schema)); + let request = IndexNodeRequest::new(hyper::body::Bytes::from("!@#)%"), Arc::new(schema)); request.wait().expect_err("Should reject invalid JSON"); } @@ -98,7 +98,7 @@ mod tests { fn rejects_json_without_query_field() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = IndexNodeRequest::new(hyper::Chunk::from("{}"), Arc::new(schema)); + let request = IndexNodeRequest::new(hyper::body::Bytes::from("{}"), Arc::new(schema)); request .wait() .expect_err("Should reject JSON without query field"); @@ -108,7 +108,8 @@ mod tests { fn rejects_json_with_non_string_query_field() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = IndexNodeRequest::new(hyper::Chunk::from("{\"query\": 5}"), Arc::new(schema)); + let request = + IndexNodeRequest::new(hyper::body::Bytes::from("{\"query\": 5}"), Arc::new(schema)); request .wait() .expect_err("Should reject JSON with a non-string query field"); @@ -118,8 +119,10 @@ mod tests { fn rejects_broken_queries() { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); - let request = - IndexNodeRequest::new(hyper::Chunk::from("{\"query\": \"foo\"}"), Arc::new(schema)); + let request = IndexNodeRequest::new( + hyper::body::Bytes::from("{\"query\": \"foo\"}"), + Arc::new(schema), + ); request.wait().expect_err("Should reject broken queries"); } @@ -128,7 +131,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = IndexNodeRequest::new( - hyper::Chunk::from("{\"query\": \"{ user { name } }\"}"), + hyper::body::Bytes::from("{\"query\": \"{ user { name } }\"}"), Arc::new(schema), ); let query = request.wait().expect("Should accept valid queries"); @@ -143,7 +146,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = IndexNodeRequest::new( - hyper::Chunk::from( + hyper::body::Bytes::from( "\ {\ \"query\": \"{ user { name } }\", \ @@ -164,7 +167,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = IndexNodeRequest::new( - hyper::Chunk::from( + hyper::body::Bytes::from( "\ {\ \"query\": \"{ user { name } }\", \ @@ -181,7 +184,7 @@ mod tests { let schema = Schema::parse(EXAMPLE_SCHEMA, SubgraphDeploymentId::new("test").unwrap()).unwrap(); let request = IndexNodeRequest::new( - hyper::Chunk::from( + hyper::body::Bytes::from( "\ {\ \"query\": \"{ user { name } }\", \ diff --git a/server/index-node/src/server.rs b/server/index-node/src/server.rs index 262f7b08e84..f384908b7c1 100644 --- a/server/index-node/src/server.rs +++ b/server/index-node/src/server.rs @@ -1,7 +1,6 @@ use hyper; +use hyper::service::make_service_fn; use hyper::Server; -use std::error::Error; -use std::fmt; use std::net::{Ipv4Addr, SocketAddrV4}; use graph::prelude::{IndexNodeServer as IndexNodeServerTrait, *}; @@ -9,31 +8,12 @@ use graph::prelude::{IndexNodeServer as IndexNodeServerTrait, *}; use crate::service::IndexNodeService; /// Errors that may occur when starting the server. -#[derive(Debug)] +#[derive(Debug, Fail)] pub enum IndexNodeServeError { + #[fail(display = "Bind error: {}", _0)] BindError(hyper::Error), } -impl Error for IndexNodeServeError { - fn description(&self) -> &str { - "Failed to start the server" - } - - fn cause(&self) -> Option<&dyn Error> { - None - } -} - -impl fmt::Display for IndexNodeServeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - IndexNodeServeError::BindError(e) => { - write!(f, "Failed to bind index node server: {}", e) - } - } - } -} - impl From for IndexNodeServeError { fn from(err: hyper::Error) -> Self { IndexNodeServeError::BindError(err) @@ -100,21 +80,20 @@ where let graphql_runner = self.graphql_runner.clone(); let store = self.store.clone(); let node_id = self.node_id.clone(); - let new_service = move || { - let service = IndexNodeService::new( + let new_service = make_service_fn(move |_| { + futures03::future::ok::<_, Error>(IndexNodeService::new( logger_for_service.clone(), graphql_runner.clone(), store.clone(), node_id.clone(), - ); - future::ok::, hyper::Error>(service) - }; + )) + }); // Create a task to run the server and handle HTTP requests let task = Server::try_bind(&addr.into())? .serve(new_service) .map_err(move |e| error!(logger, "Server error"; "error" => format!("{}", e))); - Ok(Box::new(task)) + Ok(Box::new(task.compat())) } } diff --git a/server/index-node/src/service.rs b/server/index-node/src/service.rs index 46ce3b882b9..545b721076e 100644 --- a/server/index-node/src/service.rs +++ b/server/index-node/src/service.rs @@ -1,6 +1,9 @@ use http::header; use hyper::service::Service; use hyper::{Body, Method, Request, Response, StatusCode}; +use std::pin::Pin; +use std::task::Context; +use std::task::Poll; use std::time::Instant; use graph::components::server::query::GraphQLServerError; @@ -14,7 +17,7 @@ use crate::schema::SCHEMA; /// An asynchronous response to a GraphQL request. pub type IndexNodeServiceResponse = - Box, Error = GraphQLServerError> + Send>; + Pin, GraphQLServerError>> + Send>>; /// A Hyper Service that serves GraphQL over a POST / endpoint. #[derive(Debug)] @@ -57,31 +60,33 @@ where /// Serves a static file. fn serve_file(&self, contents: &'static str) -> IndexNodeServiceResponse { - Box::new(future::ok( - Response::builder() + async move { + Ok(Response::builder() .status(200) .body(Body::from(contents)) - .unwrap(), - )) + .unwrap()) + } + .boxed() } /// Serves a dynamically created file. fn serve_dynamic_file(&self, contents: String) -> IndexNodeServiceResponse { - Box::new(future::ok( - Response::builder() + async { + Ok(Response::builder() .status(200) .body(Body::from(contents)) - .unwrap(), - )) + .unwrap()) + } + .boxed() } fn index(&self) -> IndexNodeServiceResponse { - Box::new(future::ok( - Response::builder() + Box::pin(async { + Ok(Response::builder() .status(200) .body(Body::from("OK")) - .unwrap(), - )) + .unwrap()) + }) } fn handle_graphiql(&self) -> IndexNodeServiceResponse { @@ -98,17 +103,17 @@ where let schema = SCHEMA.clone(); let start = Instant::now(); - Box::new( - request_body - .concat2() - .map_err(|_| GraphQLServerError::from("Failed to read request body")) - .and_then(move |body| IndexNodeRequest::new(body, schema)) - .and_then(move |query| { - let logger = logger.clone(); - let graphql_runner = graphql_runner.clone(); - - // Run the query using the index node resolver - Box::new(future::ok(execute_query( + + hyper::body::to_bytes(request_body) + .map_err(|_| GraphQLServerError::from("Failed to read request body")) + .and_then(move |body| IndexNodeRequest::new(body, schema).compat()) + .and_then(move |query| { + let logger = logger.clone(); + let graphql_runner = graphql_runner.clone(); + + // Run the query using the index node resolver + tokio::task::block_in_place(|| { + futures03::future::ok(execute_query( query, QueryExecutionOptions { logger: logger.clone(), @@ -118,46 +123,47 @@ where max_depth: 100, max_first: std::u32::MAX, }, - ))) + )) }) - .then(move |result| { - let elapsed = start.elapsed().as_millis(); - match result { - Ok(_) => info!( - result_logger, - "GraphQL query served"; - "query_time_ms" => elapsed, - "code" => LogCode::GraphQlQuerySuccess, - ), - Err(ref e) => error!( - result_logger, - "GraphQL query failed"; - "error" => e.to_string(), - "query_time_ms" => elapsed, - "code" => LogCode::GraphQlQueryFailure, - ), - } - IndexNodeResponse::new(result) - }), - ) + }) + .then(move |result| { + let elapsed = start.elapsed().as_millis(); + match result { + Ok(_) => info!( + result_logger, + "GraphQL query served"; + "query_time_ms" => elapsed, + "code" => LogCode::GraphQlQuerySuccess, + ), + Err(ref e) => error!( + result_logger, + "GraphQL query failed"; + "error" => e.to_string(), + "query_time_ms" => elapsed, + "code" => LogCode::GraphQlQueryFailure, + ), + } + IndexNodeResponse::new(result).compat() + }) + .boxed() } // Handles OPTIONS requests fn handle_graphql_options(&self, _request: Request) -> IndexNodeServiceResponse { - Box::new(future::ok( - Response::builder() + Box::pin(async { + Ok(Response::builder() .status(200) .header("Access-Control-Allow-Origin", "*") .header("Access-Control-Allow-Headers", "Content-Type") .header("Access-Control-Allow-Methods", "GET, OPTIONS, POST") .body(Body::from("")) - .unwrap(), - )) + .unwrap()) + }) } /// Handles 302 redirects fn handle_temp_redirect(&self, destination: &str) -> IndexNodeServiceResponse { - Box::new(future::result( + Box::pin(futures03::future::ready( header::HeaderValue::from_str(destination) .map_err(|_| GraphQLServerError::from("invalid characters in redirect URL")) .map(|loc_header_val| { @@ -172,7 +178,7 @@ where /// Handles 404s. fn handle_not_found(&self) -> IndexNodeServiceResponse { - Box::new(future::ok( + Box::pin(futures03::future::ok( Response::builder() .status(StatusCode::NOT_FOUND) .body(Body::from("Not found")) @@ -216,22 +222,25 @@ where } } -impl Service for IndexNodeService +impl Service> for IndexNodeService where Q: GraphQlRunner, S: SubgraphDeploymentStore + Store, { - type ReqBody = Body; - type ResBody = Body; + type Response = Response; type Error = GraphQLServerError; type Future = IndexNodeServiceResponse; - fn call(&mut self, req: Request) -> Self::Future { + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: Request) -> Self::Future { let logger = self.logger.clone(); // Returning Err here will prevent the client from receiving any response. // Instead, we generate a Response with an error code and return Ok - Box::new(self.handle_call(req).then(move |result| match result { + Box::pin(self.handle_call(req).map(move |result| match result { Ok(response) => Ok(response), Err(err @ GraphQLServerError::Canceled(_)) => { error!(logger, "IndexNodeService call failed: {}", err); diff --git a/server/json-rpc/src/lib.rs b/server/json-rpc/src/lib.rs index 813556ba1f4..b41d65e9de5 100644 --- a/server/json-rpc/src/lib.rs +++ b/server/json-rpc/src/lib.rs @@ -3,6 +3,8 @@ extern crate jsonrpc_http_server; extern crate lazy_static; extern crate serde; +use graph::prelude::futures03::channel::{mpsc, oneshot}; +use graph::prelude::futures03::SinkExt; use graph::prelude::serde_json; use graph::prelude::{JsonRpcServer as JsonRpcServerTrait, *}; use jsonrpc_http_server::{ @@ -208,40 +210,93 @@ where logger, }); + let (task_sender, task_receiver) = + mpsc::channel:: + Send + Unpin>>(100); + graph::spawn(task_receiver.for_each(|f| { + async { + // Blocking due to store interactions. Won't be blocking after #905. + graph::spawn_blocking(f); + } + })); + + // This is a hack required because the json-rpc crate is not updated to tokio 0.2. + // We should watch the `jsonrpsee` crate and switch to that once it's ready. + async fn tokio02_spawn( + mut task_sink: mpsc::Sender + Send + Unpin>>, + future: impl std::future::Future> + Send + Unpin + 'static, + ) -> Result + where + I: Debug, + ER: Debug, + { + let (return_sender, return_receiver) = oneshot::channel(); + task_sink + .send(Box::new(future.map(move |res| { + return_sender.send(res).expect("`return_receiver` dropped"); + }))) + .await + .expect("task receiver dropped"); + return_receiver.await.expect("`return_sender` dropped") + } + let me = arc_self.clone(); + let sender = task_sender.clone(); handler.add_method("subgraph_create", move |params: Params| { let me = me.clone(); - params - .parse() - .into_future() - .and_then(move |params| me.create_handler(params)) + Box::pin(tokio02_spawn( + sender.clone(), + params + .parse() + .into_future() + .and_then(move |params| me.create_handler(params)) + .compat(), + )) + .compat() }); let me = arc_self.clone(); + let sender = task_sender.clone(); handler.add_method("subgraph_deploy", move |params: Params| { let me = me.clone(); - params - .parse() - .into_future() - .and_then(move |params| me.deploy_handler(params)) + Box::pin(tokio02_spawn( + sender.clone(), + params + .parse() + .into_future() + .and_then(move |params| me.deploy_handler(params)) + .compat(), + )) + .compat() }); let me = arc_self.clone(); + let sender = task_sender.clone(); handler.add_method("subgraph_remove", move |params: Params| { let me = me.clone(); - params - .parse() - .into_future() - .and_then(move |params| me.remove_handler(params)) + Box::pin(tokio02_spawn( + sender.clone(), + params + .parse() + .into_future() + .and_then(move |params| me.remove_handler(params)) + .compat(), + )) + .compat() }); let me = arc_self.clone(); + let sender = task_sender.clone(); handler.add_method("subgraph_reassign", move |params: Params| { let me = me.clone(); - params - .parse() - .into_future() - .and_then(move |params| me.reassign_handler(params)) + Box::pin(tokio02_spawn( + sender.clone(), + params + .parse() + .into_future() + .and_then(move |params| me.reassign_handler(params)) + .compat(), + )) + .compat() }); ServerBuilder::new(handler) diff --git a/server/metrics/Cargo.toml b/server/metrics/Cargo.toml index ba6b0331e8a..7a6bfad3ac8 100644 --- a/server/metrics/Cargo.toml +++ b/server/metrics/Cargo.toml @@ -4,10 +4,11 @@ version = "0.17.1" edition = "2018" [dependencies] +failure = "0.1.6" futures = "0.1.21" graph = { path = "../../graph" } -http = "0.1.5" -hyper = "0.12.35" +http = "0.2" +hyper = "0.13" lazy_static = "1.2.0" serde = "1.0" prometheus = "0.7" diff --git a/server/metrics/src/lib.rs b/server/metrics/src/lib.rs index bbb90f928b0..c46ea1fb488 100644 --- a/server/metrics/src/lib.rs +++ b/server/metrics/src/lib.rs @@ -1,41 +1,20 @@ -use std::error::Error; -use std::fmt::{Display, Formatter, Result as FmtResult}; use std::net::{Ipv4Addr, SocketAddrV4}; use std::sync::Arc; use hyper; -use hyper::service::service_fn_ok; +use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Response, Server}; use prometheus::{Encoder, Registry, TextEncoder}; use graph::prelude::{MetricsServer as MetricsServerTrait, *}; /// Errors that may occur when starting the server. -#[derive(Debug)] +#[derive(Debug, Fail)] pub enum PrometheusMetricsServeError { + #[fail(display = "Bind error: {}", _0)] BindError(hyper::Error), } -impl Error for PrometheusMetricsServeError { - fn description(&self) -> &str { - "Failed to start the server" - } - - fn cause(&self) -> Option<&dyn Error> { - None - } -} - -impl Display for PrometheusMetricsServeError { - fn fmt(&self, f: &mut Formatter) -> FmtResult { - match self { - PrometheusMetricsServeError::BindError(e) => { - write!(f, "Failed to bind index node server: {}", e) - } - } - } -} - impl From for PrometheusMetricsServeError { fn from(err: hyper::Error) -> Self { PrometheusMetricsServeError::BindError(err) @@ -82,25 +61,30 @@ impl MetricsServerTrait for PrometheusMetricsServer { let addr = SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), port); let server = self.clone(); - let new_service = move || { + let new_service = make_service_fn(move |_req| { + let server = server.clone(); let registry = server.registry.clone(); - service_fn_ok(move |_req| { - let metric_families = registry.gather(); - let mut buffer = vec![]; - let encoder = TextEncoder::new(); - encoder.encode(&metric_families, &mut buffer).unwrap(); - Response::builder() - .status(200) - .header(hyper::header::CONTENT_TYPE, encoder.format_type()) - .body(Body::from(buffer)) - .unwrap() - }) - }; + async move { + Ok::<_, Error>(service_fn(move |_| { + let metric_families = registry.gather(); + let mut buffer = vec![]; + let encoder = TextEncoder::new(); + encoder.encode(&metric_families, &mut buffer).unwrap(); + futures03::future::ok::<_, Error>( + Response::builder() + .status(200) + .header(hyper::header::CONTENT_TYPE, encoder.format_type()) + .body(Body::from(buffer)) + .unwrap(), + ) + })) + } + }); let task = Server::try_bind(&addr.into())? .serve(new_service) .map_err(move |e| error!(logger, "Metrics server error"; "error" => format!("{}", e))); - Ok(Box::new(task)) + Ok(Box::new(task.compat())) } } diff --git a/server/websocket/Cargo.toml b/server/websocket/Cargo.toml index f8a1abfe511..e2ab5c1182a 100644 --- a/server/websocket/Cargo.toml +++ b/server/websocket/Cargo.toml @@ -8,9 +8,13 @@ futures = "0.1.23" graph = { path = "../../graph" } graphql-parser = "0.2.1" graph-graphql = { path = "../../graphql" } -hyper = "0.12.7" +http = "0.2" lazy_static = "1.2.0" serde = "1.0" serde_derive = "1.0" tokio-tungstenite = "0.6" uuid = { version = "0.7.2", features = ["v4"] } + +# Needed for compatibility with tokio-tungstenite +tokio01 = { version = "0.1.7", package = "tokio" } +tokio-io = "0.1.7" diff --git a/server/websocket/src/connection.rs b/server/websocket/src/connection.rs index c14240b5357..6a418a72e21 100644 --- a/server/websocket/src/connection.rs +++ b/server/websocket/src/connection.rs @@ -168,7 +168,7 @@ pub struct GraphQlConnection { impl GraphQlConnection where Q: GraphQlRunner, - S: AsyncRead + AsyncWrite + Send + 'static, + S: tokio_io::AsyncRead + tokio_io::AsyncWrite + Send + 'static, { /// Creates a new GraphQL subscription service. pub(crate) fn new( @@ -350,7 +350,7 @@ where }); operations.insert(id, guard); - tokio::spawn(run_subscription); + graph::spawn(run_subscription.compat()); Ok(()) } } @@ -361,7 +361,7 @@ where impl IntoFuture for GraphQlConnection where Q: GraphQlRunner, - S: AsyncRead + AsyncWrite + Send + 'static, + S: tokio_io::AsyncRead + tokio_io::AsyncWrite + Send + 'static, { type Future = Box + Send>; type Item = (); diff --git a/server/websocket/src/lib.rs b/server/websocket/src/lib.rs index 5fbd77f48bf..887fed506fe 100644 --- a/server/websocket/src/lib.rs +++ b/server/websocket/src/lib.rs @@ -1,12 +1,3 @@ -extern crate futures; -extern crate graph; -extern crate graph_graphql; -extern crate graphql_parser; -extern crate hyper; -extern crate serde_derive; -extern crate tokio_tungstenite; -extern crate uuid; - mod connection; mod server; diff --git a/server/websocket/src/server.rs b/server/websocket/src/server.rs index 31165048db7..d5ae58b03e8 100644 --- a/server/websocket/src/server.rs +++ b/server/websocket/src/server.rs @@ -1,9 +1,9 @@ use graph::data::subgraph::schema::SUBGRAPHS_ID; use graph::prelude::{SubscriptionServer as SubscriptionServerTrait, *}; -use hyper::Uri; +use http::Uri; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::sync::Mutex; -use tokio::net::TcpListener; +use tokio01::net::TcpListener; use tokio_tungstenite::accept_hdr_async; use tokio_tungstenite::tungstenite::{handshake::server::Request, Error as WsError}; @@ -190,7 +190,9 @@ where ws_stream, graphql_runner.clone(), ); - tokio::spawn(service.into_future()); + + // Blocking due to store interactions. Won't be blocking after #905. + graph::spawn_blocking_allow_panic(service.into_future().compat()); } Err(e) => { // We gracefully skip over failed connection attempts rather diff --git a/store/postgres/src/chain_head_listener.rs b/store/postgres/src/chain_head_listener.rs index f5fc6cbc295..420e0c6f5d5 100644 --- a/store/postgres/src/chain_head_listener.rs +++ b/store/postgres/src/chain_head_listener.rs @@ -50,16 +50,17 @@ impl ChainHeadUpdateListener { metrics: Arc, listener: &mut NotificationListener, network_name: String, - mut update_sender: watch::Sender<()>, + update_sender: watch::Sender<()>, ) { let logger = logger.clone(); // Process chain head updates in a dedicated task - tokio::spawn( + graph::spawn( listener .take_event_stream() .unwrap() - .filter_map(move |notification| { + .compat() + .try_filter_map(move |notification| { // Create ChainHeadUpdate from JSON let update: ChainHeadUpdate = serde_json::from_value(notification.payload.clone()).unwrap_or_else(|_| { @@ -77,13 +78,13 @@ impl ChainHeadUpdateListener { ); // Only include update if it is for the network we're interested in - if update.network_name == network_name { + futures03::future::ok(if update.network_name == network_name { Some(update) } else { None - } + }) }) - .for_each(move |update| { + .try_for_each(move |update| { debug!( logger.clone(), "Received chain head update"; @@ -92,7 +93,7 @@ impl ChainHeadUpdateListener { "head_block_number" => &update.head_block_number, ); - update_sender.broadcast(()).map_err(|_| ()) + futures03::future::ready(update_sender.broadcast(()).map_err(|_| ())) }), ); @@ -103,6 +104,6 @@ impl ChainHeadUpdateListener { impl ChainHeadUpdateListenerTrait for ChainHeadUpdateListener { fn subscribe(&self) -> ChainHeadUpdateStream { - Box::new(self.update_receiver.clone().map_err(|_| ())) + Box::new(self.update_receiver.clone().map(Ok).compat()) } } diff --git a/store/postgres/src/store.rs b/store/postgres/src/store.rs index dfb4388d261..b341b683a88 100644 --- a/store/postgres/src/store.rs +++ b/store/postgres/src/store.rs @@ -17,19 +17,18 @@ use graph::data::subgraph::schema::{ SubgraphDeploymentEntity, SubgraphManifestEntity, TypedEntity as _, SUBGRAPHS_ID, }; use graph::prelude::{ - bail, debug, ethabi, format_err, info, o, serde_json, stream, tiny_keccak, tokio, trace, warn, - web3, AttributeIndexDefinition, BigInt, BlockNumber, ChainHeadUpdateListener as _, + bail, debug, ethabi, format_err, futures03, info, o, serde_json, stream, tiny_keccak, tokio, + trace, warn, web3, AttributeIndexDefinition, BigInt, BlockNumber, ChainHeadUpdateListener as _, ChainHeadUpdateStream, ChainStore, Entity, EntityKey, EntityModification, EntityOrder, EntityQuery, EntityRange, Error, EthereumBlock, EthereumBlockPointer, EthereumCallCache, - EthereumNetworkIdentifier, EventProducer as _, Future, LightEthereumBlock, Logger, - MetadataOperation, MetricsRegistry, QueryExecutionError, Schema, Sink as _, StopwatchMetrics, - StoreError, StoreEvent, StoreEventStream, StoreEventStreamBox, Stream, + EthereumNetworkIdentifier, EventProducer as _, Future, Future01CompatExt, LightEthereumBlock, + Logger, MetadataOperation, MetricsRegistry, QueryExecutionError, Schema, Sink as _, + StopwatchMetrics, StoreError, StoreEvent, StoreEventStream, StoreEventStreamBox, Stream, SubgraphAssignmentProviderError, SubgraphDeploymentId, SubgraphDeploymentStore, SubgraphEntityPair, TransactionAbortError, Value, BLOCK_NUMBER_MAX, }; use graph_chain_ethereum::BlockIngestorMetrics; use graph_graphql::prelude::api_schema; -use tokio::timer::Interval; use web3::types::H256; use crate::chain_head_listener::ChainHeadUpdateListener; @@ -278,60 +277,64 @@ impl Store { let logger = self.logger.clone(); let subscriptions = self.subscriptions.clone(); - tokio::spawn(store_events.for_each(move |event| { - let senders = subscriptions.read().unwrap().clone(); - let logger = logger.clone(); - let subscriptions = subscriptions.clone(); - - // Write change to all matching subscription streams; remove subscriptions - // whose receiving end has been dropped - stream::iter_ok::<_, ()>(senders).for_each(move |(id, sender)| { - let logger = logger.clone(); - let subscriptions = subscriptions.clone(); - - sender.send(event.clone()).then(move |result| { - match result { - Err(_send_error) => { - // Receiver was dropped - debug!(logger, "Unsubscribe"; "id" => &id); - subscriptions.write().unwrap().remove(&id); - Ok(()) - } - Ok(_sender) => Ok(()), - } + graph::spawn( + store_events + .for_each(move |event| { + let senders = subscriptions.read().unwrap().clone(); + let logger = logger.clone(); + let subscriptions = subscriptions.clone(); + + // Write change to all matching subscription streams; remove subscriptions + // whose receiving end has been dropped + stream::iter_ok::<_, ()>(senders).for_each(move |(id, sender)| { + let logger = logger.clone(); + let subscriptions = subscriptions.clone(); + + sender.send(event.clone()).then(move |result| { + match result { + Err(_send_error) => { + // Receiver was dropped + debug!(logger, "Unsubscribe"; "id" => &id); + subscriptions.write().unwrap().remove(&id); + Ok(()) + } + Ok(_sender) => Ok(()), + } + }) + }) }) - }) - })); + .compat(), + ); } fn periodically_clean_up_stale_subscriptions(&self) { + use futures03::stream::StreamExt; + let logger = self.logger.clone(); let subscriptions = self.subscriptions.clone(); // Clean up stale subscriptions every 5s - tokio::spawn( - Interval::new(Instant::now(), Duration::from_secs(5)) - .for_each(move |_| { - let mut subscriptions = subscriptions.write().unwrap(); - - // Obtain IDs of subscriptions whose receiving end has gone - let stale_ids = subscriptions - .iter_mut() - .filter_map(|(id, sender)| match sender.poll_ready() { - Err(_) => Some(id.clone()), - _ => None, - }) - .collect::>(); + graph::spawn( + tokio::time::interval(Duration::from_secs(5)).for_each(move |_| { + let mut subscriptions = subscriptions.write().unwrap(); + + // Obtain IDs of subscriptions whose receiving end has gone + let stale_ids = subscriptions + .iter_mut() + .filter_map(|(id, sender)| match sender.poll_ready() { + Err(_) => Some(id.clone()), + _ => None, + }) + .collect::>(); - // Remove all stale subscriptions - for id in stale_ids { - debug!(logger, "Unsubscribe"; "id" => &id); - subscriptions.remove(&id); - } + // Remove all stale subscriptions + for id in stale_ids { + debug!(logger, "Unsubscribe"; "id" => &id); + subscriptions.remove(&id); + } - Ok(()) - }) - .map_err(|_| unreachable!()), + futures03::future::ready(()) + }), ); } diff --git a/store/postgres/tests/chain_head.rs b/store/postgres/tests/chain_head.rs index 9a5ae1441e9..e1961721934 100644 --- a/store/postgres/tests/chain_head.rs +++ b/store/postgres/tests/chain_head.rs @@ -1,12 +1,12 @@ //! Test ChainStore implementation of Store, in particular, how //! the chain head pointer gets updated in various situations -use futures::future::{self, IntoFuture}; +use futures::future::IntoFuture; use std::fmt::Debug; use std::sync::Arc; use graph::components::store::{ChainStore, Store as _}; -use graph::prelude::SubgraphDeploymentId; +use graph::prelude::{Future01CompatExt, SubgraphDeploymentId}; use graph_store_postgres::Store as DieselStore; use test_store::block_store::{ @@ -36,7 +36,7 @@ where }; runtime - .block_on(future::lazy(move || { + .block_on(async { // Reset state before starting block_store::remove(); @@ -44,9 +44,9 @@ where block_store::insert(chain, NETWORK_NAME); // Run test - test(store) - })) - .expect("Failed to run ChainHead test"); + test(store).into_future().compat().await + }) + .unwrap_or_else(|e| panic!("Failed to run ChainHead test: {:?}", e)); } /// Check that `attempt_chain_head_update` works as expected on the given diff --git a/store/postgres/tests/relational.rs b/store/postgres/tests/relational.rs index c1451a516df..e388b4562c0 100644 --- a/store/postgres/tests/relational.rs +++ b/store/postgres/tests/relational.rs @@ -2,7 +2,7 @@ use diesel::connection::SimpleConnection as _; use diesel::pg::PgConnection; use diesel::prelude::*; -use futures::future::{self, IntoFuture}; +use futures::future::IntoFuture; use hex_literal::hex; use lazy_static::lazy_static; use std::fmt::Debug; @@ -11,8 +11,8 @@ use std::str::FromStr; use graph::data::store::scalar::{BigDecimal, BigInt, Bytes}; use graph::prelude::{ bigdecimal::One, web3::types::H256, Entity, EntityCollection, EntityFilter, EntityKey, - EntityOrder, EntityQuery, EntityRange, Schema, SubgraphDeploymentId, Value, ValueType, - BLOCK_NUMBER_MAX, + EntityOrder, EntityQuery, EntityRange, Future01CompatExt, Schema, SubgraphDeploymentId, Value, + ValueType, BLOCK_NUMBER_MAX, }; use graph_store_postgres::layout_for_tests::{Layout, STRING_PREFIX_SIZE}; @@ -305,7 +305,7 @@ where }; runtime - .block_on(future::lazy(move || { + .block_on(async { // Reset state before starting remove_test_data(&conn); @@ -313,9 +313,9 @@ where let layout = insert_test_data(&conn); // Run test - test(&conn, &layout) - })) - .expect("Failed to run ChainHead test"); + test(&conn, &layout).into_future().compat().await + }) + .unwrap_or_else(|e| panic!("Failed to run ChainHead test: {:?}", e)); } #[test] diff --git a/store/postgres/tests/store.rs b/store/postgres/tests/store.rs index 9d3a54afe75..718ade9ea36 100644 --- a/store/postgres/tests/store.rs +++ b/store/postgres/tests/store.rs @@ -133,7 +133,7 @@ where }; runtime - .block_on(future::lazy(move || { + .block_on(async { // Reset state before starting remove_test_data(store.clone()); @@ -141,9 +141,9 @@ where insert_test_data(store.clone()); // Run test - test(store) - })) - .expect("Failed to run Store test"); + test(store).into_future().compat().await + }) + .unwrap_or_else(|e| panic!("Failed to run Store test: {:?}", e)); } /// Inserts test data into the store. @@ -1122,17 +1122,17 @@ fn make_deployment_change(entity_id: &str, op: EntityChangeOperation) -> EntityC fn check_events( stream: StoreEventStream + Send>, expected: Vec, -) -> impl Future> { +) -> impl Future { stream .take(expected.len() as u64) .collect() .timeout(Duration::from_secs(3)) - .and_then(move |events| { + .map_ok(move |events| { + let events = events.unwrap(); assert_eq!(events.len(), expected.len()); assert_eq!(events, expected); - Ok(()) }) - .and_then(|_| Ok(())) + .compat() } // Subscribe to store events from the store. This implementation works @@ -1205,7 +1205,7 @@ fn check_basic_revert( expected: StoreEvent, subgraph_id: &SubgraphDeploymentId, entity_type: &str, -) -> impl Future> { +) -> impl Future { let this_query = user_query() .filter(EntityFilter::Equal( "name".to_owned(), @@ -1804,7 +1804,7 @@ fn throttle_subscription_delivers() { #[test] fn throttle_subscription_throttles() { run_test( - |store| -> Box> + Send> { + |store| -> Box> + Send> { // Throttle for a very long time (30s) let subscription = subscribe_and_consume(store.clone(), &TEST_SUBGRAPH_ID, USER) .throttle_while_syncing( @@ -1839,10 +1839,9 @@ fn throttle_subscription_throttles() { .take(1) .collect() .timeout(Duration::from_millis(500)) + .compat() .then(|res| { assert!(res.is_err()); - let err = res.err().unwrap(); - assert!(err.is_elapsed()); future::ok(()) }), ) diff --git a/store/test-store/src/lib.rs b/store/test-store/src/lib.rs index d11c4702039..2655678d87e 100644 --- a/store/test-store/src/lib.rs +++ b/store/test-store/src/lib.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate diesel; -use crate::tokio::runtime::Runtime; +use crate::tokio::runtime::{Builder, Runtime}; use graph::log; use graph::prelude::{Store as _, *}; use graph_mock::MockMetricsRegistry; @@ -29,12 +29,11 @@ lazy_static! { None => Logger::root(slog::Discard, o!()), }; - // Use this for tests that need subscriptions from `STORE`. - pub static ref STORE_RUNTIME: Mutex = Mutex::new(Runtime::new().unwrap()); + pub static ref STORE_RUNTIME: Mutex = Mutex::new(Builder::new().basic_scheduler().enable_all().build().unwrap()); // Create Store instance once for use with each of the tests. pub static ref STORE: Arc = { - STORE_RUNTIME.lock().unwrap().block_on(future::lazy(|| -> Result<_, ()> { + STORE_RUNTIME.lock().unwrap().block_on(async { // Set up Store let logger = &*LOGGER; let postgres_url = postgres_test_url(); @@ -48,7 +47,7 @@ lazy_static! { conn_pool_size, &logger, ); - Ok(Arc::new(Store::new( + Arc::new(Store::new( StoreConfig { postgres_url, network_name: NETWORK_NAME.to_owned(), @@ -57,8 +56,8 @@ lazy_static! { net_identifiers, postgres_conn_pool, Arc::new(MockMetricsRegistry::new()), - ))) - })).expect("could not create Diesel Store instance for test suite") + )) + }) }; pub static ref GENESIS_PTR: EthereumBlockPointer = (