Additional Durable Functions implementation.
This commit continues the Durable Functions implementation: * Changes `azure-functions-durable` crate to use the released version of the `hyper` crate, but with the 0.1.0 futures-compatibility layer. This fixes the issue where the reactor could not be found for the client with a 0.1.0 futures-based tokio reactor that is being used by the Azure Functions for Rust runtime. * Implement the `DurableOrchestrationClient` binding to wrap an `OrchestrationClient` and provide the `start_new` method. More methods will be implemented later. * Implement the `DurableActivityContext` binding to extract the instance identifier and input from the binding data. * Implemented a mechanism for outer orchestration futures to control inner futures for updating the current orchestration event, which should occur immediately after the future is ready. * Implemented proper replay detection. * Implemented the `join_all` method on `DurableOrchestrationContext`. * Implemented the Durable Functions example (still needs documentation). * Various clippy and code clean up fixes.
This commit is contained in:
parent
e1dd374796
commit
60b5678248
|
@ -21,26 +21,18 @@ name = "approx"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atty"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -48,6 +40,7 @@ name = "azure-functions"
|
|||
version = "0.10.0"
|
||||
dependencies = [
|
||||
"azure-functions-codegen 0.10.0",
|
||||
"azure-functions-durable 0.10.0",
|
||||
"azure-functions-shared 0.10.0",
|
||||
"backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -62,8 +55,8 @@ dependencies = [
|
|||
"matches 0.1.8 (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.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -85,6 +78,24 @@ dependencies = [
|
|||
"syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azure-functions-durable"
|
||||
version = "0.10.0"
|
||||
dependencies = [
|
||||
"chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mockito 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-core 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "azure-functions-sdk"
|
||||
version = "0.10.0"
|
||||
|
@ -112,7 +123,6 @@ dependencies = [
|
|||
"prost-types 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tower-grpc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -135,7 +145,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"backtrace-sys 0.1.32 (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.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -144,8 +154,8 @@ name = "backtrace-sys"
|
|||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -210,16 +220,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "c2-chacha"
|
||||
version = "0.2.2"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.46"
|
||||
version = "1.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -242,7 +251,7 @@ name = "chrono"
|
|||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -276,7 +285,7 @@ name = "codegen"
|
|||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -299,23 +308,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.7.1"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.7.2"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"autocfg 0.1.7 (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.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.7.0 (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.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -336,6 +345,16 @@ dependencies = [
|
|||
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (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)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctrlc"
|
||||
version = "3.1.3"
|
||||
|
@ -345,6 +364,66 @@ dependencies = [
|
|||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"darling_macro 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ident_case 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"derive_builder_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder_core"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difference"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.8.1"
|
||||
|
@ -360,6 +439,7 @@ dependencies = [
|
|||
"azure-functions 0.10.0",
|
||||
"futures-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -455,7 +535,7 @@ version = "0.1.8"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -465,7 +545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
dependencies = [
|
||||
"futures-core-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -525,11 +605,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.12"
|
||||
version = "0.1.13"
|
||||
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)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -543,7 +623,7 @@ dependencies = [
|
|||
"fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"indexmap 1.3.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)",
|
||||
"string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -578,7 +658,15 @@ name = "heck"
|
|||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -657,21 +745,39 @@ dependencies = [
|
|||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.2.0"
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iovec"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.8.0"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -698,7 +804,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.64"
|
||||
version = "0.2.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -727,6 +833,11 @@ name = "matches"
|
|||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "maybe-uninit"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.2.1"
|
||||
|
@ -734,7 +845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -749,7 +860,7 @@ dependencies = [
|
|||
"fuchsia-zircon-sys 0.3.3 (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)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (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)",
|
||||
"net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -763,7 +874,7 @@ version = "0.6.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -778,6 +889,22 @@ dependencies = [
|
|||
"ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockito"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"httparse 1.3.4 (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)",
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multimap"
|
||||
version = "0.4.0"
|
||||
|
@ -789,7 +916,7 @@ version = "0.2.33"
|
|||
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)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -799,23 +926,18 @@ version = "0.14.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.47 (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.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nodrop"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -832,15 +954,16 @@ name = "num-traits"
|
|||
version = "0.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -865,10 +988,10 @@ 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)",
|
||||
"cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -931,7 +1054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -967,7 +1090,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)",
|
||||
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -983,7 +1106,7 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1033,7 +1156,7 @@ version = "0.4.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1044,8 +1167,8 @@ name = "rand"
|
|||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1056,7 +1179,7 @@ name = "rand_chacha"
|
|||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1078,7 +1201,7 @@ name = "rand_core"
|
|||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1157,6 +1280,11 @@ dependencies = [
|
|||
"winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.0.0"
|
||||
|
@ -1210,6 +1338,16 @@ dependencies = [
|
|||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6 (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.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "service-bus-example"
|
||||
version = "0.1.0"
|
||||
|
@ -1235,7 +1373,6 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"azure-functions 0.10.0",
|
||||
"serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1246,8 +1383,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "0.6.10"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string"
|
||||
|
@ -1257,6 +1397,11 @@ dependencies = [
|
|||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.8.0"
|
||||
|
@ -1306,7 +1451,7 @@ version = "3.1.0"
|
|||
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)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1334,7 +1479,7 @@ name = "time"
|
|||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -1355,7 +1500,7 @@ dependencies = [
|
|||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.11.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)",
|
||||
"tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1390,6 +1535,24 @@ dependencies = [
|
|||
"tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-core"
|
||||
version = "0.1.17"
|
||||
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.29 (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.19 (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.8 (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.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-current-thread"
|
||||
version = "0.1.6"
|
||||
|
@ -1438,7 +1601,7 @@ dependencies = [
|
|||
"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.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1473,13 +1636,13 @@ name = "tokio-threadpool"
|
|||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.29 (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)",
|
||||
"num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -1517,7 +1680,7 @@ dependencies = [
|
|||
"bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"futures 0.1.29 (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.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (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.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1646,9 +1809,25 @@ name = "ucd-trie"
|
|||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.3.0"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
|
@ -1666,6 +1845,16 @@ name = "unicode-xid"
|
|||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vec_map"
|
||||
version = "0.8.1"
|
||||
|
@ -1707,7 +1896,7 @@ version = "2.0.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1776,9 +1965,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
||||
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
|
||||
"checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94"
|
||||
"checksum arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9"
|
||||
"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90"
|
||||
"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875"
|
||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
||||
"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e"
|
||||
|
@ -1788,8 +1976,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"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 c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101"
|
||||
"checksum cc 1.0.46 (registry+https://github.com/rust-lang/crates.io-index)" = "0213d356d3c4ea2c18c40b037c3be23cd639825c18f25ee670ac7813beeef99c"
|
||||
"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb"
|
||||
"checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8"
|
||||
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
"checksum cgmath 0.16.1 (registry+https://github.com/rust-lang/crates.io-index)" = "64a4b57c8f4e3a2e9ac07e0f6abc9c24b6fc9e1b54c3478cfb598f3d0023e51c"
|
||||
"checksum chrono 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e8493056968583b0193c1bb04d6f7684586f3726992d6c573261941a895dbd68"
|
||||
|
@ -1797,11 +1985,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
|
||||
"checksum codegen 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bf02acd61125952ee148207cd411f9b73c9e218eab4b901375a82e1a443b6238"
|
||||
"checksum colored 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6cdb90b60f2927f8d76139c72dbde7e10c3a2bc47c8594c9c7a66529f2687c03"
|
||||
"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71"
|
||||
"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9"
|
||||
"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca"
|
||||
"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac"
|
||||
"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b"
|
||||
"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6"
|
||||
"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4"
|
||||
"checksum ctrlc 3.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c7dfd2d8b4c82121dfdff120f818e09fc4380b0b7e17a742081a89b94853e87f"
|
||||
"checksum darling 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fcfbcb0c5961907597a7d1148e3af036268f2b773886b8bb3eeb1e1281d3d3d6"
|
||||
"checksum darling_core 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6afc018370c3bff3eb51f89256a6bdb18b4fdcda72d577982a14954a7a0b402c"
|
||||
"checksum darling_macro 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6d8dac1c6f1d29a41c4712b4400f878cb4fcc4c7628f298dd75038e024998d1"
|
||||
"checksum derive_builder 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ac53fa6a3cda160df823a9346442525dcaf1e171999a1cf23e67067e4fd64d4"
|
||||
"checksum derive_builder_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0288a23da9333c246bb18c143426074a6ae96747995c5819d2947b64cd942b37"
|
||||
"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198"
|
||||
"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||
"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
|
||||
|
@ -1822,40 +2017,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum futures-sink-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec"
|
||||
"checksum futures-util-preview 0.3.0-alpha.19 (registry+https://github.com/rust-lang/crates.io-index)" = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d"
|
||||
"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec"
|
||||
"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
|
||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||
"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462"
|
||||
"checksum handlebars 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "91ef1ac30f2eaaa2b835fce73c57091cb6b9fc62b7eef285efbf980b0f20001b"
|
||||
"checksum hashbrown 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353"
|
||||
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
|
||||
"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120"
|
||||
"checksum http 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "d7e06e336150b178206af098a055e3621e8336027e2b4d126bda0bc64824baaf"
|
||||
"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
|
||||
"checksum http-connection 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5f6080cea47f7371d4da9a46dd52787c598ce93886393e400bc178f9039bac27"
|
||||
"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9"
|
||||
"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6"
|
||||
"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3"
|
||||
"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 indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2"
|
||||
"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
|
||||
"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358"
|
||||
"checksum itertools 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "87fa75c9dea7b07be3138c49abbb83fd4bea199b5cdc76f9804458edc5da0d6e"
|
||||
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
|
||||
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
|
||||
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
"checksum libc 0.2.64 (registry+https://github.com/rust-lang/crates.io-index)" = "74dfca3d9957906e8d1e6a0b641dc9a59848e793f1da2165889fd4f62d10d79c"
|
||||
"checksum libc 0.2.65 (registry+https://github.com/rust-lang/crates.io-index)" = "1a31a0627fdf1f6a39ec0dd577e101440b7db22672c0901fe00a9a6fbb5c24e8"
|
||||
"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
|
||||
"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||
"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
|
||||
"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
|
||||
"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||
"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
|
||||
"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f"
|
||||
"checksum memoffset 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a85c1a8c329f11437034d7313dca647c79096523533a1c79e86f1d0f657c7cc"
|
||||
"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23"
|
||||
"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 mockito 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4d910005896c16bb589e560173d10a7d5a4e747ea6f0c734ddcd9ad91b45e976"
|
||||
"checksum multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151"
|
||||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||
"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
||||
"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31"
|
||||
"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
|
||||
"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
|
||||
"checksum num_cpus 1.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "155394f924cdddf08149da25bfb932d226b4a593ca7468b08191ff6335941af5"
|
||||
"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252"
|
||||
"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b"
|
||||
|
@ -1866,7 +2065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547"
|
||||
"checksum petgraph 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "9c3659d1ee90221741f65dd128d9998311b0e40c5d3c23a62445938214abce4f"
|
||||
"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
|
||||
"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b"
|
||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27"
|
||||
"checksum prost 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "96d14b1c185652833d24aaad41c5832b0be5616a590227c1fbff57c616754b23"
|
||||
|
@ -1893,16 +2092,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8"
|
||||
"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421"
|
||||
"checksum scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28"
|
||||
"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4b39bd9b0b087684013a792c59e3e07a46a01d2322518d8a1104641a0b1be0"
|
||||
"checksum serde_derive 1.0.102 (registry+https://github.com/rust-lang/crates.io-index)" = "ca13fc1a832f793322228923fbb3aba9f3f44444898f835d31ad1b74fa0a2bf8"
|
||||
"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2"
|
||||
"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573"
|
||||
"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68"
|
||||
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||
"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
|
||||
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
||||
"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d"
|
||||
"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
"checksum syn 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0e7bedb3320d0f3035594b0b723c8a28d7d336a3eda3881db79e61d676fb644c"
|
||||
|
@ -1914,6 +2116,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6"
|
||||
"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"
|
||||
"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443"
|
||||
"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac"
|
||||
"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af"
|
||||
|
@ -1936,10 +2139,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382"
|
||||
"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9"
|
||||
"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2"
|
||||
"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9"
|
||||
"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5"
|
||||
"checksum unicode-normalization 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09c8070a9942f5e7cfccd93f490fdebd230ee3c3c9f107cb25bad5351ef671cf"
|
||||
"checksum unicode-segmentation 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49f5526225fd8b77342d5986ab5f6055552e9c0776193b5b63fd53b46debfad7"
|
||||
"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20"
|
||||
"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||
"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c"
|
||||
"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a"
|
||||
"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a"
|
||||
"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"
|
||||
|
|
|
@ -78,7 +78,7 @@ fn validate_orchestration_function(func: &ItemFn) {
|
|||
);
|
||||
}
|
||||
|
||||
if let ReturnType::Type(_, ty) = &func.sig.decl.output {
|
||||
if let ReturnType::Type(_, ty) = &func.sig.output {
|
||||
match ty.as_ref() {
|
||||
Type::Path(tp) => {
|
||||
if last_segment_in_path(&tp.path).ident != ORCHESTRATION_OUTPUT_TYPE {
|
||||
|
@ -135,7 +135,7 @@ fn validate_activity_function(func: &ItemFn) {
|
|||
}
|
||||
}
|
||||
|
||||
if let ReturnType::Type(_, ty) = &func.decl.output {
|
||||
if let ReturnType::Type(_, ty) = &func.sig.output {
|
||||
validate_return_binding(&*ty);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,8 +9,8 @@ homepage = "https://functions.rs"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
futures-preview = { version = "0.3.0-alpha.17" }
|
||||
hyper = { git = "https://github.com/hyperium/hyper", rev = "1d00bb29d4f5d123ddd04d7f78de3b1a98fe7dfb", features=["runtime"] }
|
||||
futures-preview = { version = "0.3.0-alpha.17", features = ["compat"] }
|
||||
hyper = "0.12.33"
|
||||
serde = { version="1.0.97", features = ["derive"] }
|
||||
serde_json = "1.0.40"
|
||||
tokio = "0.1.22"
|
||||
|
|
|
@ -2,38 +2,20 @@
|
|||
#![feature(async_await)]
|
||||
#![feature(result_map_or_else)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate derive_builder;
|
||||
extern crate hyper;
|
||||
//extern crate hyper_tls;
|
||||
extern crate futures;
|
||||
|
||||
use crate::futures::FutureExt;
|
||||
use crate::futures::TryFutureExt;
|
||||
use crate::futures::TryStreamExt;
|
||||
use chrono::prelude::*;
|
||||
use futures::{future, Future};
|
||||
use log::{debug, info, warn};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{from_slice, from_str, Map, Value};
|
||||
use std::fmt::{Debug, Display, Formatter};
|
||||
use derive_builder::Builder;
|
||||
use futures::{
|
||||
compat::{Future01CompatExt, Stream01CompatExt},
|
||||
TryStreamExt,
|
||||
};
|
||||
use hyper::{client::HttpConnector, Body, Client, Request, StatusCode};
|
||||
use log::debug;
|
||||
use serde::Deserialize;
|
||||
use serde_json::{from_slice, to_string, Map, Value};
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::result::Result::*;
|
||||
use url::Url;
|
||||
|
||||
//use hyper_tls::HttpsConnector;
|
||||
use hyper::{client::HttpConnector, Body, Client, Request, StatusCode, Uri};
|
||||
|
||||
static EVENT_NAME_PLACEHOLDER: &'static str = "{eventName}";
|
||||
static FUNC_NAME_PLACEHOLDER: &'static str = "{functionName}";
|
||||
static INSTANCE_ID_PLACEHOLDER: &'static str = "[/{instanceId}]";
|
||||
static REASON_PLACEHOLDER: &'static str = "{text}";
|
||||
static CREATED_TIME_FROM_KEY: &'static str = "createdTimeFrom";
|
||||
static CREATED_TIME_TO_KEY: &'static str = "createdTimeTo";
|
||||
static RUNTIME_STATUS_KEY: &'static str = "runtimeStatus";
|
||||
static SHOW_HISTORY_KEY: &'static str = "showHistory";
|
||||
static SHOW_HISTORY_OUTPUT_KEY: &'static str = "showHistoryOutput";
|
||||
static SHOW_INPUT_KEY: &'static str = "showInput";
|
||||
|
||||
#[derive(Debug, Clone, Builder)]
|
||||
pub(crate) struct OrchestrationEndpoint {
|
||||
base_uri: Url,
|
||||
|
@ -197,12 +179,10 @@ pub enum OrchestrationRuntimeStatus {
|
|||
impl Display for OrchestrationRuntimeStatus {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
// or, alternatively:
|
||||
// fmt::Debug::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum OrchestrationClientError {
|
||||
//400
|
||||
InstanceFailedOrTerminated,
|
||||
|
@ -218,6 +198,32 @@ pub enum OrchestrationClientError {
|
|||
InvalidResponse,
|
||||
}
|
||||
|
||||
impl Display for OrchestrationClientError {
|
||||
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
OrchestrationClientError::InstanceFailedOrTerminated => {
|
||||
write!(f, "instance failed or terminated")
|
||||
}
|
||||
OrchestrationClientError::InstanceCompletedOrFailed => {
|
||||
write!(f, "instance completed or failed")
|
||||
}
|
||||
OrchestrationClientError::InstanceNotFound => write!(f, "instance not found"),
|
||||
OrchestrationClientError::BadRaiseEventContent => write!(f, "bad raise event content"),
|
||||
OrchestrationClientError::UnspecifiedError => write!(f, "unspecified error"),
|
||||
OrchestrationClientError::CommunicationError(msg) => {
|
||||
write!(f, "communication error: {}", msg)
|
||||
}
|
||||
OrchestrationClientError::InvalidResponse => write!(f, "invalid response"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for OrchestrationClientError {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct OrchestrationHistoryEvent {
|
||||
|
@ -272,7 +278,7 @@ pub struct PurgeHistoryResult {
|
|||
instances_deleted: u32,
|
||||
}
|
||||
|
||||
type OrchestrationResult<T> = Result<T, OrchestrationClientError>;
|
||||
pub type OrchestrationResult<T> = Result<T, OrchestrationClientError>;
|
||||
|
||||
pub struct OrchestrationClient {
|
||||
endpoint: OrchestrationEndpoint,
|
||||
|
@ -311,7 +317,7 @@ impl OrchestrationClient {
|
|||
],
|
||||
)
|
||||
.unwrap();
|
||||
let client_builder = client_builder.unwrap_or(Client::builder());
|
||||
let client_builder = client_builder.unwrap_or_else(Client::builder);
|
||||
OrchestrationClient {
|
||||
endpoint: OrchestrationEndpoint::new_from_url(end_url),
|
||||
client: client_builder.build_http(),
|
||||
|
@ -354,7 +360,7 @@ impl OrchestrationClient {
|
|||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => match response.status() {
|
||||
StatusCode::OK
|
||||
|
@ -362,7 +368,7 @@ impl OrchestrationClient {
|
|||
| StatusCode::BAD_REQUEST
|
||||
| StatusCode::NOT_FOUND
|
||||
| StatusCode::INTERNAL_SERVER_ERROR => {
|
||||
let body = response.into_body().try_concat().await;
|
||||
let body = response.into_body().compat().try_concat().await;
|
||||
body.map_or_else(
|
||||
|e| {
|
||||
Err(OrchestrationClientError::CommunicationError(format!(
|
||||
|
@ -371,7 +377,7 @@ impl OrchestrationClient {
|
|||
)))
|
||||
},
|
||||
|b| {
|
||||
serde_json::from_slice::<OrchestrationStatus>(&b).map_err(|e2| {
|
||||
from_slice::<OrchestrationStatus>(&b).map_err(|e2| {
|
||||
OrchestrationClientError::CommunicationError(format!("{:?}", e2))
|
||||
})
|
||||
},
|
||||
|
@ -436,7 +442,7 @@ impl OrchestrationClient {
|
|||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => {
|
||||
if response.status() > StatusCode::ACCEPTED {
|
||||
|
@ -445,7 +451,7 @@ impl OrchestrationClient {
|
|||
response.status()
|
||||
)))
|
||||
} else {
|
||||
let body = response.into_body().try_concat().await;
|
||||
let body = response.into_body().compat().try_concat().await;
|
||||
body.map_or_else(
|
||||
|e| {
|
||||
Err(OrchestrationClientError::CommunicationError(format!(
|
||||
|
@ -454,7 +460,7 @@ impl OrchestrationClient {
|
|||
)))
|
||||
},
|
||||
|b| {
|
||||
serde_json::from_slice(&b).map_err(|e2| {
|
||||
from_slice(&b).map_err(|e2| {
|
||||
OrchestrationClientError::CommunicationError(format!("{:?}", e2))
|
||||
})
|
||||
},
|
||||
|
@ -488,11 +494,11 @@ impl OrchestrationClient {
|
|||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => match response.status() {
|
||||
StatusCode::OK => {
|
||||
let body = response.into_body().try_concat().await;
|
||||
let body = response.into_body().compat().try_concat().await;
|
||||
body.map_or_else(
|
||||
|e| {
|
||||
Err(OrchestrationClientError::CommunicationError(format!(
|
||||
|
@ -501,7 +507,7 @@ impl OrchestrationClient {
|
|||
)))
|
||||
},
|
||||
|b| {
|
||||
serde_json::from_slice(&b).map_err(|e2| {
|
||||
from_slice(&b).map_err(|e2| {
|
||||
OrchestrationClientError::CommunicationError(format!("{:?}", e2))
|
||||
})
|
||||
},
|
||||
|
@ -556,11 +562,11 @@ impl OrchestrationClient {
|
|||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => match response.status() {
|
||||
StatusCode::OK => {
|
||||
let body = response.into_body().try_concat().await;
|
||||
let body = response.into_body().compat().try_concat().await;
|
||||
body.map_or_else(
|
||||
|e| {
|
||||
Err(OrchestrationClientError::CommunicationError(format!(
|
||||
|
@ -569,7 +575,7 @@ impl OrchestrationClient {
|
|||
)))
|
||||
},
|
||||
|b| {
|
||||
serde_json::from_slice(&b).map_err(|e2| {
|
||||
from_slice(&b).map_err(|e2| {
|
||||
OrchestrationClientError::CommunicationError(format!("{:?}", e2))
|
||||
})
|
||||
},
|
||||
|
@ -597,7 +603,7 @@ impl OrchestrationClient {
|
|||
query: InstanceQuery<'a>,
|
||||
) -> OrchestrationResult<()>
|
||||
where
|
||||
D: Into<serde_json::Value>,
|
||||
D: Into<Value>,
|
||||
{
|
||||
let raise_url = self.endpoint.raise_event_url(
|
||||
query.instance_id.unwrap(),
|
||||
|
@ -613,12 +619,10 @@ impl OrchestrationClient {
|
|||
.method("POST")
|
||||
.uri(raise_url.into_string())
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(
|
||||
serde_json::to_string(&event_data.into()).unwrap(),
|
||||
))
|
||||
.body(Body::from(to_string(&event_data.into()).unwrap()))
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => match response.status() {
|
||||
StatusCode::ACCEPTED => Ok(()),
|
||||
|
@ -659,7 +663,7 @@ impl OrchestrationClient {
|
|||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => match response.status() {
|
||||
StatusCode::ACCEPTED => Ok(()),
|
||||
|
@ -681,30 +685,29 @@ impl OrchestrationClient {
|
|||
&self,
|
||||
orchestrator_function_name: &str,
|
||||
instance_id: Option<&str>,
|
||||
input: Option<D>,
|
||||
input: D,
|
||||
) -> OrchestrationResult<String>
|
||||
where
|
||||
D: Into<serde_json::Value>,
|
||||
D: Into<Value>,
|
||||
{
|
||||
let creationUri = self
|
||||
let creation_uri = self
|
||||
.endpoint
|
||||
.create_new_instance_url(orchestrator_function_name, instance_id);
|
||||
let body_value = input.map_or("".to_owned(), |i| i.into().to_string());
|
||||
|
||||
let req = Request::builder()
|
||||
.method("POST")
|
||||
.uri(creationUri.into_string())
|
||||
.uri(creation_uri.into_string())
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(body_value))
|
||||
.body(Body::from(input.into().to_string()))
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => {
|
||||
if response.status() > StatusCode::ACCEPTED {
|
||||
Err(OrchestrationClientError::UnspecifiedError)
|
||||
} else {
|
||||
let body = response.into_body().try_concat().await;
|
||||
let body = response.into_body().compat().try_concat().await;
|
||||
body.map_or_else(
|
||||
|e| {
|
||||
Err(OrchestrationClientError::CommunicationError(format!(
|
||||
|
@ -769,7 +772,7 @@ impl OrchestrationClient {
|
|||
.body(Body::empty())
|
||||
.unwrap();
|
||||
|
||||
let res = self.client.request(req).await;
|
||||
let res = self.client.request(req).compat().await;
|
||||
match res {
|
||||
Ok(response) => match response.status() {
|
||||
StatusCode::ACCEPTED | StatusCode::GONE => Ok(()),
|
||||
|
@ -787,23 +790,16 @@ impl OrchestrationClient {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
use mockito;
|
||||
use std::ops::Deref;
|
||||
|
||||
#[cfg(test)]
|
||||
extern crate tokio;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use futures::future::lazy;
|
||||
use mockito::mock;
|
||||
use tokio;
|
||||
use tokio_core::reactor::Core;
|
||||
|
||||
use super::*;
|
||||
use futures::future::lazy;
|
||||
use hyper::rt;
|
||||
use hyper::{Body, Request, Response, Server};
|
||||
use mockito::mock;
|
||||
use serde_json::from_str;
|
||||
use tokio;
|
||||
use tokio_core::reactor::Core;
|
||||
|
||||
static EP_GOOD: &'static str = "http://localhost:7071/runtime/webhooks/durabletask/instances/INSTANCEID?taskHub=myHub&connection=Storage&code=myCode";
|
||||
static EP_BAD: &'static str =
|
||||
|
@ -816,7 +812,6 @@ mod tests {
|
|||
|
||||
let rewind_result = "http://localhost:7071/runtime/webhooks/durabletask/instances/1234/rewind?taskHub=myHub&connection=Storage&code=myCode&reason=myReason";
|
||||
let rewind_url = endpoint.rewind_url("1234", "myReason", None, None, None);
|
||||
println!("{:?}", rewind_url);
|
||||
assert_eq!(rewind_url.to_string(), rewind_result);
|
||||
}
|
||||
|
||||
|
@ -836,7 +831,7 @@ mod tests {
|
|||
|
||||
let compare_dt = Utc.ymd(2018, 2, 28).and_hms(5, 18, 49);
|
||||
|
||||
let h1_obj: OrchestrationHistoryEvent = serde_json::from_str(&h1).unwrap();
|
||||
let h1_obj: OrchestrationHistoryEvent = from_str(&h1).unwrap();
|
||||
assert_eq!(h1_obj.event_type, "ExecutionStarted");
|
||||
assert_eq!(h1_obj.timestamp, compare_dt);
|
||||
|
||||
|
@ -852,7 +847,7 @@ mod tests {
|
|||
}"#
|
||||
.to_owned();
|
||||
|
||||
let h2_obj: OrchestrationHistoryEvent = serde_json::from_str(&h2).unwrap();
|
||||
let h2_obj: OrchestrationHistoryEvent = from_str(&h2).unwrap();
|
||||
assert_eq!(h2_obj.orchestration_status.is_some(), true);
|
||||
assert_eq!(
|
||||
h2_obj.orchestration_status.unwrap(),
|
||||
|
@ -914,7 +909,7 @@ mod tests {
|
|||
}"#
|
||||
.to_owned();
|
||||
|
||||
let instance_status: OrchestrationStatus = serde_json::from_str(&example).unwrap();
|
||||
let instance_status: OrchestrationStatus = from_str(&example).unwrap();
|
||||
assert_eq!(instance_status.history_events.is_some(), true);
|
||||
assert_eq!(instance_status.history_events.unwrap().len(), 5);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ edition = "2018"
|
|||
[dependencies]
|
||||
azure-functions-shared = { version = "0.10.0", path = "../azure-functions-shared" }
|
||||
azure-functions-codegen = { version = "0.10.0", path = "../azure-functions-codegen" }
|
||||
azure-functions-durable = { version = "0.10.0", path = "../azure-functions-durable" }
|
||||
http = "0.1"
|
||||
tower-hyper = "0.1.1"
|
||||
tower-grpc = "0.1.1"
|
||||
|
@ -19,7 +20,7 @@ tower-util = "0.1.0"
|
|||
tower-request-modifier = "0.1.0"
|
||||
log = { version = "0.4.8", features = ["std"] }
|
||||
futures01 = { package = "futures", version = "0.1.28" }
|
||||
futures-preview = { version = "0.3.0-alpha.19", features = ["compat"], optional = true }
|
||||
futures-preview = { version = "0.3.0-alpha.19", features = ["compat"] }
|
||||
clap = "2.33.0"
|
||||
tokio = "0.1.22"
|
||||
tokio-threadpool = "0.1.16"
|
||||
|
@ -36,7 +37,7 @@ fs_extra = "1.1.0"
|
|||
semver = "0.9.0"
|
||||
|
||||
[features]
|
||||
unstable = ["azure-functions-codegen/unstable", "azure-functions-shared/unstable", "futures-preview"]
|
||||
unstable = ["azure-functions-codegen/unstable", "azure-functions-shared/unstable"]
|
||||
|
||||
[dev-dependencies]
|
||||
matches = "0.1.8"
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use crate::rpc::TypedData;
|
||||
use crate::rpc::{typed_data::Data, TypedData};
|
||||
use serde::Deserialize;
|
||||
use serde_json::{from_str, Number, Value};
|
||||
use std::collections::HashMap;
|
||||
|
||||
const INSTANCE_ID_KEY: &str = "instanceId";
|
||||
|
||||
/// Represents the Durable Functions activity context binding.
|
||||
///
|
||||
/// The following binding attributes are supported:
|
||||
|
@ -16,14 +19,32 @@ use std::collections::HashMap;
|
|||
/// TODO: IMPLEMENT
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DurableActivityContext {}
|
||||
pub struct DurableActivityContext {
|
||||
/// The input to the activity function.
|
||||
pub input: Value,
|
||||
/// The orchestration instance identifier.
|
||||
pub instance_id: String,
|
||||
}
|
||||
|
||||
impl DurableActivityContext {
|
||||
#[doc(hidden)]
|
||||
pub fn new(data: TypedData, metadata: HashMap<String, TypedData>) -> Self {
|
||||
println!("{:#?}", data);
|
||||
println!("{:#?}", metadata);
|
||||
DurableActivityContext {}
|
||||
pub fn new(data: TypedData, mut metadata: HashMap<String, TypedData>) -> Self {
|
||||
DurableActivityContext {
|
||||
input: match data.data {
|
||||
Some(Data::String(s)) => Value::String(s),
|
||||
Some(Data::Json(s)) => from_str(&s).unwrap_or(Value::Null),
|
||||
Some(Data::Int(i)) => Value::Number(i.into()),
|
||||
Some(Data::Double(d)) => Value::Number(Number::from_f64(d).unwrap()),
|
||||
_ => Value::Null,
|
||||
},
|
||||
instance_id: metadata
|
||||
.remove(INSTANCE_ID_KEY)
|
||||
.map(|data| match data.data {
|
||||
Some(Data::String(s)) => s,
|
||||
_ => panic!("expected a string for instance id"),
|
||||
})
|
||||
.expect("expected an instance id"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,11 +56,19 @@ mod tests {
|
|||
#[test]
|
||||
fn it_constructs() {
|
||||
let data = TypedData {
|
||||
data: Some(Data::String(r#"{ }"#.to_owned())),
|
||||
data: Some(Data::String("bar".to_string())),
|
||||
};
|
||||
|
||||
let _ = DurableActivityContext::new(data, HashMap::new());
|
||||
let mut metadata = HashMap::new();
|
||||
metadata.insert(
|
||||
INSTANCE_ID_KEY.to_string(),
|
||||
TypedData {
|
||||
data: Some(Data::String("foo".to_string())),
|
||||
},
|
||||
);
|
||||
|
||||
// TODO: implement
|
||||
let context = DurableActivityContext::new(data, metadata);
|
||||
assert_eq!(context.instance_id, "foo");
|
||||
assert_eq!(context.input, Value::String("bar".to_string()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,41 @@
|
|||
use crate::{
|
||||
durable::{CreationUrls, ManagementUrls},
|
||||
rpc::{typed_data::Data, TypedData},
|
||||
};
|
||||
use crate::rpc::{typed_data::Data, TypedData};
|
||||
use azure_functions_durable::{OrchestrationClient, OrchestrationResult};
|
||||
use serde::Deserialize;
|
||||
use serde_json::from_str;
|
||||
use serde_json::{from_str, Value};
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct CreationUrls {
|
||||
#[serde(rename = "createNewInstancePostUri")]
|
||||
create_new_instance_url: String,
|
||||
#[serde(rename = "createAndWaitOnNewInstancePostUri")]
|
||||
create_new_instance_and_wait_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct ManagementUrls {
|
||||
id: String,
|
||||
#[serde(rename = "statusQueryGetUri")]
|
||||
status_query_url: String,
|
||||
#[serde(rename = "sendEventPostUri")]
|
||||
raise_event_url: String,
|
||||
#[serde(rename = "terminatePostUri")]
|
||||
terminate_url: String,
|
||||
#[serde(rename = "rewindPostUri")]
|
||||
rewind_url: String,
|
||||
#[serde(rename = "purgeHistoryDeleteUri")]
|
||||
purge_history_url: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct BindingData {
|
||||
#[serde(rename = "taskHubName")]
|
||||
task_hub: String,
|
||||
creation_urls: CreationUrls,
|
||||
management_urls: ManagementUrls,
|
||||
}
|
||||
|
||||
/// Represents the Durable Functions orchestration client input binding.
|
||||
///
|
||||
|
@ -18,23 +50,41 @@ use serde_json::from_str;
|
|||
/// # Examples
|
||||
///
|
||||
/// TODO: IMPLEMENT
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct DurableOrchestrationClient {
|
||||
#[serde(rename = "taskHubName")]
|
||||
task_hub: String,
|
||||
creation_urls: CreationUrls,
|
||||
management_urls: ManagementUrls,
|
||||
client: OrchestrationClient,
|
||||
}
|
||||
|
||||
impl DurableOrchestrationClient {
|
||||
/// Starts a new orchestration.
|
||||
///
|
||||
/// TODO: provide example
|
||||
pub async fn start_new<D>(
|
||||
&self,
|
||||
orchestrator_function_name: &str,
|
||||
instance_id: Option<&str>,
|
||||
input: D,
|
||||
) -> OrchestrationResult<String>
|
||||
where
|
||||
D: Into<Value>,
|
||||
{
|
||||
self.client
|
||||
.start_new(orchestrator_function_name, instance_id, input)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl From<TypedData> for DurableOrchestrationClient {
|
||||
fn from(data: TypedData) -> Self {
|
||||
match &data.data {
|
||||
let data: BindingData = match &data.data {
|
||||
Some(Data::String(s)) => {
|
||||
from_str(s).expect("failed to parse durable orchestration client data")
|
||||
}
|
||||
_ => panic!("expected string data for durable orchestration client"),
|
||||
};
|
||||
|
||||
DurableOrchestrationClient {
|
||||
client: OrchestrationClient::new(&data.management_urls.status_query_url),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,39 +96,10 @@ mod tests {
|
|||
#[test]
|
||||
fn it_converts_from_typed_data() {
|
||||
let data = TypedData {
|
||||
data: Some(Data::String(r#"{"taskHubName":"test","creationUrls":{"createNewInstancePostUri":"http://localhost:8080/runtime/webhooks/durabletask/orchestrators/{functionName}[/{instanceId}]?code=foo","createAndWaitOnNewInstancePostUri":"http://localhost:8080/runtime/webhooks/durabletask/orchestrators/{functionName}[/{instanceId}]?timeout={timeoutInSeconds}&pollingInterval={intervalInSeconds}&code=foo"},"managementUrls":{"id":"INSTANCEID","statusQueryGetUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID?taskHub=DurableFunctionsHub&connection=Storage&code=foo","sendEventPostUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&connection=Storage&code=foo","terminatePostUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/terminate?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=foo","rewindPostUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/rewind?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=foo","purgeHistoryDeleteUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID?taskHub=DurableFunctionsHub&connection=Storage&code=foo"}}"#.to_owned())),
|
||||
data: Some(Data::String(r#"{"taskHubName":"DurableFunctionsHub","creationUrls":{"createNewInstancePostUri":"http://localhost:8080/runtime/webhooks/durabletask/orchestrators/{functionName}[/{instanceId}]?code=foo","createAndWaitOnNewInstancePostUri":"http://localhost:8080/runtime/webhooks/durabletask/orchestrators/{functionName}[/{instanceId}]?timeout={timeoutInSeconds}&pollingInterval={intervalInSeconds}&code=foo"},"managementUrls":{"id":"INSTANCEID","statusQueryGetUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID?taskHub=DurableFunctionsHub&connection=Storage&code=foo","sendEventPostUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&connection=Storage&code=foo","terminatePostUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/terminate?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=foo","rewindPostUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/rewind?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=foo","purgeHistoryDeleteUri":"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID?taskHub=DurableFunctionsHub&connection=Storage&code=foo"}}"#.to_owned())),
|
||||
};
|
||||
|
||||
let client: DurableOrchestrationClient = data.into();
|
||||
assert_eq!(client.task_hub, "test");
|
||||
assert_eq!(
|
||||
client.creation_urls.create_new_instance_url,
|
||||
"http://localhost:8080/runtime/webhooks/durabletask/orchestrators/{functionName}[/{instanceId}]?code=foo"
|
||||
);
|
||||
assert_eq!(
|
||||
client.creation_urls.create_new_instance_and_wait_url,
|
||||
"http://localhost:8080/runtime/webhooks/durabletask/orchestrators/{functionName}[/{instanceId}]?timeout={timeoutInSeconds}&pollingInterval={intervalInSeconds}&code=foo"
|
||||
);
|
||||
assert_eq!(client.management_urls.id, "INSTANCEID");
|
||||
assert_eq!(
|
||||
client.management_urls.status_query_url,
|
||||
"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID?taskHub=DurableFunctionsHub&connection=Storage&code=foo"
|
||||
);
|
||||
assert_eq!(
|
||||
client.management_urls.raise_event_url,
|
||||
"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/raiseEvent/{eventName}?taskHub=DurableFunctionsHub&connection=Storage&code=foo"
|
||||
);
|
||||
assert_eq!(
|
||||
client.management_urls.terminate_url,
|
||||
"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/terminate?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=foo"
|
||||
);
|
||||
assert_eq!(
|
||||
client.management_urls.rewind_url,
|
||||
"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID/rewind?reason={text}&taskHub=DurableFunctionsHub&connection=Storage&code=foo"
|
||||
);
|
||||
assert_eq!(
|
||||
client.management_urls.purge_history_url,
|
||||
"http://localhost:8080/runtime/webhooks/durabletask/instances/INSTANCEID?taskHub=DurableFunctionsHub&connection=Storage&code=foo"
|
||||
);
|
||||
assert_eq!(client.client.task_hub(), "DurableFunctionsHub");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,204 @@
|
|||
use serde::Deserialize;
|
||||
use serde_json::{from_str, Value};
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
use crate::durable::{Action, EventType, HistoryEvent};
|
||||
use crate::{
|
||||
durable::ExecutionResult,
|
||||
rpc::{typed_data::Data, TypedData},
|
||||
};
|
||||
use chrono::{DateTime, Utc};
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::task::{Context, Poll};
|
||||
use futures::future::join_all;
|
||||
use serde::Deserialize;
|
||||
use serde_json::{from_str, Value};
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
collections::HashMap,
|
||||
future::Future,
|
||||
pin::Pin,
|
||||
rc::Rc,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
/// Represents a Future returned by the orchestration context.
|
||||
pub trait OrchestrationFuture: Future {
|
||||
#[doc(hidden)]
|
||||
fn notify_inner(&mut self);
|
||||
}
|
||||
|
||||
struct ActionFuture<T> {
|
||||
result: Option<T>,
|
||||
state: Rc<RefCell<OrchestrationState>>,
|
||||
is_inner: bool,
|
||||
}
|
||||
|
||||
impl<T> ActionFuture<T> {
|
||||
fn new(result: Option<T>, state: Rc<RefCell<OrchestrationState>>) -> Self {
|
||||
ActionFuture {
|
||||
result,
|
||||
state,
|
||||
is_inner: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Future for ActionFuture<T>
|
||||
where
|
||||
T: Unpin,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, _context: &mut Context) -> Poll<T> {
|
||||
let this = self.get_mut();
|
||||
if let Some(v) = this.result.take() {
|
||||
if !this.is_inner {
|
||||
this.state.borrow_mut().update();
|
||||
}
|
||||
return Poll::Ready(v);
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OrchestrationFuture for ActionFuture<T>
|
||||
where
|
||||
T: Unpin,
|
||||
{
|
||||
fn notify_inner(&mut self) {
|
||||
self.is_inner = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Future for the `DurableOrchestrationContext::join_all` function.
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct JoinAll<F>
|
||||
where
|
||||
F: OrchestrationFuture,
|
||||
{
|
||||
inner: futures::future::JoinAll<F>,
|
||||
state: Rc<RefCell<OrchestrationState>>,
|
||||
is_inner: bool,
|
||||
}
|
||||
|
||||
impl<F> JoinAll<F>
|
||||
where
|
||||
F: OrchestrationFuture,
|
||||
{
|
||||
fn new<T>(state: Rc<RefCell<OrchestrationState>>, iter: T) -> Self
|
||||
where
|
||||
T: IntoIterator<Item = F>,
|
||||
F: OrchestrationFuture,
|
||||
{
|
||||
let futs: Vec<_> = iter
|
||||
.into_iter()
|
||||
.map(|mut f| {
|
||||
f.notify_inner();
|
||||
f
|
||||
})
|
||||
.collect();
|
||||
|
||||
JoinAll {
|
||||
inner: join_all(futs),
|
||||
state,
|
||||
is_inner: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> Future for JoinAll<F>
|
||||
where
|
||||
F: OrchestrationFuture,
|
||||
{
|
||||
type Output = <futures::future::JoinAll<F> as Future>::Output;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, context: &mut Context) -> Poll<Self::Output> {
|
||||
let result = Future::poll(Pin::new(&mut self.inner), context);
|
||||
|
||||
if !self.is_inner {
|
||||
if let Poll::Ready(_) = &result {
|
||||
self.get_mut().state.borrow_mut().update();
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl<F> OrchestrationFuture for JoinAll<F>
|
||||
where
|
||||
F: OrchestrationFuture,
|
||||
{
|
||||
fn notify_inner(&mut self) {
|
||||
self.is_inner = true;
|
||||
}
|
||||
}
|
||||
|
||||
struct OrchestrationState {
|
||||
is_replaying: bool,
|
||||
history: Vec<HistoryEvent>,
|
||||
result: Rc<RefCell<ExecutionResult>>,
|
||||
orchestration_index: usize,
|
||||
}
|
||||
|
||||
impl OrchestrationState {
|
||||
fn find_scheduled_activity(&mut self, activity_name: &str) -> Option<&mut HistoryEvent> {
|
||||
self.history.iter_mut().find(|event| {
|
||||
event.name == Some(activity_name.to_owned())
|
||||
&& event.event_type == EventType::TaskScheduled
|
||||
&& !event.is_processed
|
||||
})
|
||||
}
|
||||
|
||||
fn find_completed_activity(&mut self, event_id: i32) -> Option<&mut HistoryEvent> {
|
||||
self.history.iter_mut().find(|event| {
|
||||
event.event_type == EventType::TaskCompleted
|
||||
&& event.task_scheduled_id == Some(event_id)
|
||||
})
|
||||
}
|
||||
|
||||
fn find_failed_activity(&mut self, event_id: i32) -> Option<&mut HistoryEvent> {
|
||||
self.history.iter_mut().find(|event| {
|
||||
event.event_type == EventType::TaskFailed && event.task_scheduled_id == Some(event_id)
|
||||
})
|
||||
}
|
||||
|
||||
fn update(&mut self) {
|
||||
fn is_newer_event(event: &HistoryEvent, timestamp: DateTime<Utc>) -> bool {
|
||||
event.event_type == EventType::OrchestratorStarted && event.timestamp > timestamp
|
||||
}
|
||||
|
||||
let start = self.orchestration_index + 1;
|
||||
if start >= self.history.len() {
|
||||
return;
|
||||
}
|
||||
|
||||
let current_timestamp = self.history[self.orchestration_index].timestamp;
|
||||
|
||||
match self.history[start..]
|
||||
.iter()
|
||||
.position(|event| is_newer_event(event, current_timestamp))
|
||||
.map(|pos| pos + start)
|
||||
{
|
||||
Some(next) => {
|
||||
// A new orchestration execution has occurred
|
||||
self.orchestration_index = next;
|
||||
self.result.borrow_mut().notify_new_execution();
|
||||
|
||||
let current_timestamp = self.history[self.orchestration_index].timestamp;
|
||||
let start = self.orchestration_index + 1;
|
||||
|
||||
// Check to see if this is the last execution; if so, no more replaying
|
||||
if start >= self.history.len()
|
||||
|| !self.history[start..]
|
||||
.iter()
|
||||
.any(|event| is_newer_event(event, current_timestamp))
|
||||
{
|
||||
self.is_replaying = false;
|
||||
}
|
||||
}
|
||||
None => {
|
||||
self.is_replaying = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the Durable Functions orchestration context binding.
|
||||
///
|
||||
|
@ -24,211 +212,128 @@ use std::task::{Context, Poll};
|
|||
/// # Examples
|
||||
///
|
||||
/// TODO: IMPLEMENT
|
||||
#[derive(Debug)]
|
||||
pub struct DurableOrchestrationContext {
|
||||
data: DurableOrchestrationContextData,
|
||||
|
||||
result: Rc<RefCell<ExecutionResult>>,
|
||||
|
||||
current_time: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct DurableOrchestrationContextData {
|
||||
instance_id: String,
|
||||
|
||||
#[serde(rename = "isReplaying")]
|
||||
replaying: bool,
|
||||
|
||||
parent_instance_id: Option<String>,
|
||||
|
||||
input: Value,
|
||||
|
||||
history: Vec<HistoryEvent>,
|
||||
/// The orchestration instance identifier.
|
||||
pub instance_id: String,
|
||||
/// The parent orchestration instance identifier.
|
||||
pub parent_instance_id: Option<String>,
|
||||
/// The input value to the orchestration.
|
||||
pub input: Value,
|
||||
state: Rc<RefCell<OrchestrationState>>,
|
||||
}
|
||||
|
||||
impl DurableOrchestrationContext {
|
||||
#[doc(hidden)]
|
||||
pub fn new(data: TypedData, _metadata: HashMap<String, TypedData>) -> Self {
|
||||
#[derive(Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct BindingData {
|
||||
instance_id: String,
|
||||
is_replaying: bool,
|
||||
parent_instance_id: Option<String>,
|
||||
input: Value,
|
||||
history: Vec<HistoryEvent>,
|
||||
}
|
||||
|
||||
match &data.data {
|
||||
Some(Data::String(s)) => {
|
||||
let data: DurableOrchestrationContextData =
|
||||
let data: BindingData =
|
||||
from_str(s).expect("failed to parse orchestration context data");
|
||||
|
||||
let current_time = data
|
||||
let orchestration_index = data
|
||||
.history
|
||||
.iter()
|
||||
.find(|event| event.event_type == EventType::OrchestratorStarted)
|
||||
.map(|event| event.timestamp)
|
||||
.unwrap_or(Utc::now());
|
||||
.position(|event| event.event_type == EventType::OrchestratorStarted)
|
||||
.expect("failed to find orchestration started event");
|
||||
|
||||
DurableOrchestrationContext {
|
||||
data,
|
||||
result: Rc::new(RefCell::new(ExecutionResult::default())),
|
||||
current_time,
|
||||
instance_id: data.instance_id,
|
||||
parent_instance_id: data.parent_instance_id,
|
||||
input: data.input,
|
||||
state: Rc::new(RefCell::new(OrchestrationState {
|
||||
orchestration_index,
|
||||
is_replaying: data.is_replaying,
|
||||
history: data.history,
|
||||
result: Rc::new(RefCell::new(ExecutionResult::default())),
|
||||
})),
|
||||
}
|
||||
}
|
||||
_ => panic!("expected JSON data for orchestration context data"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the instance ID of the currently executing orchestration.
|
||||
pub fn instance_id(&self) -> &str {
|
||||
&self.data.instance_id
|
||||
}
|
||||
|
||||
/// Gets the parent instance ID of the currently executing sub-orchestration.
|
||||
pub fn parent_instance_id(&self) -> Option<&str> {
|
||||
self.data.parent_instance_id.as_ref().map(|id| &**id)
|
||||
}
|
||||
|
||||
/// Gets a value indicating whether the orchestrator function is currently replaying itself.
|
||||
pub fn is_replaying(&self) -> bool {
|
||||
self.data.replaying
|
||||
}
|
||||
|
||||
/// The JSON-serializeable input to pass to the orchestrator function.
|
||||
pub fn input(&self) -> &Value {
|
||||
&self.data.input
|
||||
self.state.borrow().is_replaying
|
||||
}
|
||||
|
||||
/// Gets the current date/time in a way that is safe for use by orchestrator functions.
|
||||
pub fn current_time(&self) -> DateTime<Utc>{
|
||||
self.current_time
|
||||
pub fn current_time(&self) -> DateTime<Utc> {
|
||||
let state = self.state.borrow();
|
||||
state.history[state.orchestration_index].timestamp
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn execution_result(&self) -> Rc<RefCell<ExecutionResult>> {
|
||||
self.result.clone()
|
||||
self.state.borrow().result.clone()
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
/// Creates a future which represents a collection of the outputs of the futures given.
|
||||
///
|
||||
/// The returned future will drive execution for all of its underlying futures,
|
||||
/// collecting the results into a destination `Vec<T>` in the same order as they
|
||||
/// were provided.
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub fn join_all<I>(&self, iter: I) -> JoinAll<I::Item>
|
||||
where
|
||||
I: IntoIterator,
|
||||
I::Item: OrchestrationFuture,
|
||||
{
|
||||
JoinAll::new(self.state.clone(), iter)
|
||||
}
|
||||
|
||||
/// Schedules an activity function for execution.
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub fn call_activity<D>(
|
||||
&mut self,
|
||||
activity_name: &str,
|
||||
data: D,
|
||||
) -> impl Future<Output = Result<Value, String>>
|
||||
) -> impl Future<Output = Result<Value, String>> + OrchestrationFuture
|
||||
where
|
||||
D: Into<Value>,
|
||||
{
|
||||
self.result.borrow_mut().add_action(Action::CallActivity {
|
||||
let mut state = self.state.borrow_mut();
|
||||
|
||||
// Push the action on the execution result
|
||||
state.result.borrow_mut().push_action(Action::CallActivity {
|
||||
function_name: activity_name.to_string(),
|
||||
input: data.into(),
|
||||
});
|
||||
|
||||
let mut event_result = Option::<Result<Value, String>>::None; //ActionFuture(None); //Option::<ActionFuture<Result<Value, String>>>>::None;
|
||||
let mut result: Option<Result<Value, String>> = None;
|
||||
|
||||
if let Some(scheduled) = self.find_scheduled_activity(activity_name) {
|
||||
scheduled.processed = true;
|
||||
// Attempt to resolve the activity
|
||||
if let Some(scheduled) = state.find_scheduled_activity(activity_name) {
|
||||
scheduled.is_processed = true;
|
||||
|
||||
let id = scheduled.event_id;
|
||||
if let Some(completed) = self.find_completed_activity(id) {
|
||||
completed.processed = true;
|
||||
|
||||
let value = completed.result.clone().unwrap_or_default();
|
||||
event_result = Some(Ok(value));
|
||||
} else if let Some(failed) = self.find_failed_activity(id) {
|
||||
failed.processed = true;
|
||||
|
||||
let message = failed.reason.clone().unwrap_or_default();
|
||||
event_result = Some(Err(message));
|
||||
if let Some(completed) = state.find_completed_activity(id) {
|
||||
completed.is_processed = true;
|
||||
result = Some(Ok(completed
|
||||
.result
|
||||
.as_ref()
|
||||
.map(|s| from_str(&s).unwrap_or_default())
|
||||
.unwrap_or(Value::Null)));
|
||||
} else if let Some(failed) = state.find_failed_activity(id) {
|
||||
failed.is_processed = true;
|
||||
result = Some(Err(failed.reason.clone().unwrap_or_default()));
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(_) = &event_result {
|
||||
self.current_time = self.next_current_time();
|
||||
}
|
||||
|
||||
ActionFuture(event_result)
|
||||
}
|
||||
|
||||
fn find_scheduled_activity(&mut self, activity_name: &str) -> Option<&mut HistoryEvent> {
|
||||
self.data.history.iter_mut().find(|event| {
|
||||
event.name == Some(activity_name.to_owned())
|
||||
&& event.event_type == EventType::TaskScheduled
|
||||
&& !event.processed
|
||||
})
|
||||
}
|
||||
|
||||
fn find_completed_activity(&mut self, event_id: i32) -> Option<&mut HistoryEvent> {
|
||||
self.data.history.iter_mut().find(|event| {
|
||||
event.event_type == EventType::TaskCompleted
|
||||
&& event.task_scheduled_id == Some(event_id)
|
||||
})
|
||||
}
|
||||
|
||||
fn find_failed_activity(&mut self, event_id: i32) -> Option<&mut HistoryEvent> {
|
||||
self.data.history.iter_mut().find(|event| {
|
||||
event.event_type == EventType::TaskFailed && event.task_scheduled_id == Some(event_id)
|
||||
})
|
||||
}
|
||||
|
||||
fn next_current_time(&self) -> DateTime<Utc> {
|
||||
let current_time = self.current_time;
|
||||
|
||||
self.data
|
||||
.history
|
||||
.iter()
|
||||
.find(|event| {
|
||||
event.event_type == EventType::OrchestratorStarted && event.timestamp > current_time
|
||||
})
|
||||
.map(|event| event.timestamp)
|
||||
.unwrap_or(current_time)
|
||||
ActionFuture::new(result, self.state.clone())
|
||||
}
|
||||
}
|
||||
|
||||
struct ActionFuture<T>(Option<T>);
|
||||
|
||||
impl<T> Future for ActionFuture<T>
|
||||
where
|
||||
T: Unpin,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, _context: &mut Context) -> Poll<T> {
|
||||
if let Some(v) = self.get_mut().0.take() {
|
||||
return Poll::Ready(v);
|
||||
}
|
||||
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"history":[
|
||||
{
|
||||
"EventType":12,
|
||||
"EventId":-1,
|
||||
"IsPlayed":false,
|
||||
"Timestamp":"2019-07-18T06:22:27.016757Z"
|
||||
},
|
||||
{
|
||||
"OrchestrationInstance":{
|
||||
"InstanceId":"49497890673e4a75ab380e7a956c607b",
|
||||
"ExecutionId":"5d2025984bef476bbaacefaa499a4f5f"
|
||||
},
|
||||
"EventType":0,
|
||||
"ParentInstance":null,
|
||||
"Name":"HelloWorld",
|
||||
"Version":"",
|
||||
"Input":"{}",
|
||||
"Tags":null,
|
||||
"EventId":-1,
|
||||
"IsPlayed":false,
|
||||
"Timestamp":"2019-07-18T06:22:26.626966Z"
|
||||
}
|
||||
],
|
||||
"input":{
|
||||
|
||||
},
|
||||
"instanceId":"49497890673e4a75ab380e7a956c607b",
|
||||
"isReplaying":false,
|
||||
"parentInstanceId":null
|
||||
}
|
||||
*/
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
@ -255,7 +360,8 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn new_constructs_an_orchestration_context_without_history() {
|
||||
#[should_panic(expected = "failed to find orchestration started event")]
|
||||
fn it_panics_if_missing_history() {
|
||||
let data = TypedData {
|
||||
data: Some(Data::String(
|
||||
r#"{
|
||||
|
@ -269,15 +375,7 @@ mod tests {
|
|||
)),
|
||||
};
|
||||
|
||||
let context = DurableOrchestrationContext::new(data, HashMap::new());
|
||||
assert_eq!(context.instance_id(), "49497890673e4a75ab380e7a956c607b");
|
||||
assert_eq!(
|
||||
context.parent_instance_id(),
|
||||
Some("1234123412341234123412341234")
|
||||
);
|
||||
assert!(!context.is_replaying());
|
||||
assert_eq!(context.data.history, vec![]);
|
||||
assert_eq!(context.input(), &serde_json::Value::Array(vec![]));
|
||||
DurableOrchestrationContext::new(data, HashMap::new());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -318,21 +416,21 @@ mod tests {
|
|||
};
|
||||
|
||||
let context = DurableOrchestrationContext::new(data, HashMap::new());
|
||||
assert_eq!(context.instance_id(), "49497890673e4a75ab380e7a956c607b");
|
||||
assert_eq!(context.parent_instance_id(), None);
|
||||
assert_eq!(context.instance_id, "49497890673e4a75ab380e7a956c607b");
|
||||
assert_eq!(context.parent_instance_id, None);
|
||||
assert!(!context.is_replaying());
|
||||
assert_eq!(context.input(), &serde_json::Value::Array(vec![]));
|
||||
assert_eq!(context.input, serde_json::Value::Array(vec![]));
|
||||
assert_eq!(
|
||||
context.data.history,
|
||||
context.state.borrow().history,
|
||||
vec![
|
||||
HistoryEvent {
|
||||
event_type: EventType::OrchestratorStarted,
|
||||
event_id: -1,
|
||||
played: true,
|
||||
is_played: true,
|
||||
timestamp: DateTime::<Utc>::from(
|
||||
DateTime::parse_from_rfc3339("2019-07-18T06:22:27.016757Z").unwrap()
|
||||
),
|
||||
processed: false,
|
||||
is_processed: false,
|
||||
name: None,
|
||||
input: None,
|
||||
result: None,
|
||||
|
@ -346,11 +444,11 @@ mod tests {
|
|||
HistoryEvent {
|
||||
event_type: EventType::ExecutionStarted,
|
||||
event_id: -1,
|
||||
played: false,
|
||||
is_played: false,
|
||||
timestamp: DateTime::<Utc>::from(
|
||||
DateTime::parse_from_rfc3339("2019-07-18T06:22:26.626966Z").unwrap()
|
||||
),
|
||||
processed: false,
|
||||
is_processed: false,
|
||||
name: Some("HelloWorld".to_owned()),
|
||||
input: Some("{}".into()),
|
||||
result: None,
|
||||
|
|
|
@ -14,35 +14,36 @@ use std::{
|
|||
|
||||
mod actions;
|
||||
mod activity_output;
|
||||
mod creation_urls;
|
||||
mod history;
|
||||
mod management_urls;
|
||||
mod orchestration_output;
|
||||
|
||||
pub use actions::*;
|
||||
pub use creation_urls::*;
|
||||
pub use history::*;
|
||||
pub use management_urls::*;
|
||||
pub use orchestration_output::*;
|
||||
|
||||
pub use self::actions::*;
|
||||
pub use self::activity_output::*;
|
||||
pub use self::creation_urls::*;
|
||||
pub use self::management_urls::*;
|
||||
pub use self::history::*;
|
||||
pub use self::orchestration_output::*;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Debug, Serialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecutionResult {
|
||||
done: bool,
|
||||
actions: Vec<Action>,
|
||||
is_done: bool,
|
||||
actions: Vec<Vec<Action>>,
|
||||
output: Option<Value>,
|
||||
custom_status: Option<Value>,
|
||||
error: Option<String>,
|
||||
}
|
||||
|
||||
impl ExecutionResult {
|
||||
pub(crate) fn add_action(&mut self, action: Action) {
|
||||
self.actions.push(action);
|
||||
pub(crate) fn notify_new_execution(&mut self) {
|
||||
self.actions.push(Vec::new());
|
||||
}
|
||||
|
||||
pub(crate) fn push_action(&mut self, action: Action) {
|
||||
if self.actions.is_empty() {
|
||||
self.actions.push(Vec::new());
|
||||
}
|
||||
|
||||
self.actions.last_mut().unwrap().push(action);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +93,7 @@ where
|
|||
Poll::Ready(output) => {
|
||||
let mut result = result.borrow_mut();
|
||||
result.output = Some(output.into_value());
|
||||
result.done = true;
|
||||
result.is_done = true;
|
||||
}
|
||||
Poll::Pending => {}
|
||||
};
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::rpc::{typed_data::Data, TypedData};
|
||||
use serde_json::Value;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
/// Represents the output of a Durable Functions activity function.
|
||||
///
|
||||
|
@ -15,6 +16,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Value> for ActivityOutput {
|
||||
fn from_iter<I>(iter: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Value>,
|
||||
{
|
||||
ActivityOutput(Value::from_iter(iter))
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl Into<TypedData> for ActivityOutput {
|
||||
fn into(self) -> TypedData {
|
||||
|
|
|
@ -17,13 +17,12 @@ pub struct HistoryEvent {
|
|||
|
||||
pub(crate) event_id: i32,
|
||||
|
||||
#[serde(alias = "IsPlayed")]
|
||||
pub(crate) played: bool,
|
||||
pub(crate) is_played: bool,
|
||||
|
||||
pub(crate) timestamp: DateTime<Utc>,
|
||||
|
||||
#[serde(default, alias = "IsProcessed")]
|
||||
pub(crate) processed: bool,
|
||||
#[serde(skip)]
|
||||
pub(crate) is_processed: bool,
|
||||
|
||||
// EventRaised, ExecutionStarted, SubOrchestrationInstanceCreated, TaskScheduled
|
||||
pub(crate) name: Option<String>,
|
||||
|
@ -32,7 +31,7 @@ pub struct HistoryEvent {
|
|||
pub(crate) input: Option<Value>,
|
||||
|
||||
//SubOrchestrationInstanceCompleted, TaskCompleted
|
||||
pub(crate) result: Option<Value>,
|
||||
pub(crate) result: Option<String>,
|
||||
|
||||
// SubOrchestrationInstanceCompleted , SubOrchestrationInstanceFailed, TaskCompleted,TaskFailed
|
||||
pub(crate) task_scheduled_id: Option<i32>,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::durable::IntoValue;
|
||||
use serde_json::Value;
|
||||
use std::iter::FromIterator;
|
||||
|
||||
/// Represents the output of a Durable Functions orchestration function.
|
||||
///
|
||||
|
@ -15,6 +16,15 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Value> for OrchestrationOutput {
|
||||
fn from_iter<I>(iter: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = Value>,
|
||||
{
|
||||
OrchestrationOutput(Value::from_iter(iter))
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoValue for OrchestrationOutput {
|
||||
fn into_value(self) -> Value {
|
||||
self.0
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
//!
|
||||
//! * [Blob trigger](bindings/struct.BlobTrigger.html)
|
||||
//! * [Cosmos DB trigger](bindings/struct.CosmosDbTrigger.html)
|
||||
//! * [Durable Activity trigger](bindings/struct.DurableOrchestrationContext.html)
|
||||
//! * [Durable Orchestration trigger](bindings/struct.DurableOrchestrationContext.html)
|
||||
//! * [Event Grid trigger](bindings/struct.EventGridEvent.html)
|
||||
//! * [Event Hub trigger](bindings/struct.EventHubTrigger.html)
|
||||
//! * [Generic trigger](bindings/struct.GenericTrigger.html)
|
||||
|
@ -18,6 +20,7 @@
|
|||
//!
|
||||
//! * [Blob input](bindings/struct.Blob.html)
|
||||
//! * [Cosmos DB input](bindings/struct.CosmosDbDocument.html)
|
||||
//! * [Durable orchestration client input](bindings/struct.DurableOrchestrationClient.html)
|
||||
//! * [Generic input](bindings/struct.GenericInput.html)
|
||||
//! * [SignalR connection info input](bindings/struct.SignalRConnectionInfo.html)
|
||||
//! * [Table input](bindings/struct.Table.html)
|
||||
|
@ -87,6 +90,7 @@
|
|||
#![deny(unused_extern_crates)]
|
||||
#![deny(missing_docs)]
|
||||
#![cfg_attr(test, recursion_limit = "128")]
|
||||
#![feature(async_await)]
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use azure_functions_codegen::export;
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "lldb",
|
||||
"request": "attach",
|
||||
"name": "Debug",
|
||||
"windows": {
|
||||
"program": "durable-functions-example.exe"
|
||||
},
|
||||
"program": "durable-functions-example",
|
||||
"preLaunchTask": "Launch Azure Functions Application",
|
||||
"postDebugTask": "Terminate Azure Functions Application"
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Launch Azure Functions Application",
|
||||
"type": "shell",
|
||||
"command": "cargo",
|
||||
"args": [
|
||||
"func",
|
||||
"run",
|
||||
"--",
|
||||
"--features",
|
||||
"unstable"
|
||||
],
|
||||
"presentation": {
|
||||
"reveal": "always",
|
||||
"clear": true,
|
||||
"focus": true
|
||||
},
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "azureFunctions",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "\\b\\B",
|
||||
"file": 1,
|
||||
"location": 2,
|
||||
"message": 3
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "^Azure Functions Core Tools",
|
||||
"endsPattern": "^Application started."
|
||||
}
|
||||
}
|
||||
],
|
||||
"isBackground": true
|
||||
},
|
||||
{
|
||||
"label": "Terminate Azure Functions Application",
|
||||
"type": "process",
|
||||
"command":"${command:workbench.action.tasks.terminate}",
|
||||
"args": [
|
||||
"Launch Azure Functions Application"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -8,6 +8,7 @@ edition = "2018"
|
|||
azure-functions = { path = "../../azure-functions" }
|
||||
log = "0.4.6"
|
||||
futures-preview = { version = "0.3.0-alpha.17", optional = true }
|
||||
serde_json = "1.0.40"
|
||||
|
||||
[features]
|
||||
unstable = ["azure-functions/unstable", "futures-preview"]
|
||||
|
|
|
@ -1,18 +1,29 @@
|
|||
use azure_functions::{bindings::DurableOrchestrationContext, durable::OrchestrationOutput, func};
|
||||
use futures::future::join_all;
|
||||
use log::warn;
|
||||
use serde_json::Value;
|
||||
|
||||
#[func]
|
||||
pub async fn hello_world(mut context: DurableOrchestrationContext) -> OrchestrationOutput {
|
||||
// join_all(
|
||||
// [
|
||||
// context.call_activity("say_hello", "Tokyo"),
|
||||
// context.call_activity("say_hello", "London"),
|
||||
// context.call_activity("say_hello", "Seattle"),
|
||||
// ]
|
||||
// .into_iter(),
|
||||
// )
|
||||
// .await
|
||||
// .map(|r| r.unwrap())
|
||||
// .into()
|
||||
unimplemented!()
|
||||
if !context.is_replaying() {
|
||||
warn!("Orchestration started at {}.", context.current_time());
|
||||
}
|
||||
|
||||
let activities = vec![
|
||||
context.call_activity("say_hello", "Tokyo"),
|
||||
context.call_activity("say_hello", "London"),
|
||||
context.call_activity("say_hello", "Seattle"),
|
||||
];
|
||||
|
||||
let result: Vec<_> = context
|
||||
.join_all(activities)
|
||||
.await
|
||||
.into_iter()
|
||||
.map(|r| r.unwrap_or_else(|e| Value::from(format!("Activity failed: {}", e))))
|
||||
.collect();
|
||||
|
||||
if !context.is_replaying() {
|
||||
warn!("Orchestration completed at {}.", context.current_time());
|
||||
}
|
||||
|
||||
result.into()
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
use azure_functions::{bindings::DurableActivityContext, durable::ActivityOutput, func};
|
||||
|
||||
#[func]
|
||||
pub async fn say_hello(_context: DurableActivityContext) -> ActivityOutput {
|
||||
// format!(
|
||||
// "Hello {}!",
|
||||
// context.input().as_str().expect("expected a string input")
|
||||
// )
|
||||
// .into()
|
||||
unimplemented!()
|
||||
pub fn say_hello(context: DurableActivityContext) -> ActivityOutput {
|
||||
format!(
|
||||
"Hello {}!",
|
||||
context.input.as_str().expect("expected a string input")
|
||||
)
|
||||
.into()
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ use azure_functions::{
|
|||
bindings::{DurableOrchestrationClient, HttpRequest, HttpResponse},
|
||||
func,
|
||||
};
|
||||
use serde_json::Value;
|
||||
|
||||
#[func]
|
||||
pub async fn start(_req: HttpRequest, _client: DurableOrchestrationClient) -> HttpResponse {
|
||||
// match client.start_new("hello_world").await {
|
||||
// Ok(_) => "Orchestration started.".into(),
|
||||
// Err(e) => format!("Failed to start orchestration: {}", e).into()
|
||||
// }
|
||||
unimplemented!()
|
||||
pub async fn start(_req: HttpRequest, client: DurableOrchestrationClient) -> HttpResponse {
|
||||
match client.start_new("hello_world", None, Value::Null).await {
|
||||
Ok(_) => "Orchestration started.".into(),
|
||||
Err(e) => format!("Failed to start orchestration: {}", e).into(),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue