feat: finish monitor in executor, daemonize executor
Signed-off-by: Catty Steve <4795515+Catty2014@user.noreply.gitee.com>
This commit is contained in:
Generated
+621
-14
@@ -70,12 +70,138 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "arraydeque"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236"
|
||||
|
||||
[[package]]
|
||||
name = "async-broadcast"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"event-listener-strategy",
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-channel"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"event-listener-strategy",
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-executor"
|
||||
version = "1.13.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8"
|
||||
dependencies = [
|
||||
"async-task",
|
||||
"concurrent-queue",
|
||||
"fastrand",
|
||||
"futures-lite",
|
||||
"pin-project-lite",
|
||||
"slab",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"futures-io",
|
||||
"futures-lite",
|
||||
"parking",
|
||||
"polling",
|
||||
"rustix",
|
||||
"slab",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-lock"
|
||||
version = "3.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"event-listener-strategy",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-signal",
|
||||
"async-task",
|
||||
"blocking",
|
||||
"cfg-if",
|
||||
"event-listener",
|
||||
"futures-lite",
|
||||
"rustix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-recursion"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-signal"
|
||||
version = "0.2.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"atomic-waker",
|
||||
"cfg-if",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"rustix",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "async-task"
|
||||
version = "4.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
||||
|
||||
[[package]]
|
||||
name = "async-trait"
|
||||
version = "0.1.89"
|
||||
@@ -87,12 +213,30 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.10.0"
|
||||
@@ -111,6 +255,19 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "blocking"
|
||||
version = "1.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e83f8d02be6967315521be875afa792a316e28d57b5a2d401897e2a7921b7f21"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-task",
|
||||
"futures-io",
|
||||
"futures-lite",
|
||||
"piper",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.19.1"
|
||||
@@ -139,6 +296,26 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "cgroups-rs"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efc46cf39fc5922b840030e0e5b378ce5caa9a824a675a95c6dec2c2c9ce9468"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
"libc",
|
||||
"log",
|
||||
"nix 0.25.1",
|
||||
"thiserror 1.0.69",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.42"
|
||||
@@ -199,6 +376,15 @@ version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "config"
|
||||
version = "0.15.19"
|
||||
@@ -263,6 +449,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crunchy"
|
||||
version = "0.2.4"
|
||||
@@ -307,6 +499,33 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "endi"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66b7e2430c6dff6a955451e2cfc438f09cea1965a9d6f87f7e3b90decc014099"
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef"
|
||||
dependencies = [
|
||||
"enumflags2_derive",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2_derive"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_filter"
|
||||
version = "0.1.4"
|
||||
@@ -330,6 +549,12 @@ dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "erased-serde"
|
||||
version = "0.4.9"
|
||||
@@ -351,6 +576,27 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "5.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
|
||||
dependencies = [
|
||||
"concurrent-queue",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener-strategy"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
|
||||
dependencies = [
|
||||
"event-listener",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
@@ -369,6 +615,31 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "futures-core"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||
|
||||
[[package]]
|
||||
name = "futures-lite"
|
||||
version = "2.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"parking",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
@@ -417,6 +688,12 @@ dependencies = [
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.10.0"
|
||||
@@ -432,6 +709,18 @@ version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||
|
||||
[[package]]
|
||||
name = "hex"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.64"
|
||||
@@ -456,6 +745,16 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.2"
|
||||
@@ -552,6 +851,15 @@ version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minijinja"
|
||||
version = "2.14.0"
|
||||
@@ -572,6 +880,31 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
|
||||
dependencies = [
|
||||
"bitflags 2.10.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
@@ -603,6 +936,22 @@ dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ordered-stream"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"pin-project-lite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking"
|
||||
version = "2.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.5"
|
||||
@@ -681,6 +1030,31 @@ version = "0.2.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||
|
||||
[[package]]
|
||||
name = "piper"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"fastrand",
|
||||
"futures-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"hermit-abi",
|
||||
"pin-project-lite",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "portable-atomic"
|
||||
version = "1.11.1"
|
||||
@@ -696,6 +1070,15 @@ dependencies = [
|
||||
"portable-atomic",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
|
||||
dependencies = [
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.103"
|
||||
@@ -726,7 +1109,7 @@ version = "0.5.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -764,7 +1147,7 @@ version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.10.0",
|
||||
"once_cell",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
@@ -788,7 +1171,7 @@ version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"bitflags 2.10.0",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
@@ -801,12 +1184,6 @@ version = "1.0.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -857,15 +1234,26 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.145"
|
||||
version = "1.0.148"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||
checksum = "3084b546a1dd6289475996f182a22aba973866ea8e8b02c51d9f46b1336a22da"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"zmij",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_repr"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -904,6 +1292,12 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.15.1"
|
||||
@@ -920,6 +1314,12 @@ dependencies = [
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
@@ -950,13 +1350,33 @@ dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "2.0.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
"thiserror-impl 2.0.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1029,6 +1449,18 @@ dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.23.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d7cbc3b4b49633d57a0509303158ca50de80ae32c265093b24c414705807832"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.4"
|
||||
@@ -1044,6 +1476,37 @@ version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100"
|
||||
dependencies = [
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typeid"
|
||||
version = "1.0.3"
|
||||
@@ -1062,6 +1525,17 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
|
||||
|
||||
[[package]]
|
||||
name = "uds_windows"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9"
|
||||
dependencies = [
|
||||
"memoffset",
|
||||
"tempfile",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.22"
|
||||
@@ -1088,6 +1562,7 @@ checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"js-sys",
|
||||
"serde_core",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
@@ -1157,6 +1632,28 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[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 = "windows-core"
|
||||
version = "0.62.2"
|
||||
@@ -1318,6 +1815,8 @@ checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
name = "workshop-executor"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cgroups-rs",
|
||||
"chrono",
|
||||
"clap",
|
||||
"config",
|
||||
@@ -1327,9 +1826,10 @@ dependencies = [
|
||||
"minijinja",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shlex",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"thiserror 2.0.17",
|
||||
"tokio",
|
||||
"topological-sort",
|
||||
"uuid",
|
||||
@@ -1345,3 +1845,110 @@ dependencies = [
|
||||
"encoding_rs",
|
||||
"hashlink",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "5.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b622b18155f7a93d1cd2dc8c01d2d6a44e08fb9ebb7b3f9e6ed101488bad6c91"
|
||||
dependencies = [
|
||||
"async-broadcast",
|
||||
"async-executor",
|
||||
"async-io",
|
||||
"async-lock",
|
||||
"async-process",
|
||||
"async-recursion",
|
||||
"async-task",
|
||||
"async-trait",
|
||||
"blocking",
|
||||
"enumflags2",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
"futures-lite",
|
||||
"hex",
|
||||
"nix 0.30.1",
|
||||
"ordered-stream",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
"tracing",
|
||||
"uds_windows",
|
||||
"uuid",
|
||||
"windows-sys 0.61.2",
|
||||
"winnow",
|
||||
"zbus_macros",
|
||||
"zbus_names",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus_macros"
|
||||
version = "5.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cdb94821ca8a87ca9c298b5d1cbd80e2a8b67115d99f6e4551ac49e42b6a314"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"zbus_names",
|
||||
"zvariant",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zbus_names"
|
||||
version = "4.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"static_assertions",
|
||||
"winnow",
|
||||
"zvariant",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9747e91771f56fd7893e1164abd78febd14a670ceec257caad15e051de35f06"
|
||||
|
||||
[[package]]
|
||||
name = "zvariant"
|
||||
version = "5.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2be61892e4f2b1772727be11630a62664a1826b62efa43a6fe7449521cb8744c"
|
||||
dependencies = [
|
||||
"endi",
|
||||
"enumflags2",
|
||||
"serde",
|
||||
"winnow",
|
||||
"zvariant_derive",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_derive"
|
||||
version = "5.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da58575a1b2b20766513b1ec59d8e2e68db2745379f961f86650655e862d2006"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"zvariant_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zvariant_utils"
|
||||
version = "3.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6949d142f89f6916deca2232cf26a8afacf2b9fdc35ce766105e104478be599"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"syn",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
@@ -4,6 +4,8 @@ version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.100"
|
||||
cgroups-rs = "0.5.0"
|
||||
chrono = { version = "0.4.42", features = ["serde"] }
|
||||
clap = { version = "4.5.53", features = ["derive"] }
|
||||
config = "0.15.19"
|
||||
@@ -13,6 +15,7 @@ log = "0.4.28"
|
||||
minijinja = "2.14.0"
|
||||
regex = "1.12.2"
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = "1.0.148"
|
||||
shlex = "1.3.0"
|
||||
tempfile = "3.24.0"
|
||||
thiserror = "2.0.17"
|
||||
|
||||
@@ -0,0 +1,187 @@
|
||||
use crate::Cli;
|
||||
use serde::Serialize;
|
||||
use serde_json::Value;
|
||||
use std::sync::Arc;
|
||||
use tokio::io::{AsyncBufReadExt, BufReader};
|
||||
use tokio::net::{UnixListener, UnixStream};
|
||||
use tokio::process::{Child, Command};
|
||||
use tokio::signal;
|
||||
use tokio::sync::RwLock;
|
||||
use tokio::time::{Duration, interval};
|
||||
|
||||
#[derive(Debug, Clone, Serialize)]
|
||||
struct Heartbeat {
|
||||
pipeline_id: String,
|
||||
build_id: String,
|
||||
stage: String,
|
||||
timestamp: u64,
|
||||
status: String,
|
||||
subtasks: Vec<String>,
|
||||
}
|
||||
|
||||
pub async fn daemon(cli: &Cli) {
|
||||
let _ = std::fs::remove_file("/tmp/wsexecutor.sock");
|
||||
|
||||
let mut heartbeat = Arc::new(RwLock::new(Heartbeat {
|
||||
pipeline_id: cli.pipeline.clone(),
|
||||
build_id: cli.build_id.clone(),
|
||||
stage: String::new(),
|
||||
timestamp: 0,
|
||||
status: String::new(),
|
||||
subtasks: Vec::new(),
|
||||
}));
|
||||
|
||||
// let heartbeat_clone = heartbeat.clone();
|
||||
let heartbeat_task = {
|
||||
let hb = heartbeat.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut tick = interval(Duration::from_secs(1));
|
||||
loop {
|
||||
tick.tick().await;
|
||||
let mut hb = hb.write().await;
|
||||
hb.timestamp = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_millis() as u64;
|
||||
|
||||
// 只输出到stdout(模拟未来发送给Agent)
|
||||
println!("[HEARTBEAT] {}", serde_json::to_string(&*hb).unwrap());
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
let socket_task = tokio::spawn(async move {
|
||||
log::info!("Creating Unix socket at /tmp/wsexecutor.sock");
|
||||
let listener =
|
||||
UnixListener::bind("/tmp/wsexecutor.sock").expect("Failed to bind Unix socket");
|
||||
|
||||
loop {
|
||||
match listener.accept().await {
|
||||
Ok((stream, _)) => {
|
||||
tokio::spawn(handle_connection(stream));
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Accept error: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let execution_task = {
|
||||
let hb = heartbeat.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut hb = hb.write().await;
|
||||
let mut children: Vec<(String, Child)> = vec![];
|
||||
|
||||
for _i in 1..=3 {
|
||||
let child = Command::new("bash")
|
||||
.arg("-c")
|
||||
.arg("'echo running!'")
|
||||
.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
.expect("Failed to spawn child");
|
||||
|
||||
let pid = child.id().unwrap_or(0).to_string();
|
||||
children.push((pid.clone(), child));
|
||||
|
||||
hb.subtasks.push(pid.clone());
|
||||
}
|
||||
|
||||
for (pid, mut child) in children {
|
||||
let status = child.wait().await.expect("Failed to wait child");
|
||||
log::info!("Subtask {} exited with: {}", pid, status);
|
||||
|
||||
hb.subtasks.retain(|p| p != &pid);
|
||||
}
|
||||
|
||||
hb.stage = "Success".to_string();
|
||||
})
|
||||
};
|
||||
|
||||
tokio::select! {
|
||||
_ = heartbeat_task => {
|
||||
log::error!("Heartbeat task died");
|
||||
}
|
||||
_ = execution_task => {
|
||||
log::info!("All subtasks completed");
|
||||
}
|
||||
_ = socket_task => {
|
||||
log::error!("Socket task died");
|
||||
}
|
||||
_ = signal::ctrl_c() => {
|
||||
log::info!("Shutting down...");
|
||||
// 清理子进程
|
||||
}
|
||||
}
|
||||
// 清理子进程(防止僵尸)
|
||||
for pid in heartbeat.read().await.subtasks.clone() {
|
||||
// 发送SIGTERM
|
||||
let _ = Command::new("kill").arg("-TERM").arg(&pid).status().await;
|
||||
}
|
||||
|
||||
// 清理socket
|
||||
let _ = std::fs::remove_file("/tmp/wsexecutor.sock");
|
||||
}
|
||||
|
||||
async fn handle_connection(stream: UnixStream) {
|
||||
let peer_addr = match stream.peer_addr() {
|
||||
Ok(addr) => format!("{:?}", addr),
|
||||
Err(_) => "unknown".to_string(),
|
||||
};
|
||||
|
||||
log::debug!("New connection from: {}", peer_addr);
|
||||
|
||||
let mut reader = BufReader::new(stream);
|
||||
let mut line = String::new();
|
||||
|
||||
loop {
|
||||
line.clear();
|
||||
match reader.read_line(&mut line).await {
|
||||
Ok(0) => {
|
||||
log::debug!("Connection closed by peer: {}", peer_addr);
|
||||
break;
|
||||
}
|
||||
Ok(_) => {
|
||||
// 简单打印原始JSON(预留字段解析空间)
|
||||
match serde_json::from_str::<Value>(&line) {
|
||||
Ok(json) => {
|
||||
// 只提取关键字段打印(字段可能变化)
|
||||
let msgtype = json
|
||||
.get("msgtype")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("unknown");
|
||||
let name = json
|
||||
.get("name")
|
||||
.and_then(|v| v.as_str())
|
||||
.unwrap_or("unnamed");
|
||||
|
||||
log::info!("[{}] Message from '{}': {}", msgtype, name, line.trim());
|
||||
|
||||
// TODO: 字段稳定后,可扩展为结构化打印
|
||||
// match msgtype {
|
||||
// "ResourceUsage" => print_resource(&json),
|
||||
// "Log" => print_log(&json),
|
||||
// _ => log::debug!("Unknown type: {}", msgtype),
|
||||
// }
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!(
|
||||
"Invalid JSON from {}: {} - Error: {}",
|
||||
peer_addr,
|
||||
line.trim(),
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to read from {}: {}", peer_addr, e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log::debug!("Connection handler for {} exiting", peer_addr);
|
||||
}
|
||||
@@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::time::Duration;
|
||||
use tokio::process::Command;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ResourceUsage {
|
||||
@@ -12,7 +13,7 @@ pub struct ResourceUsage {
|
||||
pub io_write_kb: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
||||
pub struct RetryPolicy {
|
||||
pub max_attempts: usize,
|
||||
pub backoff_ms: u64,
|
||||
@@ -92,7 +93,7 @@ pub async fn execute(
|
||||
env_vars: HashMap<String, String>,
|
||||
event_tx: Option<tokio::sync::mpsc::Sender<ExecutionEvent>>,
|
||||
) -> Result<ExecutionResult, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let retry_policy = RetryPolicy {
|
||||
let mut retry_policy = RetryPolicy {
|
||||
max_attempts: 1,
|
||||
backoff_ms: 0,
|
||||
jitter: false,
|
||||
@@ -117,14 +118,14 @@ pub async fn execute(
|
||||
script_path,
|
||||
pipeline_name,
|
||||
username,
|
||||
task_id: function.name,
|
||||
task_id: function.name.clone(),
|
||||
working_dir,
|
||||
env_vars,
|
||||
timeout,
|
||||
retry_policy,
|
||||
};
|
||||
let mut attempt = 1;
|
||||
let start_time = std::time::Instant::now();
|
||||
// let start_time = std::time::Instant::now();
|
||||
|
||||
loop {
|
||||
if let Some(tx) = &event_tx {
|
||||
@@ -133,9 +134,96 @@ pub async fn execute(
|
||||
timestamp: chrono::Utc::now(),
|
||||
});
|
||||
}
|
||||
match execute_single(context, attempt, event_tx.clone()).await {
|
||||
match execute_single(&context, attempt, event_tx.clone()).await {
|
||||
Ok(result) => {
|
||||
log::info!("Task {} succeeded on attempt {}", context.task_id, attempt);
|
||||
return Ok(result);
|
||||
}
|
||||
Err((error, retryable)) => {
|
||||
if let Some(tx) = &event_tx {
|
||||
let _ = tx.send(ExecutionEvent::TaskFailed { task_id: context.task_id.clone(), error:error.clone(), retryable, attempt }).await;
|
||||
}
|
||||
|
||||
if retryable && attempt < retry_policy.max_attempts {
|
||||
attempt += 1;
|
||||
log::info!("Task {} failed on attempt {}, retrying...", context.task_id, attempt);
|
||||
|
||||
tokio::time::sleep(Duration::from_millis(retry_policy.backoff_ms)).await;
|
||||
continue;
|
||||
} else {
|
||||
return Err(format!("Task {} failed after {} attempts", context.task_id, attempt).into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
todo!();
|
||||
}
|
||||
|
||||
async fn execute_single(
|
||||
context: &ExecutionContext,
|
||||
attempt: usize,
|
||||
event_tx: Option<tokio::sync::mpsc::Sender<ExecutionEvent>>,
|
||||
) -> Result<ExecutionResult, (String, bool)> {
|
||||
let start_time = std::time::Instant::now();
|
||||
let mut command = Command::new("bash"); // TODO: 换成可变的解释器
|
||||
command.current_dir(&context.working_dir);
|
||||
|
||||
command.envs(&context.env_vars);
|
||||
command.env("WS_TASKID", &context.task_id);
|
||||
command.env("WS_PIPELINE", &context.pipeline_name);
|
||||
command.env("WS_ATTEMPT", attempt.to_string());
|
||||
|
||||
command.arg(&context.script_path); // TODO: 适配可变的解释器
|
||||
|
||||
let child = match command.stdout(std::process::Stdio::piped())
|
||||
.stderr(std::process::Stdio::piped())
|
||||
.spawn()
|
||||
{
|
||||
Ok(child) => child,
|
||||
Err(err) => {
|
||||
return Err((format!("Failed to spawn command: {}", err), false));
|
||||
}
|
||||
};
|
||||
|
||||
let pid = child.id();
|
||||
log::debug!("Task {} started with PID {}", context.task_id, pid.unwrap_or(0));
|
||||
todo!();
|
||||
|
||||
/*
|
||||
let output_handler = OutputHandler::new(); // TODO: 完成OutputHandler
|
||||
|
||||
let result = if let Some(timeout) = context.timeout && timeout.as_secs() > 0{
|
||||
tokio::time::timeout(timeout, output_handler.wait()).await
|
||||
} else {
|
||||
Ok(output_handler.wait().await)
|
||||
};
|
||||
|
||||
match result.flatten() {
|
||||
Ok((exit_code, stdout_len, stderr_len, new_env)) => {
|
||||
let duration = start_time.elapsed();
|
||||
|
||||
let result = ExecutionResult {
|
||||
task_id: context.task_id.clone(),
|
||||
exit_code,
|
||||
success: exit_code == 0,
|
||||
duration,
|
||||
stdout_bytes: stdout_len,
|
||||
stderr_bytes: stderr_len,
|
||||
new_env_vars: new_env,
|
||||
resource_usage: None,
|
||||
};
|
||||
if let Some(tx) = &event_tx {
|
||||
let _ = tx.send(ExecutionEvent::TaskCompleted {
|
||||
task_id: context.task_id.clone(),
|
||||
result: result.clone(),
|
||||
}).await;
|
||||
}
|
||||
|
||||
return Ok(result)
|
||||
}
|
||||
Err(e) => {
|
||||
return Err((format!("Execution error: {}", e), true))
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
mod parser;
|
||||
mod decorator;
|
||||
mod schedule;
|
||||
mod error;
|
||||
mod variable;
|
||||
mod builder;
|
||||
mod decorator;
|
||||
mod engine;
|
||||
use clap::{Parser};
|
||||
mod error;
|
||||
mod monitor;
|
||||
mod parser;
|
||||
mod schedule;
|
||||
mod variable;
|
||||
mod daemon;
|
||||
use clap::{Parser, Subcommand};
|
||||
use config::Config;
|
||||
use env_logger;
|
||||
|
||||
use crate::monitor::monitor;
|
||||
use crate::daemon::daemon;
|
||||
|
||||
/// Honey Biscuit Workshop script executor
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about=None)]
|
||||
struct Args {
|
||||
/// Path to the script to execute
|
||||
script: String,
|
||||
|
||||
/// Path to bake_base.sh
|
||||
#[arg(short, long, default_value="./bake_base.sh")]
|
||||
bake_base: String,
|
||||
|
||||
struct Cli {
|
||||
/// Username of the pipeline executor
|
||||
#[arg(short, long)]
|
||||
username: String,
|
||||
@@ -27,17 +26,71 @@ struct Args {
|
||||
#[arg(short, long)]
|
||||
pipeline: String,
|
||||
|
||||
/// Build ID of this build
|
||||
#[arg(short, long)]
|
||||
build_id: String,
|
||||
|
||||
/// Parse the script without executing
|
||||
#[arg(long, default_value="false")]
|
||||
#[arg(long, default_value = "false")]
|
||||
dry_run: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
command: Option<Commands>,
|
||||
}
|
||||
|
||||
fn main(){
|
||||
#[derive(Subcommand, Debug)]
|
||||
enum Commands {
|
||||
/// Monitor a running task
|
||||
Monitor { group: String },
|
||||
/// Prepare a task
|
||||
Prebake {
|
||||
config: String,
|
||||
},
|
||||
/// Run a task
|
||||
Bake {
|
||||
/// Path to the script to execute
|
||||
script: String,
|
||||
|
||||
/// Path to bake_base.sh
|
||||
#[arg(short, long, default_value = "./bake_base.sh")]
|
||||
bake_base: String,
|
||||
|
||||
},
|
||||
/// Finish a task
|
||||
Finalize {
|
||||
config: String,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
env_logger::init();
|
||||
let mut settings = Config::builder()
|
||||
// .add_source(config::File::with_name("_config.toml"))
|
||||
.add_source(config::Environment::with_prefix("HBW_EXEC_"))
|
||||
.build()
|
||||
.unwrap();
|
||||
let args = Args::parse();
|
||||
let cli = Cli::parse();
|
||||
match &cli.command {
|
||||
Some(Commands::Monitor { group }) => {
|
||||
log::info!("Starting monitor for group: {}", group);
|
||||
let result = monitor(group, Some(1000)).await;
|
||||
result.unwrap();
|
||||
}
|
||||
Some(Commands::Prebake { config }) => {
|
||||
// builder::prebake(config);
|
||||
}
|
||||
Some(Commands::Bake {script, bake_base}) => {
|
||||
// builder::bake(script, bake_base, username, pipeline, *dry_run);
|
||||
}
|
||||
Some(Commands::Finalize {config}) => {
|
||||
// builder::finalize(config);
|
||||
}
|
||||
None => {
|
||||
// Running in daemon mode
|
||||
log::info!("Executor will be running in daemon mode.");
|
||||
|
||||
let result = daemon(&cli).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
mod cgroups;
|
||||
mod jobobject;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::time::Instant;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct ResourceUsageInfo {
|
||||
pub msgtype: String,
|
||||
pub name: String,
|
||||
pub os_type: OsType,
|
||||
pub statistics: UsageStats,
|
||||
pub timestamp: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum OsType {
|
||||
Linux,
|
||||
Windows,
|
||||
MacOS,
|
||||
}
|
||||
|
||||
enum AgentSocket {
|
||||
Unix(String),
|
||||
Tcp(String),
|
||||
DryRun
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct UsageStats {
|
||||
pub cpu_usage_percent: f64,
|
||||
pub memory_usage_bytes: u64,
|
||||
pub memory_limit_bytes: i64,
|
||||
// pub memory_usage_percent: f64,
|
||||
pub process_count: u64,
|
||||
pub cpu_usage_us: u64,
|
||||
/// Internal timestamp, using std::Instant
|
||||
#[serde(skip, default="default_internal_timestamp")]
|
||||
_timestamp: Instant,
|
||||
}
|
||||
|
||||
fn default_internal_timestamp() -> Instant{
|
||||
Instant::now()
|
||||
}
|
||||
|
||||
pub async fn monitor(name: &String, interval_ms: Option<u64>) -> anyhow::Result<()> {
|
||||
let socket_addr = get_wsagent_socket_addr()?;
|
||||
let interval = tokio::time::Duration::from_millis(interval_ms.unwrap_or(1000));
|
||||
let mut socket = establish_connection(&socket_addr).await?;
|
||||
let mut prev_usage = UsageStats{
|
||||
cpu_usage_percent: 0.0,
|
||||
memory_usage_bytes: 0,
|
||||
memory_limit_bytes: 0,
|
||||
process_count: 0,
|
||||
cpu_usage_us: 0,
|
||||
_timestamp: default_internal_timestamp(),
|
||||
};
|
||||
loop {
|
||||
let usage:UsageStats = cgroups::get_usage(&name, prev_usage)?; // TODO: 多系统支持?
|
||||
prev_usage = usage.clone();
|
||||
// dbg!(&usage);
|
||||
let usage_info = ResourceUsageInfo {
|
||||
msgtype: "ResourceUsage".to_string(),
|
||||
name: name.clone(),
|
||||
os_type: OsType::Linux, // TODO: 多系统支持?
|
||||
statistics: usage,
|
||||
timestamp: std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH)?.as_millis() as u64,
|
||||
};
|
||||
|
||||
let usage_json = serde_json::to_string(&usage_info)?;
|
||||
|
||||
send_usage_info(&mut socket, &usage_json).await?;
|
||||
// TODO: 增加消息接收,提供(伪)双向通信功能
|
||||
|
||||
tokio::time::sleep(interval).await;
|
||||
}
|
||||
}
|
||||
|
||||
fn get_wsagent_socket_addr() -> anyhow::Result<AgentSocket> {
|
||||
let socket_addr = std::env::var("WSAGENT_SOCK")
|
||||
.map_err(|_| anyhow::anyhow!("WSAGENT_SOCK is not set!"))?;
|
||||
let socket = if socket_addr.starts_with("unix://") {
|
||||
AgentSocket::Unix(socket_addr.strip_prefix("unix://").unwrap().to_string())
|
||||
} else if socket_addr.starts_with("/") {
|
||||
AgentSocket::Unix(socket_addr)
|
||||
} else if socket_addr.starts_with("tcp://") {
|
||||
AgentSocket::Tcp(socket_addr.strip_prefix("tcp://").unwrap().to_string())
|
||||
} else if socket_addr.starts_with("dryrun") {
|
||||
AgentSocket::DryRun
|
||||
} else { // TCP by default
|
||||
AgentSocket::Tcp(socket_addr)
|
||||
};
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
async fn send_usage_info<S>(stream: &mut S, usage_json: &str) -> anyhow::Result<()>
|
||||
where S: tokio::io::AsyncWrite + Unpin
|
||||
{
|
||||
stream.write(usage_json.as_bytes()).await?;
|
||||
stream.write_all(b"\n").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn establish_connection(socket_addr: &AgentSocket) -> anyhow::Result<Box<dyn tokio::io::AsyncWrite + Unpin>> {
|
||||
match &socket_addr {
|
||||
AgentSocket::Unix(path) => {
|
||||
let socket = tokio::net::UnixStream::connect(path).await?;
|
||||
Ok(Box::new(socket) as Box<dyn tokio::io::AsyncWrite + Unpin>)
|
||||
}
|
||||
|
||||
AgentSocket::Tcp(path) => {
|
||||
let socket = tokio::net::TcpStream::connect(path).await?;
|
||||
Ok(Box::new(socket) as Box<dyn tokio::io::AsyncWrite + Unpin>)
|
||||
}
|
||||
|
||||
AgentSocket::DryRun => {
|
||||
Ok(Box::new(tokio::io::sink()) as Box<dyn tokio::io::AsyncWrite + Unpin>)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
use cgroups_rs;
|
||||
use cgroups_rs::{fs::{cpu::CpuController, memory::MemController, pid::PidController}, stats::CpuAcctStats};
|
||||
use log;
|
||||
use cgroups_rs::fs::Cgroup;
|
||||
use std::time::{Instant, Duration};
|
||||
use crate::monitor::UsageStats;
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn get_usage(name: &String, usage_prev: crate::monitor::UsageStats) -> anyhow::Result<crate::monitor::UsageStats> {
|
||||
let hierarchy = cgroups_rs::fs::hierarchies::auto();
|
||||
if !hierarchy.v2() {
|
||||
return Err(anyhow::anyhow!("Unsupported cgroup hierarchy, cgroups v2 required."));
|
||||
}
|
||||
let cgroup = Cgroup::load(hierarchy, name);
|
||||
let mut cpu_usage_us: u64 = 0;
|
||||
let mut cpu_usage_percent: f64 = 0.0;
|
||||
let mut memory_usage_bytes: u64 = 0;
|
||||
let mut memory_limit_bytes: i64 = 0;
|
||||
let mut process_count: u64 = 0;
|
||||
|
||||
if let Some(cpu) = cgroup.controller_of::<CpuController>() {
|
||||
let stats = parse_cpustat(&cpu.cpu().stat.as_str())?;
|
||||
cpu_usage_us = stats.usage_usec;
|
||||
}
|
||||
else {
|
||||
log::warn!("Failed to fetch CPU usage info!");
|
||||
}
|
||||
|
||||
let current = Instant::now();
|
||||
let delta_usage = cpu_usage_us - usage_prev.cpu_usage_us;
|
||||
let delta_wall = current - usage_prev._timestamp;
|
||||
if usage_prev._timestamp > current {
|
||||
log::warn!("Usage stats are from the future!");
|
||||
}
|
||||
else if usage_prev.cpu_usage_us == 0 {
|
||||
log::info!("Previous CPU usage is zero, probably a fresh start.");
|
||||
}
|
||||
else if delta_wall < Duration::from_millis(1) {
|
||||
log::warn!("Usage stats are too close together!");
|
||||
}
|
||||
else {
|
||||
cpu_usage_percent = delta_usage as f64 / delta_wall.as_micros() as f64 * 100.0;
|
||||
// dbg!(&delta_usage, &delta_wall);
|
||||
}
|
||||
|
||||
if let Some(mem) = cgroup.controller_of::<MemController>() {
|
||||
let stats = mem.memory_stat();
|
||||
memory_usage_bytes = stats.usage_in_bytes;
|
||||
memory_limit_bytes = stats.limit_in_bytes;
|
||||
}
|
||||
|
||||
if let Some(proc) = cgroup.controller_of::<PidController>() {
|
||||
process_count = proc.get_pid_current()?;
|
||||
}
|
||||
Ok(UsageStats{
|
||||
cpu_usage_us,
|
||||
cpu_usage_percent,
|
||||
memory_usage_bytes,
|
||||
// memory_usage_percent: 0.0,
|
||||
memory_limit_bytes,
|
||||
process_count,
|
||||
_timestamp: Instant::now(),
|
||||
})
|
||||
|
||||
// todo!();
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct CgroupCpuStat {
|
||||
pub usage_usec: u64,
|
||||
pub user_usec: u64,
|
||||
pub system_usec: u64,
|
||||
pub nice_usec: u64,
|
||||
pub core_sched_force_idle_usec: u64,
|
||||
pub nr_periods: u64,
|
||||
pub nr_throttled: u64,
|
||||
pub throttled_usec: u64,
|
||||
pub nr_bursts: u64,
|
||||
pub burst_usec: u64,
|
||||
}
|
||||
|
||||
fn parse_cpustat(stat: &str) -> anyhow::Result<CgroupCpuStat> {
|
||||
let mut cpu_stat = CgroupCpuStat::default();
|
||||
for line in stat.lines() {
|
||||
let line = line.trim();
|
||||
if line.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let (key, value_str) = line
|
||||
.split_once(' ')
|
||||
.ok_or_else(|| anyhow::anyhow!("Invalid format:{}", line))?;
|
||||
|
||||
let value = value_str
|
||||
.parse::<u64>()
|
||||
.map_err(|e| anyhow::anyhow!("Cannot convert value {}({}) into integer: {}", key, value_str, e))?;
|
||||
|
||||
match key {
|
||||
"usage_usec" => cpu_stat.usage_usec = value,
|
||||
"user_usec" => cpu_stat.user_usec = value,
|
||||
"system_usec" => cpu_stat.system_usec = value,
|
||||
"nice_usec" => cpu_stat.nice_usec = value,
|
||||
"core_sched.force_idle_usec" => cpu_stat.core_sched_force_idle_usec = value,
|
||||
"nr_periods" => cpu_stat.nr_periods = value,
|
||||
"nr_throttled" => cpu_stat.nr_throttled = value,
|
||||
"throttled_usec" => cpu_stat.throttled_usec = value,
|
||||
"nr_bursts" => cpu_stat.nr_bursts = value,
|
||||
"burst_usec" => cpu_stat.burst_usec = value,
|
||||
_unknown_key => {}, // Ignore unknown keys
|
||||
}
|
||||
}
|
||||
Ok(cpu_stat)
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_usage() -> anyhow::Result<f64> {
|
||||
unimplemented!("Not supporting windows JobObject at this time!");
|
||||
}
|
||||
Reference in New Issue
Block a user