Chain head subscription (#126)

* Start WebSockets server.

* Expose non-working subscription.

* Dummy subscription for testing.

* Proper implementation with event loop.

* Finalized pubsub.

* Bump clap.

* Fix yml.

* Disable WS logs.

* Remove stale TransactionHash mention

* Fix build from nightly API change.

* Don't panic on invalid port.

* Bind server to random port.

* Send only best blocks.
This commit is contained in:
Tomasz Drwięga
2018-04-17 13:03:57 +02:00
committed by Gav Wood
parent eb6d142846
commit e253a4cb9f
18 changed files with 464 additions and 107 deletions
+96 -41
View File
@@ -16,6 +16,14 @@ name = "ansi_term"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "app_dirs"
version = "1.2.1"
@@ -155,10 +163,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "clap"
version = "2.29.4"
version = "2.31.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -206,13 +214,15 @@ dependencies = [
name = "demo-cli"
version = "0.1.0"
dependencies = [
"clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)",
"demo-executor 0.1.0",
"demo-primitives 0.1.0",
"demo-runtime 0.1.0",
"ed25519 0.1.0",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"hex-literal 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-client 0.1.0",
@@ -223,6 +233,7 @@ dependencies = [
"substrate-rpc-servers 0.1.0",
"substrate-runtime-io 0.1.0",
"substrate-state-machine 0.1.0",
"tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"triehash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -650,12 +661,12 @@ dependencies = [
[[package]]
name = "globset"
version = "0.2.1"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
@@ -724,7 +735,7 @@ dependencies = [
[[package]]
name = "hyper"
version = "0.11.17"
version = "0.11.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -813,11 +824,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "jsonrpc-core"
version = "8.0.1"
source = "git+https://github.com/paritytech/jsonrpc.git#d1e2cc48d962510328f7373509fb494a85dbeae8"
version = "8.0.2"
source = "git+https://github.com/paritytech/jsonrpc.git#9cfa451b0534281d83f7564bf41fda465a6e18c8"
dependencies = [
"futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -825,50 +836,64 @@ dependencies = [
[[package]]
name = "jsonrpc-http-server"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#d1e2cc48d962510328f7373509fb494a85dbeae8"
version = "8.0.1"
source = "git+https://github.com/paritytech/jsonrpc.git#9cfa451b0534281d83f7564bf41fda465a6e18c8"
dependencies = [
"hyper 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-server-utils 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)",
"unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jsonrpc-macros"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#d1e2cc48d962510328f7373509fb494a85dbeae8"
version = "8.0.1"
source = "git+https://github.com/paritytech/jsonrpc.git#9cfa451b0534281d83f7564bf41fda465a6e18c8"
dependencies = [
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-pubsub 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jsonrpc-pubsub"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#d1e2cc48d962510328f7373509fb494a85dbeae8"
version = "8.0.1"
source = "git+https://github.com/paritytech/jsonrpc.git#9cfa451b0534281d83f7564bf41fda465a6e18c8"
dependencies = [
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jsonrpc-server-utils"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#d1e2cc48d962510328f7373509fb494a85dbeae8"
version = "8.0.1"
source = "git+https://github.com/paritytech/jsonrpc.git#9cfa451b0534281d83f7564bf41fda465a6e18c8"
dependencies = [
"bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"globset 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
"tokio-io 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "jsonrpc-ws-server"
version = "8.0.0"
source = "git+https://github.com/paritytech/jsonrpc.git#9cfa451b0534281d83f7564bf41fda465a6e18c8"
dependencies = [
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-server-utils 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)",
]
[[package]]
name = "keccak-hash"
version = "0.1.0"
@@ -1190,7 +1215,7 @@ name = "polkadot-cli"
version = "0.1.0"
dependencies = [
"app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)",
"clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ctrlc 1.1.1 (git+https://github.com/paritytech/rust-ctrlc.git)",
"ed25519 0.1.0",
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1661,6 +1686,11 @@ dependencies = [
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sha1"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "shell32-sys"
version = "0.1.2"
@@ -1872,8 +1902,9 @@ version = "0.1.0"
dependencies = [
"assert_matches 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-macros 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-pubsub 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-client 0.1.0",
@@ -1881,14 +1912,18 @@ dependencies = [
"substrate-primitives 0.1.0",
"substrate-runtime-support 0.1.0",
"substrate-state-machine 0.1.0",
"tokio-core 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "substrate-rpc-servers"
version = "0.1.0"
dependencies = [
"jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-http-server 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-pubsub 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)",
"jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)",
"log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"substrate-rpc 0.1.0",
]
@@ -2451,6 +2486,22 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ws"
version = "0.7.5"
source = "git+https://github.com/tomusdrw/ws-rs#f12d19c4c19422fc79af28a3181f598bc07ecd1e"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"httparse 1.2.4 (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.13 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)",
"sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
@@ -2489,6 +2540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4"
"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455"
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum app_dirs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e73a24bad9bd6a94d6395382a6c69fe071708ae4409f763c5475e14ee896313d"
"checksum arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)" = "06f59fe10306bb78facd90d28c2038ad23ffaaefa85bac43c8a434cde383334f"
@@ -2507,7 +2559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1b7db437d718977f6dc9b2e3fd6fc343c02ac6b899b73fdd2179163447bd9ce9"
"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0"
"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de"
"checksum clap 2.29.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b8f59bcebcfe4269b09f71dab0da15b355c75916a8f975d3876ce81561893ee"
"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum constant_time_eq 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8ff012e225ce166d4422e0e78419d901719760f62ae2b7969ca6b564d1b54a9e"
"checksum crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "24ce9782d4d5c53674646a6a4c1863a21a8fc0cb649b3c94dfc16e45071dea19"
@@ -2546,7 +2598,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum futures 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "0bab5b5e94f5c31fc764ba5dd9ad16568aae5d4825538c01d6bca680c9bf94a7"
"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum globset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "464627f948c3190ae3d04b1bc6d7dca2f785bda0ac01278e6db129ad383dbeb6"
"checksum globset 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e96ab92362c06811385ae9a34d2698e8a1160745e0c78fbb434a44c8de3fabc"
"checksum hashdb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d97be07c358c5b461268b4ce60304024c5fa5acfd4bd8cd743639f0252003cf5"
"checksum heapsize 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1679e6ea370dee694f91f1dc469bf94cf8f52051d147aec3e1f9497c6fc22461"
"checksum hex 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "459d3cf58137bb02ad4adeef5036377ff59f066dbb82517b7192e3a5462a2abc"
@@ -2554,7 +2606,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum hex-literal-impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2ea76da4c7f1a54d01d54985566d3fdd960b2bbd7b970da024821c883c2d9631"
"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37"
"checksum hyper 0.10.13 (registry+https://github.com/rust-lang/crates.io-index)" = "368cb56b2740ebf4230520e2b90ebb0461e69034d85d1945febd9b3971426db2"
"checksum hyper 0.11.17 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4de6edd503089841ebfa88341e1c00fb19b6bf93d820d908db15960fd31226"
"checksum hyper 0.11.25 (registry+https://github.com/rust-lang/crates.io-index)" = "549dbb86397490ce69d908425b9beebc85bbaad25157d67479d4995bb56fdf9a"
"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d"
"checksum igd 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "356a0dc23a4fa0f8ce4777258085d00a01ea4923b2efd93538fc44bf5e1bda76"
"checksum integer-sqrt 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8833702c315192502093b244e29c6ab9c55454adfe21b879a87a039ea8fe8520"
@@ -2563,11 +2615,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum isatty 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f2a233726c7bb76995cec749d59582e5664823b7245d4970354408f1d79a7a2"
"checksum itertools 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4833d6978da405305126af4ac88569b5d71ff758581ce5a987dbfa3755f694fc"
"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c"
"checksum jsonrpc-core 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-http-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-macros 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-pubsub 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-server-utils 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-core 8.0.2 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-http-server 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-macros 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-pubsub 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-server-utils 8.0.1 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum jsonrpc-ws-server 8.0.0 (git+https://github.com/paritytech/jsonrpc.git)" = "<none>"
"checksum keccak-hash 0.1.0 (git+https://github.com/paritytech/parity.git)" = "<none>"
"checksum keccak-hash 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f300c1f149cd9ca5214eed24f6e713a597517420fb8b15499824aa916259ec1"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
@@ -2635,6 +2688,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0"
"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5"
"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb"
"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c"
"checksum shell32-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9ee04b46101f57121c9da2b151988283b6beb79b34f5bb29a58ee48cb695122c"
"checksum slab 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6dbdd334bd28d328dad1c41b0ea662517883d8880d8533895ef96c8003dec9c4"
"checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
@@ -2688,6 +2742,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
"checksum ws 0.7.5 (git+https://github.com/tomusdrw/ws-rs)" = "<none>"
"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
"checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61"
"checksum xml-rs 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7ec6c39eaa68382c8e31e35239402c0a9489d4141a8ceb0c716099a0b515b562"
+5
View File
@@ -1,5 +1,10 @@
#!/bin/sh
# NOTE `cargo install wasm-gc` before running this script.
set -e
export CARGO_INCREMENTAL=0
cd demo/runtime/wasm && ./build.sh && cd ../../..
cd substrate/executor/wasm && ./build.sh && cd ../../..
cd substrate/test-runtime/wasm && ./build.sh && cd ../../..
+8 -5
View File
@@ -6,12 +6,15 @@ description = "Substrate Demo node implementation in Rust."
[dependencies]
clap = { version = "2.27", features = ["yaml"] }
env_logger = "0.4"
error-chain = "0.11"
log = "0.3"
hex-literal = "0.1"
triehash = "0.1"
ctrlc = { git = "https://github.com/paritytech/rust-ctrlc.git" }
ed25519 = { path = "../../substrate/ed25519" }
env_logger = "0.4"
futures = "0.1.17"
error-chain = "0.11"
hex-literal = "0.1"
log = "0.3"
tokio-core = "0.1.12"
triehash = "0.1"
substrate-client = { path = "../../substrate/client" }
substrate-codec = { path = "../../substrate/codec" }
substrate-runtime-io = { path = "../../substrate/runtime-io" }
+31 -12
View File
@@ -18,18 +18,21 @@
#![warn(missing_docs)]
extern crate env_logger;
extern crate ctrlc;
extern crate ed25519;
extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate triehash;
extern crate substrate_codec as codec;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_state_machine as state_machine;
extern crate substrate_client as client;
extern crate substrate_codec as codec;
extern crate substrate_primitives as primitives;
extern crate substrate_rpc;
extern crate substrate_rpc_servers as rpc;
extern crate demo_primitives;
extern crate substrate_runtime_io as runtime_io;
extern crate substrate_state_machine as state_machine;
extern crate demo_executor;
extern crate demo_primitives;
extern crate demo_runtime;
#[macro_use]
@@ -44,11 +47,12 @@ extern crate log;
pub mod error;
use std::sync::Arc;
use client::genesis;
use codec::Slicable;
use runtime_io::with_externalities;
use demo_runtime::{GenesisConfig, ConsensusConfig, CouncilConfig, DemocracyConfig,
SessionConfig, StakingConfig, BuildExternalities};
use client::genesis;
use futures::{Future, Sink, Stream};
struct DummyPool;
impl substrate_rpc::author::AuthorApi for DummyPool {
@@ -128,15 +132,30 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
(primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
};
let client = Arc::new(client::new_in_mem(executor, prepare_genesis)?);
let mut core = ::tokio_core::reactor::Core::new().expect("Unable to spawn event loop.");
let address = "127.0.0.1:9933".parse().unwrap();
let handler = rpc::rpc_handler(client.clone(), DummyPool, client);
let server = rpc::start_http(&address, handler)?;
let _rpc_servers = {
let handler = || {
let chain = rpc::apis::chain::Chain::new(client.clone(), core.remote());
rpc::rpc_handler(client.clone(), chain, DummyPool)
};
let http_address = "127.0.0.1:9933".parse().unwrap();
let ws_address = "127.0.0.1:9944".parse().unwrap();
(
rpc::start_http(&http_address, handler())?,
rpc::start_ws(&ws_address, handler())?
)
};
if let Some(_) = matches.subcommand_matches("validator") {
info!("Starting validator.");
server.wait();
return Ok(());
let (exit_send, exit) = futures::sync::mpsc::channel(1);
ctrlc::CtrlC::set_handler(move || {
exit_send.clone().send(()).wait().expect("Error sending exit notification");
});
core.run(exit.into_future()).expect("Error running informant event loop");
return Ok(())
}
println!("No command given.\n");
+1 -2
View File
@@ -355,7 +355,6 @@ impl<S: state_machine::Backend> BlockBuilder for ClientBlockBuilder<S>
#[cfg(test)]
mod tests {
use super::*;
use runtime_io::with_externalities;
use keyring::Keyring;
use codec::Slicable;
use client::in_mem::Backend as InMemory;
@@ -388,7 +387,7 @@ mod tests {
::client::new_in_mem(
LocalDispatch::new(),
|| {
let mut storage = genesis_config.build_externalities();
let storage = genesis_config.build_externalities();
let block = ::client::genesis::construct_genesis_block(&storage);
(substrate_primitives::block::Header::decode(&mut block.header.encode().as_ref()).expect("to_vec() always gives a valid serialisation; qed"), storage.into_iter().collect())
}
+6 -1
View File
@@ -40,7 +40,12 @@ args:
- rpc-port:
long: rpc-port
value_name: PORT
help: Specify RPC server TCP port
help: Specify HTTP RPC server TCP port
takes_value: true
- ws-port:
long: ws-port
value_name: PORT
help: Specify WebSockets RPC server TCP port
takes_value: true
- bootnodes:
long: bootnodes
+57 -22
View File
@@ -47,8 +47,9 @@ extern crate log;
pub mod error;
mod informant;
use std::path::{Path, PathBuf};
use std::io;
use std::net::SocketAddr;
use std::path::{Path, PathBuf};
use futures::sync::mpsc;
use futures::{Sink, Future, Stream};
use tokio_core::reactor;
@@ -117,43 +118,76 @@ pub fn run<I, T>(args: I) -> error::Result<()> where
});
config.roles = role;
config.network.boot_nodes = matches
.values_of("bootnodes")
.map_or(Default::default(), |v| v.map(|n| n.to_owned()).collect());
config.network.config_path = Some(network_path(&base_path).to_string_lossy().into());
config.network.net_config_path = config.network.config_path.clone();
{
config.network.boot_nodes = matches
.values_of("bootnodes")
.map_or(Default::default(), |v| v.map(|n| n.to_owned()).collect());
config.network.config_path = Some(network_path(&base_path).to_string_lossy().into());
config.network.net_config_path = config.network.config_path.clone();
let port = match matches.value_of("port") {
Some(port) => port.parse().expect("Invalid p2p port value specified."),
None => 30333,
};
config.network.listen_address = Some(SocketAddr::new("0.0.0.0".parse().unwrap(), port));
config.network.public_address = None;
config.network.client_version = format!("parity-polkadot/{}", crate_version!());
let port = match matches.value_of("port") {
Some(port) => port.parse().expect("Invalid p2p port value specified."),
None => 30333,
};
config.network.listen_address = Some(SocketAddr::new("0.0.0.0".parse().unwrap(), port));
config.network.public_address = None;
config.network.client_version = format!("parity-polkadot/{}", crate_version!());
}
config.keys = matches.values_of("key").unwrap_or_default().map(str::to_owned).collect();
let service = service::Service::new(config)?;
let mut address: SocketAddr = "127.0.0.1:9933".parse().unwrap();
if let Some(port) = matches.value_of("rpc-port") {
let rpc_port: u16 = port.parse().expect("Invalid RPC port value specified.");
address.set_port(rpc_port);
}
let handler = rpc::rpc_handler(service.client(), service.transaction_pool(), service.client());
let _server = rpc::start_http(&address, handler)?;
informant::start(&service, core.handle());
let (exit_send, exit) = mpsc::channel(1);
ctrlc::CtrlC::set_handler(move || {
exit_send.clone().send(()).wait().expect("Error sending exit notification");
});
let _rpc_servers = {
let http_address = parse_address("127.0.0.1:9933", "rpc-port", &matches)?;
let ws_address = parse_address("127.0.0.1:9944", "ws-port", &matches)?;
let handler = || {
let chain = rpc::apis::chain::Chain::new(service.client(), core.remote());
rpc::rpc_handler(service.client(), chain, service.transaction_pool())
};
(
start_server(http_address, |address| rpc::start_http(address, handler())),
start_server(ws_address, |address| rpc::start_ws(address, handler())),
)
};
core.run(exit.into_future()).expect("Error running informant event loop");
Ok(())
}
fn start_server<T, F>(mut address: SocketAddr, start: F) -> Result<T, io::Error> where
F: Fn(&SocketAddr) -> Result<T, io::Error>,
{
start(&address)
.or_else(|e| match e.kind() {
io::ErrorKind::AddrInUse |
io::ErrorKind::PermissionDenied => {
warn!("Unable to bind server to {}. Trying random port.", address);
address.set_port(0);
start(&address)
},
_ => Err(e),
})
}
fn parse_address(default: &str, port_param: &str, matches: &clap::ArgMatches) -> Result<SocketAddr, String> {
let mut address: SocketAddr = default.parse().unwrap();
if let Some(port) = matches.value_of(port_param) {
let port: u16 = port.parse().ok().ok_or(format!("Invalid port for --{} specified.", port_param))?;
address.set_port(port);
}
Ok(address)
}
fn keystore_path(base_path: &Path) -> PathBuf {
let mut path = base_path.to_owned();
path.push("keystore");
@@ -183,6 +217,7 @@ fn default_base_path() -> PathBuf {
fn init_logger(pattern: &str) {
let mut builder = env_logger::LogBuilder::new();
// Disable info logging by default for some modules:
builder.filter(Some("ws"), log::LogLevelFilter::Warn);
builder.filter(Some("hyper"), log::LogLevelFilter::Warn);
// Enable info for others.
builder.filter(None, log::LogLevelFilter::Info);
+1 -1
View File
@@ -33,7 +33,7 @@ use {error, in_mem, block_builder, runtime_io, bft};
pub type BlockchainEventStream = mpsc::UnboundedReceiver<BlockImportNotification>;
/// Polkadot Client
pub struct Client<B, E> where B: backend::Backend {
pub struct Client<B, E> {
backend: B,
executor: E,
import_notification_sinks: Mutex<Vec<mpsc::UnboundedSender<BlockImportNotification>>>,
+5 -2
View File
@@ -4,6 +4,9 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
jsonrpc-core = { git = "https://github.com/paritytech/jsonrpc.git" }
jsonrpc-http-server = { git = "https://github.com/paritytech/jsonrpc.git" }
jsonrpc-pubsub = { git = "https://github.com/paritytech/jsonrpc.git" }
jsonrpc-ws-server = { git = "https://github.com/paritytech/jsonrpc.git" }
log = "0.3"
substrate-rpc = { path = "../rpc", version = "0.1" }
jsonrpc-core = { git="https://github.com/paritytech/jsonrpc.git" }
jsonrpc-http-server = { git="https://github.com/paritytech/jsonrpc.git" }
+36 -7
View File
@@ -18,30 +18,42 @@
#[warn(missing_docs)]
extern crate substrate_rpc as apis;
pub extern crate substrate_rpc as apis;
extern crate jsonrpc_core as rpc;
extern crate jsonrpc_http_server as http;
extern crate jsonrpc_pubsub as pubsub;
extern crate jsonrpc_ws_server as ws;
#[macro_use]
extern crate log;
use std::io;
type Metadata = apis::metadata::Metadata;
type RpcHandler = pubsub::PubSubHandler<Metadata>;
/// Construct rpc `IoHandler`
pub fn rpc_handler<S, T, C>(state: S, transaction_pool: T, chain: C) -> rpc::IoHandler where
pub fn rpc_handler<S, C, A>(
state: S,
chain: C,
author: A,
) -> RpcHandler where
S: apis::state::StateApi,
T: apis::author::AuthorApi,
C: apis::chain::ChainApi,
C: apis::chain::ChainApi<Metadata=Metadata>,
A: apis::author::AuthorApi,
{
let mut io = rpc::IoHandler::new();
let mut io = pubsub::PubSubHandler::default();
io.extend_with(state.to_delegate());
io.extend_with(transaction_pool.to_delegate());
io.extend_with(chain.to_delegate());
io.extend_with(author.to_delegate());
io
}
/// Start HTTP server listening on given address.
pub fn start_http(
addr: &std::net::SocketAddr,
io: rpc::IoHandler,
io: RpcHandler,
) -> io::Result<http::Server> {
http::ServerBuilder::new(io)
.threads(4)
@@ -49,3 +61,20 @@ pub fn start_http(
.cors(http::DomainsValidation::Disabled)
.start_http(addr)
}
/// Start WS server listening on given address.
pub fn start_ws(
addr: &std::net::SocketAddr,
io: RpcHandler,
) -> io::Result<ws::Server> {
ws::ServerBuilder::with_meta_extractor(io, |context: &ws::RequestContext| Metadata::new(context.sender()))
.start(addr)
.map_err(|err| match err {
ws::Error(ws::ErrorKind::Io(io), _) => io,
ws::Error(ws::ErrorKind::ConnectionClosed, _) => io::ErrorKind::BrokenPipe.into(),
ws::Error(e, _) => {
error!("{}", e);
io::ErrorKind::Other.into()
}
})
}
+5 -3
View File
@@ -4,15 +4,17 @@ version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
parking_lot = "0.4"
log = "0.3"
error-chain = "0.11"
jsonrpc-core = { git="https://github.com/paritytech/jsonrpc.git" }
jsonrpc-macros = { git="https://github.com/paritytech/jsonrpc.git" }
jsonrpc-pubsub = { git="https://github.com/paritytech/jsonrpc.git" }
log = "0.3"
parking_lot = "0.4"
substrate-client = { path = "../client" }
substrate-executor = { path = "../executor" }
substrate-primitives = { path = "../primitives" }
substrate-state-machine = { path = "../state-machine" }
substrate-executor = { path = "../executor" }
tokio-core = "0.1.12"
[dev-dependencies]
assert_matches = "1.1"
@@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Authoring RPC module errors.
use client;
use rpc;
+1 -2
View File
@@ -15,7 +15,6 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use primitives::block;
use substrate_executor as executor;
use super::*;
use super::error::*;
@@ -38,7 +37,7 @@ impl AsyncAuthorApi for DummyTxPool {
#[test]
fn submit_transaction_should_not_cause_error() {
let mut p = Arc::new(Mutex::new(DummyTxPool::default()));
let p = Arc::new(Mutex::new(DummyTxPool::default()));
assert_matches!(
AuthorApi::submit_extrinsic(&p, block::Extrinsic(vec![])),
+63 -5
View File
@@ -17,12 +17,20 @@
//! Substrate blockchain API.
use std::sync::Arc;
use primitives::block;
use client::{self, Client};
use client::{self, Client, BlockchainEvents};
use state_machine;
mod error;
use jsonrpc_macros::pubsub;
use jsonrpc_pubsub::SubscriptionId;
use rpc::Result as RpcResult;
use rpc::futures::{Future, Sink, Stream};
use tokio_core::reactor::Remote;
use subscriptions::Subscriptions;
mod error;
#[cfg(test)]
mod tests;
@@ -31,6 +39,8 @@ use self::error::{Result, ResultExt};
build_rpc_trait! {
/// Polkadot blockchain API
pub trait ChainApi {
type Metadata;
/// Get header of a relay chain block.
#[rpc(name = "chain_getHeader")]
fn header(&self, block::HeaderHash) -> Result<Option<block::Header>>;
@@ -38,19 +48,67 @@ build_rpc_trait! {
/// Get hash of the head.
#[rpc(name = "chain_getHead")]
fn head(&self) -> Result<block::HeaderHash>;
#[pubsub(name = "chain_newHead")] {
/// Hello subscription
#[rpc(name = "subscribe_newHead")]
fn subscribe_new_head(&self, Self::Metadata, pubsub::Subscriber<block::Header>);
/// Unsubscribe from hello subscription.
#[rpc(name = "unsubscribe_newHead")]
fn unsubscribe_new_head(&self, SubscriptionId) -> RpcResult<bool>;
}
}
}
impl<B, E> ChainApi for Arc<Client<B, E>> where
/// Chain API with subscriptions support.
pub struct Chain<B, E> {
/// Substrate client.
client: Arc<Client<B, E>>,
/// Current subscriptions.
subscriptions: Subscriptions,
}
impl<B, E> Chain<B, E> {
/// Create new Chain API RPC handler.
pub fn new(client: Arc<Client<B, E>>, remote: Remote) -> Self {
Chain {
client,
subscriptions: Subscriptions::new(remote),
}
}
}
impl<B, E> ChainApi for Chain<B, E> where
B: client::backend::Backend + Send + Sync + 'static,
E: state_machine::CodeExecutor + Send + Sync + 'static,
client::error::Error: From<<<B as client::backend::Backend>::State as state_machine::backend::Backend>::Error>,
{
type Metadata = ::metadata::Metadata;
fn header(&self, hash: block::HeaderHash) -> Result<Option<block::Header>> {
client::Client::header(self, &block::Id::Hash(hash)).chain_err(|| "Blockchain error")
self.client.header(&block::Id::Hash(hash)).chain_err(|| "Blockchain error")
}
fn head(&self) -> Result<block::HeaderHash> {
Ok(client::Client::info(self).chain_err(|| "Blockchain error")?.chain.best_hash)
Ok(self.client.info().chain_err(|| "Blockchain error")?.chain.best_hash)
}
fn subscribe_new_head(&self, _metadata: Self::Metadata, subscriber: pubsub::Subscriber<block::Header>) {
self.subscriptions.add(subscriber, |sink| {
let stream = self.client.import_notification_stream()
.filter(|notification| notification.is_new_best)
.map(|notification| Ok(notification.header))
.map_err(|e| warn!("Block notification stream error: {:?}", e));
sink
.sink_map_err(|e| warn!("Error sending notifications: {:?}", e))
.send_all(stream)
// we ignore the resulting Stream (if the first stream is over we are unsubscribed)
.map(|_| ())
});
}
fn unsubscribe_new_head(&self, id: SubscriptionId) -> RpcResult<bool> {
Ok(self.subscriptions.cancel(id))
}
}
+7 -1
View File
@@ -29,7 +29,13 @@ fn should_return_header() {
digest: Default::default(),
};
let client = Arc::new(client::new_in_mem(executor::WasmExecutor, || (test_genesis_block.clone(), vec![])).unwrap());
let core = ::tokio_core::reactor::Core::new().unwrap();
let remote = core.remote();
let client = Chain {
client: Arc::new(client::new_in_mem(executor::WasmExecutor, || (test_genesis_block.clone(), vec![])).unwrap()),
subscriptions: Subscriptions::new(remote),
};
assert_matches!(
ChainApi::header(&client, test_genesis_block.blake2_256().into()),
+8 -3
View File
@@ -18,11 +18,13 @@
#![warn(missing_docs)]
extern crate parking_lot;
extern crate jsonrpc_core as rpc;
extern crate jsonrpc_pubsub;
extern crate parking_lot;
extern crate substrate_client as client;
extern crate substrate_primitives as primitives;
extern crate substrate_state_machine as state_machine;
extern crate tokio_core;
#[macro_use]
extern crate error_chain;
@@ -39,6 +41,9 @@ extern crate assert_matches;
#[cfg(test)]
extern crate substrate_runtime_support as runtime_support;
pub mod chain;
pub mod state;
mod subscriptions;
pub mod author;
pub mod chain;
pub mod metadata;
pub mod state;
+46
View File
@@ -0,0 +1,46 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! RPC Metadata
use std::sync::Arc;
use jsonrpc_pubsub::{Session, PubSubMetadata};
/// RPC Metadata.
///
/// Manages peristent session for transports that support it
/// and may contain some additional info extracted from specific transports
/// (like remote client IP address, request headers, etc)
#[derive(Default, Clone)]
pub struct Metadata {
session: Option<Arc<Session>>,
}
impl ::rpc::Metadata for Metadata {}
impl PubSubMetadata for Metadata {
fn session(&self) -> Option<Arc<Session>> {
self.session.clone()
}
}
impl Metadata {
/// Create new `Metadata` with session (Pub/Sub) support.
pub fn new(transport: ::rpc::futures::sync::mpsc::Sender<String>) -> Self {
Metadata {
session: Some(Arc::new(Session::new(transport))),
}
}
}
@@ -0,0 +1,86 @@
// Copyright 2017-2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use std::collections::HashMap;
use std::sync::atomic::{self, AtomicUsize};
use jsonrpc_macros::pubsub;
use jsonrpc_pubsub::SubscriptionId;
use parking_lot::Mutex;
use rpc::futures::sync::oneshot;
use rpc::futures::{Future, future};
use tokio_core::reactor::Remote;
type Id = u64;
/// Subscriptions manager.
///
/// Takes care of assigning unique subscription ids and
/// driving the sinks into completion.
#[derive(Debug)]
pub struct Subscriptions {
next_id: AtomicUsize,
active_subscriptions: Mutex<HashMap<Id, oneshot::Sender<()>>>,
event_loop: Remote,
}
impl Subscriptions {
/// Creates new `Subscriptions` object.
pub fn new(event_loop: Remote) -> Self {
Subscriptions {
next_id: Default::default(),
active_subscriptions: Default::default(),
event_loop,
}
}
/// Creates new subscription for given subscriber.
///
/// Second parameter is a function that converts Subscriber sink into a future.
/// This future will be driven to completion bu underlying event loop
/// or will be cancelled in case #cancel is invoked.
pub fn add<T, E, G, R, F>(&self, subscriber: pubsub::Subscriber<T, E>, into_future: G) where
G: FnOnce(pubsub::Sink<T, E>) -> R,
R: future::IntoFuture<Future=F, Item=(), Error=()>,
F: future::Future<Item=(), Error=()> + Send + 'static,
{
let id = self.next_id.fetch_add(1, atomic::Ordering::AcqRel) as u64;
if let Ok(sink) = subscriber.assign_id(id.into()) {
let (tx, rx) = oneshot::channel();
let future = into_future(sink)
.into_future()
.select(rx.map_err(|e| warn!("Error timeing out: {:?}", e)))
.map(|_| ())
.map_err(|_| ());
self.active_subscriptions.lock().insert(id, tx);
self.event_loop.spawn(|_| future);
}
}
/// Cancel subscription.
///
/// Returns true if subscription existed or false otherwise.
pub fn cancel(&self, id: SubscriptionId) -> bool {
if let SubscriptionId::Number(id) = id {
if let Some(tx) = self.active_subscriptions.lock().remove(&id) {
let _ = tx.send(());
return true;
}
}
false
}
}