Sync commit

This commit is contained in:
Joe Bellus 2021-11-13 00:29:29 -05:00
commit b624dc3b34
7 changed files with 1438 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

779
Cargo.lock generated Normal file
View File

@ -0,0 +1,779 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "actix"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3720d0064a0ce5c0de7bd93bdb0a6caebab2a9b5668746145d7b3b0c5da02914"
dependencies = [
"actix-rt",
"actix_derive",
"bitflags",
"bytes",
"crossbeam-channel",
"futures-core",
"futures-sink",
"futures-task",
"futures-util",
"log",
"once_cell",
"parking_lot",
"pin-project-lite",
"smallvec",
"tokio",
"tokio-util",
]
[[package]]
name = "actix-macros"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
dependencies = [
"quote",
"syn",
]
[[package]]
name = "actix-rt"
version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a0c218d0a17c120f10ee0c69c9f0c45d87319e8f66b1f065e8412b612fc3e24"
dependencies = [
"actix-macros",
"futures-core",
"tokio",
]
[[package]]
name = "actix_derive"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d44b8fee1ced9671ba043476deddef739dd0959bf77030b26b738cc591737a7"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "arkham"
version = "0.1.1"
dependencies = [
"console",
]
[[package]]
name = "async-channel"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2114d64672151c0c5eaa5e131ec84a74f06e1e559830dabba01ca30605d66319"
dependencies = [
"concurrent-queue",
"event-listener",
"futures-core",
]
[[package]]
name = "async-io"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a811e6a479f2439f0c04038796b5cfb3d2ad56c230e0f2d3f7b04d68cfee607b"
dependencies = [
"concurrent-queue",
"futures-lite",
"libc",
"log",
"once_cell",
"parking",
"polling",
"slab",
"socket2",
"waker-fn",
"winapi",
]
[[package]]
name = "async-process"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6"
dependencies = [
"async-io",
"blocking",
"cfg-if",
"event-listener",
"futures-lite",
"libc",
"once_cell",
"signal-hook",
"winapi",
]
[[package]]
name = "async-task"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0"
[[package]]
name = "atomic-waker"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a"
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "blocking"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "046e47d4b2d391b1f6f8b407b1deb8dee56c1852ccd868becf2710f601b5f427"
dependencies = [
"async-channel",
"async-task",
"atomic-waker",
"fastrand",
"futures-lite",
"once_cell",
]
[[package]]
name = "bytes"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
[[package]]
name = "cache-padded"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba"
[[package]]
name = "cc"
version = "1.0.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "concurrent-queue"
version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3"
dependencies = [
"cache-padded",
]
[[package]]
name = "conductor"
version = "0.1.0"
dependencies = [
"actix",
"actix-rt",
"arkham",
"async-process",
"expand_str",
"futures",
"serde",
"serde_yaml",
]
[[package]]
name = "console"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"regex",
"terminal_size",
"unicode-width",
"winapi",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
dependencies = [
"cfg-if",
"lazy_static",
]
[[package]]
name = "dtoa"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
[[package]]
name = "encode_unicode"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
name = "event-listener"
version = "2.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59"
[[package]]
name = "expand_str"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7bfbc9fbd454fca65e24c398c860da7bf0b76d0d4e62eb89e2e72d69e18a0e4"
[[package]]
name = "fastrand"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b394ed3d285a429378d3b384b9eb1285267e7df4b166df24b7a6939a04dc392e"
dependencies = [
"instant",
]
[[package]]
name = "futures"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca"
dependencies = [
"futures-channel",
"futures-core",
"futures-executor",
"futures-io",
"futures-sink",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-channel"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
name = "futures-core"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
[[package]]
name = "futures-executor"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]]
name = "futures-io"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377"
[[package]]
name = "futures-lite"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7694489acd39452c77daa48516b894c153f192c3578d5a839b62c58099fcbf48"
dependencies = [
"fastrand",
"futures-core",
"futures-io",
"memchr",
"parking",
"pin-project-lite",
"waker-fn",
]
[[package]]
name = "futures-macro"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb"
dependencies = [
"autocfg",
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "futures-sink"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11"
[[package]]
name = "futures-task"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99"
[[package]]
name = "futures-util"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481"
dependencies = [
"autocfg",
"futures-channel",
"futures-core",
"futures-io",
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"pin-project-lite",
"pin-utils",
"proc-macro-hack",
"proc-macro-nested",
"slab",
]
[[package]]
name = "hashbrown"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "indexmap"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5"
dependencies = [
"autocfg",
"hashbrown",
]
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
[[package]]
name = "linked-hash-map"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
[[package]]
name = "lock_api"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
[[package]]
name = "memchr"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
[[package]]
name = "mio"
version = "0.7.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc"
dependencies = [
"libc",
"log",
"miow",
"ntapi",
"winapi",
]
[[package]]
name = "miow"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
dependencies = [
"winapi",
]
[[package]]
name = "ntapi"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
dependencies = [
"winapi",
]
[[package]]
name = "once_cell"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
[[package]]
name = "parking"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72"
[[package]]
name = "parking_lot"
version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
dependencies = [
"cfg-if",
"instant",
"libc",
"redox_syscall",
"smallvec",
"winapi",
]
[[package]]
name = "pin-project-lite"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443"
[[package]]
name = "pin-utils"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "polling"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259"
dependencies = [
"cfg-if",
"libc",
"log",
"wepoll-ffi",
"winapi",
]
[[package]]
name = "proc-macro-hack"
version = "0.5.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
[[package]]
name = "proc-macro-nested"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
[[package]]
name = "proc-macro2"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43"
dependencies = [
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461"
dependencies = [
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.130"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_yaml"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"
dependencies = [
"dtoa",
"indexmap",
"serde",
"yaml-rust",
]
[[package]]
name = "signal-hook"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "smallvec"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309"
[[package]]
name = "socket2"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "syn"
version = "1.0.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "terminal_size"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "tokio"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "588b2d10a336da58d877567cd8fb8a14b463e2104910f8132cd054b4b96e29ee"
dependencies = [
"autocfg",
"bytes",
"libc",
"memchr",
"mio",
"once_cell",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"winapi",
]
[[package]]
name = "tokio-util"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
]
[[package]]
name = "unicode-width"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "unicode-xid"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
[[package]]
name = "waker-fn"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca"
[[package]]
name = "wepoll-ffi"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d743fdedc5c64377b5fc2bc036b01c7fd642205a0d96356034ae3404d49eb7fb"
dependencies = [
"cc",
]
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "yaml-rust"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
dependencies = [
"linked-hash-map",
]

18
Cargo.toml Normal file
View File

@ -0,0 +1,18 @@
[package]
name = "conductor"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
serde = { version = "1.0.130", features = ["derive"] }
serde_yaml = "0.8.21"
expand_str = "0.1.1"
actix = "0.12.0"
actix-rt = "2.4.0"
async-process = "1.3.0"
futures = "0.3.17"
arkham = { path = "../arkham" }

356
src/definition.rs Normal file
View File

@ -0,0 +1,356 @@
use crate::job::{Job, Jobs};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Serialize, Deserialize, Default)]
#[serde(default)]
pub struct Project {
pub components: Vec<Component>,
pub groups: Vec<Group>,
pub env: HashMap<String, String>,
pub tasks: Vec<TaskDefinition>,
}
impl Project {
fn get_absolute_task(&self, name: &str) -> Option<Jobs> {
self.tasks
.iter()
.find(|t| t.name == name)
.map(|task| {
let job = self.build_project_task_job(task);
let mut jobs = task
.before
.iter()
.map(|name| self.get_absolute_task(name))
.flatten()
.map(|jobs| jobs.to_vec())
.flatten()
.collect::<Vec<_>>();
jobs.push(job);
Jobs::new(jobs)
})
.or_else(|| {
self.components.iter().find_map(|component| {
component
.tasks
.iter()
.find(|t| format!("{}:{}", component.name, t.name) == name)
.map(|task| {
let job = self.build_component_task_job(component, task);
let mut jobs = task
.before
.iter()
.map(|name| self.get_absolute_task(name))
.flatten()
.map(|jobs| jobs.to_vec())
.flatten()
.collect::<Vec<_>>();
jobs.push(job);
Jobs::new(jobs)
})
})
})
}
fn get_relative_task(&self, task_name: &str, component_name: &str) -> Option<Jobs> {
if let Some(component) = self.components.iter().find(|c| c.name == component_name) {
component
.tasks
.iter()
.find(|t| t.name == task_name)
.map(|task| {
let job = self.build_component_task_job(component, task);
let mut jobs = task
.before
.iter()
.map(|name| self.get_by_name(name))
.flatten()
.map(|jobs| jobs.to_vec())
.flatten()
.collect::<Vec<_>>();
jobs.push(job);
Jobs::new(jobs)
})
} else {
None
}
}
fn get_component(&self, name: &str) -> Option<Jobs> {
self.components.iter().find(|c| c.name == name).map(|c| {
let component_job = self.build_component_job(c);
let mut absolute_tasks = c
.before
.iter()
.map(|name| self.get_absolute_task(name))
.flatten()
.map(|jobs| jobs.to_vec())
.flatten()
.collect::<Vec<_>>();
let mut relative_tasks = c
.before
.iter()
.map(|name| self.get_relative_task(name, &c.name))
.flatten()
.map(|jobs| jobs.to_vec())
.flatten()
.collect::<Vec<_>>();
absolute_tasks.append(&mut relative_tasks);
absolute_tasks.push(component_job);
Jobs::new(absolute_tasks)
})
}
fn build_component_job(&self, c: &Component) -> Job {
let mut env = self.env.clone();
env.extend(c.env.clone());
Job {
name: c.name.clone(),
env,
..Job::default()
}
}
fn build_project_task_job(&self, task: &TaskDefinition) -> Job {
let mut env = self.env.clone();
env.extend(task.env.clone());
Job {
name: task.name.clone(),
..Job::default()
}
}
fn build_component_task_job(&self, component: &Component, task: &TaskDefinition) -> Job {
let mut env = self.env.clone();
env.extend(component.env.clone());
env.extend(task.env.clone());
Job {
name: format!("{}:{}", component.name.clone(), task.name.clone()),
env,
..Job::default()
}
}
pub fn get_by_name(&self, name: &str) -> Option<Jobs> {
self.get_component(name)
.or_else(|| self.get_absolute_task(name))
}
pub fn from_str(s: &str) -> Self {
serde_yaml::from_str(s).unwrap()
}
}
#[derive(Serialize, Deserialize, Default)]
#[serde(default)]
pub struct Group {
name: String,
components: Vec<Component>,
env: HashMap<String, String>,
}
#[derive(Serialize, Deserialize)]
#[serde(default)]
pub struct Component {
pub env: HashMap<String, String>,
pub name: String,
pub command: String,
pub path: Option<String>,
pub retry: bool,
pub keep_alive: bool,
pub retry_delay: u64,
pub before: Vec<String>,
pub tasks: Vec<TaskDefinition>,
}
impl Default for Component {
fn default() -> Self {
Self {
env: HashMap::new(),
name: "UNNAMED".to_string(),
command: String::new(),
path: None,
retry: false,
keep_alive: true,
retry_delay: 2,
before: vec![],
tasks: vec![],
}
}
}
#[derive(Serialize, Deserialize, Default)]
#[serde(default)]
pub struct TaskDefinition {
pub env: HashMap<String, String>,
pub name: String,
pub command: String,
pub path: Option<String>,
pub retry: bool,
pub keep_alive: bool,
pub retry_delay: u64,
pub before: Vec<String>,
}
#[cfg(test)]
mod tests {
use super::Project;
#[test]
fn component_by_name() {
let project = Project::from_str(
r#"
components:
- name: test-component
"#,
);
let jobs = project.get_by_name("test-component").unwrap();
assert_eq!(jobs.len(), 1);
}
#[test]
fn project_task() {
let project = Project::from_str(
r#"
tasks:
- name: task1
"#,
);
let jobs = project.get_by_name("task1").unwrap();
assert_eq!(jobs.len(), 1);
}
#[test]
fn component_task() {
let project = Project::from_str(
r#"
components:
- name: c1
tasks:
- name: task1
"#,
);
let jobs = project.get_by_name("c1:task1").unwrap();
assert_eq!(jobs.len(), 1);
}
#[test]
fn component_dependent_absolute_component_task() {
let project = Project::from_str(
r#"
components:
- name: main-cmp
before:
- main-cmp:sub-task
tasks:
- name: sub-task
"#,
);
let jobs = project.get_by_name("main-cmp").unwrap();
assert_eq!(jobs.len(), 2);
assert_eq!(jobs.first().unwrap().name, "main-cmp:sub-task");
}
#[test]
fn component_dependent_relative_component_task() {
let project = Project::from_str(
r#"
components:
- name: main-cmp
before:
- sub-task
tasks:
- name: sub-task
"#,
);
let jobs = project.get_by_name("main-cmp").unwrap();
assert_eq!(jobs.len(), 2);
assert_eq!(jobs.first().unwrap().name, "main-cmp:sub-task");
}
#[test]
fn complicated_dependencies() {
let project = Project::from_str(
r#"
components:
- name: ui
before:
- build-ui
tasks:
- name: build-ui
- name: server
before:
- setup
tasks:
- name: setup
- name: build
before:
- server:setup
tasks:
- name: build
before:
- ui:build-ui
- server:build
"#,
);
let jobs = project.get_by_name("build").unwrap();
assert_eq!(jobs.get(0).unwrap().name, "ui:build-ui");
assert_eq!(jobs.get(1).unwrap().name, "server:setup");
assert_eq!(jobs.get(2).unwrap().name, "server:build");
assert_eq!(jobs.get(3).unwrap().name, "build");
assert_eq!(jobs.len(), 4);
}
#[test]
fn component_env() {
let project = Project::from_str(
r#"
env:
foo: one
sub: two
components:
- name: main-cmp
env:
sub: three
"#,
);
let jobs = project.get_by_name("main-cmp").unwrap();
let job = jobs.first().unwrap();
assert_eq!(job.env.get("foo"), Some(&String::from("one")));
assert_eq!(job.env.get("sub"), Some(&String::from("three")));
}
#[test]
fn task_env() {
let project = Project::from_str(
r#"
env:
root: ten
foo: one
sub: two
components:
- name: main-cmp
env:
sub: three
tasks:
- name: t
env:
foo: four
"#,
);
let jobs = project.get_by_name("main-cmp:t").unwrap();
let job = jobs.first().unwrap();
assert_eq!(job.env.get("foo"), Some(&String::from("four")));
assert_eq!(job.env.get("sub"), Some(&String::from("three")));
assert_eq!(job.env.get("root"), Some(&String::from("ten")));
}
}

66
src/job.rs Normal file
View File

@ -0,0 +1,66 @@
use actix::Message;
use std::{
collections::HashMap,
ops::{Deref, DerefMut},
};
#[derive(Clone, Message)]
#[rtype(result = "()")]
pub struct Jobs(Vec<Job>);
impl Jobs {
pub fn new(tasks: Vec<Job>) -> Self {
Self(tasks)
}
}
impl std::fmt::Debug for Jobs {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Jobs")
.field(
"list",
&self.iter().map(|j| j.name.clone()).collect::<Vec<_>>(),
)
.finish()
}
}
impl Deref for Jobs {
type Target = Vec<Job>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Jobs {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
#[derive(Clone, Debug, Message)]
#[rtype(result = "()")]
pub struct Job {
pub name: String,
pub command: String,
pub path: String,
pub env: HashMap<String, String>,
pub retry: bool,
pub keep_alive: bool,
pub retry_delay: u64,
}
impl Default for Job {
fn default() -> Self {
Job {
name: "Unnamed".to_string(),
command: "".to_string(),
path: ".".to_string(),
env: HashMap::new(),
retry: true,
keep_alive: true,
retry_delay: 2,
}
}
}

29
src/main.rs Normal file
View File

@ -0,0 +1,29 @@
use crate::definition::Project;
use actix::prelude::*;
use runner::Manager;
mod definition;
mod job;
mod runner;
#[actix_rt::main]
async fn main() {
let project = Project::from_str(
r#"
components:
- name: ls
commands:
- ls
- name: currentdir
commands:
- pwd
"#,
);
let jobs = project.get_by_name("ls").unwrap();
let manager = Manager::new().start();
manager.do_send(jobs);
actix_rt::signal::ctrl_c()
.await
.expect("failed to listen for event");
}

189
src/runner.rs Normal file
View File

@ -0,0 +1,189 @@
use crate::job::{Job, Jobs};
use std::collections::HashMap;
use std::process::exit;
use std::process::Stdio;
use std::time::Duration;
use actix::prelude::*;
use async_process::Child;
use async_process::Command;
use futures::io::AsyncBufReadExt;
use futures::io::BufReader;
#[derive(Clone, Message, Debug)]
#[rtype(result = "()")]
pub enum Event {
StartedTask(i64, String),
Output(i64, String, String),
Error(i64, String, String),
FinishedTask(i64, String),
Completed(i64),
}
#[derive(Debug)]
pub struct Runner {
pub id: i64,
pub tasks: Jobs,
pub manager: Recipient<Event>,
child: Option<Child>,
pub current_job: Option<Job>,
}
impl Runner {
pub fn new(id: i64, tasks: Jobs, manager: Recipient<Event>) -> Self {
Self {
tasks,
manager,
id,
current_job: None,
child: None,
}
}
}
impl Actor for Runner {
type Context = Context<Self>;
fn started(&mut self, ctx: &mut Self::Context) {
if let Some(task) = self.tasks.pop() {
ctx.notify(task);
} else {
ctx.stop();
}
}
}
impl Handler<Job> for Runner {
type Result = ();
fn handle(&mut self, job: Job, ctx: &mut Self::Context) -> Self::Result {
self.current_job = Some(job.clone());
let _ = self
.manager
.do_send(Event::StartedTask(self.id, job.name.clone()));
let mut child = Command::new("sh")
.arg("-c")
.arg(&job.command)
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.unwrap();
let stdout = child
.stdout
.take()
.expect("child did not have a handle to stdout");
let reader = BufReader::new(stdout).lines();
let fut = async move {
child
.status()
.await
.expect("child process encountered an error")
};
let fut = actix::fut::wrap_future::<_, Self>(fut).map(move |status, _, ctx| {
if job.keep_alive && status.code() == Some(0) {
let delay = Duration::from_secs(job.retry_delay);
arkham::vox::header(format!("Restarting {} in {}s", job.name, delay.as_secs()));
ctx.notify_later(job, delay);
}
});
ctx.spawn(fut);
ctx.add_stream(reader);
}
}
impl StreamHandler<Result<String, std::io::Error>> for Runner {
fn handle(&mut self, item: Result<String, std::io::Error>, _: &mut Self::Context) {
let ev = match item {
Ok(v) => Event::Output(
self.id,
self.current_job
.as_ref()
.map(|i| i.name.clone())
.unwrap_or_else(|| String::from("UNKNOWN")),
v,
),
Err(e) => Event::Error(
self.id,
self.current_job.as_ref().unwrap().name.clone(),
e.to_string(),
),
};
let _ = self.manager.do_send(ev);
}
fn finished(&mut self, ctx: &mut Self::Context) {
let _ = self.manager.do_send(Event::FinishedTask(
self.id,
self.current_job.as_ref().unwrap().name.clone(),
));
if let Some(task) = self.tasks.pop() {
self.current_job = None;
ctx.notify(task);
} else if !self
.current_job
.as_ref()
.map(|i| i.keep_alive)
.unwrap_or(false)
{
let _ = self.manager.do_send(Event::Completed(self.id));
ctx.stop();
}
}
}
#[derive(Default)]
pub struct Manager {
id_count: i64,
runners: HashMap<i64, Addr<Runner>>,
}
impl Manager {
pub fn new() -> Self {
Self::default()
}
}
impl Actor for Manager {
type Context = Context<Self>;
}
impl Handler<Event> for Manager {
type Result = ();
fn handle(&mut self, msg: Event, ctx: &mut Self::Context) -> Self::Result {
match msg {
Event::StartedTask(_, name) => {
arkham::vox::header(format!("{} - Started", name));
}
Event::Output(_, name, v) => {
println!("[{}] {}", name, v)
}
Event::Error(_, v, name) => {
println!("[{}] Error: {}", name, v);
}
Event::FinishedTask(_, name) => {
arkham::vox::header(format!("{} - Finished", name));
}
Event::Completed(id) => {
self.runners.remove(&id);
if self.runners.is_empty() {
ctx.stop();
System::current().stop();
exit(0)
}
}
}
}
}
impl Handler<Jobs> for Manager {
type Result = ();
fn handle(&mut self, msg: Jobs, ctx: &mut Self::Context) -> Self::Result {
self.id_count += 1;
let addr = Runner::new(self.id_count, msg, ctx.address().recipient()).start();
self.runners.insert(self.id_count, addr);
}
}