Author:
Hash:
Timestamp:
+1420 -3479 +/-99 browse
Kevin Schoon [me@kevinschoon.com]
394a7b279ab0e646443e7d95d1099dd71a7f83b3
Wed, 06 May 2026 08:59:57 +0000 (1 month ago)
| 1 | diff --git a/Cargo.lock b/Cargo.lock |
| 2 | index 8d83389..232e1d1 100644 |
| 3 | --- a/Cargo.lock |
| 4 | +++ b/Cargo.lock |
| 5 | @@ -12,12 +12,6 @@ dependencies = [ |
| 6 | ] |
| 7 | |
| 8 | [[package]] |
| 9 | - name = "allocator-api2" |
| 10 | - version = "0.2.21" |
| 11 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 12 | - checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" |
| 13 | - |
| 14 | - [[package]] |
| 15 | name = "android_system_properties" |
| 16 | version = "0.1.5" |
| 17 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 18 | @@ -121,7 +115,7 @@ dependencies = [ |
| 19 | "memchr", |
| 20 | "serde", |
| 21 | "serde_derive", |
| 22 | - "winnow", |
| 23 | + "winnow 0.7.15", |
| 24 | ] |
| 25 | |
| 26 | [[package]] |
| 27 | @@ -145,15 +139,6 @@ dependencies = [ |
| 28 | ] |
| 29 | |
| 30 | [[package]] |
| 31 | - name = "atoi" |
| 32 | - version = "2.0.0" |
| 33 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 34 | - checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" |
| 35 | - dependencies = [ |
| 36 | - "num-traits", |
| 37 | - ] |
| 38 | - |
| 39 | - [[package]] |
| 40 | name = "atom_syndication" |
| 41 | version = "0.12.7" |
| 42 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 43 | @@ -179,6 +164,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 44 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" |
| 45 | |
| 46 | [[package]] |
| 47 | + name = "aws-lc-rs" |
| 48 | + version = "1.16.3" |
| 49 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 50 | + checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" |
| 51 | + dependencies = [ |
| 52 | + "aws-lc-sys", |
| 53 | + "zeroize", |
| 54 | + ] |
| 55 | + |
| 56 | + [[package]] |
| 57 | + name = "aws-lc-sys" |
| 58 | + version = "0.40.0" |
| 59 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 60 | + checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" |
| 61 | + dependencies = [ |
| 62 | + "cc", |
| 63 | + "cmake", |
| 64 | + "dunce", |
| 65 | + "fs_extra", |
| 66 | + ] |
| 67 | + |
| 68 | + [[package]] |
| 69 | name = "axum" |
| 70 | version = "0.8.9" |
| 71 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 72 | @@ -341,7 +348,6 @@ dependencies = [ |
| 73 | name = "ayllu-build" |
| 74 | version = "0.2.1" |
| 75 | dependencies = [ |
| 76 | - "async-trait", |
| 77 | "ayllu_api", |
| 78 | "ayllu_cmd", |
| 79 | "ayllu_config", |
| 80 | @@ -349,7 +355,6 @@ dependencies = [ |
| 81 | "ayllu_git", |
| 82 | "ayllu_logging", |
| 83 | "bytes", |
| 84 | - "futures", |
| 85 | "petgraph", |
| 86 | "reqwest", |
| 87 | "serde", |
| 88 | @@ -424,7 +429,7 @@ dependencies = [ |
| 89 | "serde_json", |
| 90 | "tempfile", |
| 91 | "thiserror 2.0.18", |
| 92 | - "toml", |
| 93 | + "toml 0.8.23", |
| 94 | "toml_edit", |
| 95 | ] |
| 96 | |
| 97 | @@ -432,12 +437,12 @@ dependencies = [ |
| 98 | name = "ayllu_database" |
| 99 | version = "0.2.1" |
| 100 | dependencies = [ |
| 101 | - "async-trait", |
| 102 | - "futures", |
| 103 | + "diesel", |
| 104 | + "diesel_migrations", |
| 105 | "serde", |
| 106 | "serde_json", |
| 107 | - "sqlx", |
| 108 | - "time", |
| 109 | + "thiserror 2.0.18", |
| 110 | + "timeutil", |
| 111 | "tracing", |
| 112 | ] |
| 113 | |
| 114 | @@ -446,7 +451,7 @@ name = "ayllu_git" |
| 115 | version = "0.2.1" |
| 116 | dependencies = [ |
| 117 | "git2", |
| 118 | - "rand 0.9.4", |
| 119 | + "rand", |
| 120 | "serde", |
| 121 | "tempfile", |
| 122 | "tokio", |
| 123 | @@ -483,12 +488,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 124 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" |
| 125 | |
| 126 | [[package]] |
| 127 | - name = "base64ct" |
| 128 | - version = "1.8.3" |
| 129 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 130 | - checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" |
| 131 | - |
| 132 | - [[package]] |
| 133 | name = "basic-toml" |
| 134 | version = "0.1.10" |
| 135 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 136 | @@ -502,9 +501,6 @@ name = "bitflags" |
| 137 | version = "2.11.1" |
| 138 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 139 | checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" |
| 140 | - dependencies = [ |
| 141 | - "serde_core", |
| 142 | - ] |
| 143 | |
| 144 | [[package]] |
| 145 | name = "block-buffer" |
| 146 | @@ -561,6 +557,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 147 | checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" |
| 148 | |
| 149 | [[package]] |
| 150 | + name = "cfg_aliases" |
| 151 | + version = "0.2.1" |
| 152 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 153 | + checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" |
| 154 | + |
| 155 | + [[package]] |
| 156 | name = "chrono" |
| 157 | version = "0.4.44" |
| 158 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 159 | @@ -623,6 +625,15 @@ dependencies = [ |
| 160 | ] |
| 161 | |
| 162 | [[package]] |
| 163 | + name = "cmake" |
| 164 | + version = "0.1.58" |
| 165 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 166 | + checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" |
| 167 | + dependencies = [ |
| 168 | + "cc", |
| 169 | + ] |
| 170 | + |
| 171 | + [[package]] |
| 172 | name = "colorchoice" |
| 173 | version = "1.0.5" |
| 174 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 175 | @@ -653,15 +664,6 @@ dependencies = [ |
| 176 | ] |
| 177 | |
| 178 | [[package]] |
| 179 | - name = "concurrent-queue" |
| 180 | - version = "2.5.0" |
| 181 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 182 | - checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" |
| 183 | - dependencies = [ |
| 184 | - "crossbeam-utils", |
| 185 | - ] |
| 186 | - |
| 187 | - [[package]] |
| 188 | name = "console" |
| 189 | version = "0.15.11" |
| 190 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 191 | @@ -681,12 +683,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 192 | checksum = "cb16320721f6441f979feff82c8b4fe789a5423f48e4e724d124211c44be43af" |
| 193 | |
| 194 | [[package]] |
| 195 | - name = "const-oid" |
| 196 | - version = "0.9.6" |
| 197 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 198 | - checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" |
| 199 | - |
| 200 | - [[package]] |
| 201 | name = "convert_case" |
| 202 | version = "0.6.0" |
| 203 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 204 | @@ -732,36 +728,6 @@ dependencies = [ |
| 205 | ] |
| 206 | |
| 207 | [[package]] |
| 208 | - name = "crc" |
| 209 | - version = "3.4.0" |
| 210 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 211 | - checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" |
| 212 | - dependencies = [ |
| 213 | - "crc-catalog", |
| 214 | - ] |
| 215 | - |
| 216 | - [[package]] |
| 217 | - name = "crc-catalog" |
| 218 | - version = "2.5.0" |
| 219 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 220 | - checksum = "217698eaf96b4a3f0bc4f3662aaa55bdf913cd54d7204591faa790070c6d0853" |
| 221 | - |
| 222 | - [[package]] |
| 223 | - name = "crossbeam-queue" |
| 224 | - version = "0.3.12" |
| 225 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 226 | - checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" |
| 227 | - dependencies = [ |
| 228 | - "crossbeam-utils", |
| 229 | - ] |
| 230 | - |
| 231 | - [[package]] |
| 232 | - name = "crossbeam-utils" |
| 233 | - version = "0.8.21" |
| 234 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 235 | - checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" |
| 236 | - |
| 237 | - [[package]] |
| 238 | name = "crypto-common" |
| 239 | version = "0.1.7" |
| 240 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 241 | @@ -783,6 +749,16 @@ dependencies = [ |
| 242 | |
| 243 | [[package]] |
| 244 | name = "darling" |
| 245 | + version = "0.21.3" |
| 246 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 247 | + checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" |
| 248 | + dependencies = [ |
| 249 | + "darling_core 0.21.3", |
| 250 | + "darling_macro 0.21.3", |
| 251 | + ] |
| 252 | + |
| 253 | + [[package]] |
| 254 | + name = "darling" |
| 255 | version = "0.23.0" |
| 256 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 257 | checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" |
| 258 | @@ -807,6 +783,20 @@ dependencies = [ |
| 259 | |
| 260 | [[package]] |
| 261 | name = "darling_core" |
| 262 | + version = "0.21.3" |
| 263 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 264 | + checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" |
| 265 | + dependencies = [ |
| 266 | + "fnv", |
| 267 | + "ident_case", |
| 268 | + "proc-macro2", |
| 269 | + "quote", |
| 270 | + "strsim", |
| 271 | + "syn", |
| 272 | + ] |
| 273 | + |
| 274 | + [[package]] |
| 275 | + name = "darling_core" |
| 276 | version = "0.23.0" |
| 277 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 278 | checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" |
| 279 | @@ -831,24 +821,24 @@ dependencies = [ |
| 280 | |
| 281 | [[package]] |
| 282 | name = "darling_macro" |
| 283 | - version = "0.23.0" |
| 284 | + version = "0.21.3" |
| 285 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 286 | - checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" |
| 287 | + checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" |
| 288 | dependencies = [ |
| 289 | - "darling_core 0.23.0", |
| 290 | + "darling_core 0.21.3", |
| 291 | "quote", |
| 292 | "syn", |
| 293 | ] |
| 294 | |
| 295 | [[package]] |
| 296 | - name = "der" |
| 297 | - version = "0.7.10" |
| 298 | + name = "darling_macro" |
| 299 | + version = "0.23.0" |
| 300 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 301 | - checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" |
| 302 | + checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" |
| 303 | dependencies = [ |
| 304 | - "const-oid", |
| 305 | - "pem-rfc7468", |
| 306 | - "zeroize", |
| 307 | + "darling_core 0.23.0", |
| 308 | + "quote", |
| 309 | + "syn", |
| 310 | ] |
| 311 | |
| 312 | [[package]] |
| 313 | @@ -910,15 +900,59 @@ dependencies = [ |
| 314 | ] |
| 315 | |
| 316 | [[package]] |
| 317 | + name = "diesel" |
| 318 | + version = "2.3.9" |
| 319 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 320 | + checksum = "9940fb8467a0a06312218ed384185cb8536aa10d8ec017d0ce7fad2c1bd882d5" |
| 321 | + dependencies = [ |
| 322 | + "diesel_derives", |
| 323 | + "downcast-rs", |
| 324 | + "libsqlite3-sys", |
| 325 | + "sqlite-wasm-rs", |
| 326 | + "time", |
| 327 | + ] |
| 328 | + |
| 329 | + [[package]] |
| 330 | + name = "diesel_derives" |
| 331 | + version = "2.3.9" |
| 332 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 333 | + checksum = "d1817b7f4279b947fc4cafddec12b0e5f8727141706561ce3ac94a60bddd1cf5" |
| 334 | + dependencies = [ |
| 335 | + "diesel_table_macro_syntax", |
| 336 | + "dsl_auto_type", |
| 337 | + "proc-macro2", |
| 338 | + "quote", |
| 339 | + "syn", |
| 340 | + ] |
| 341 | + |
| 342 | + [[package]] |
| 343 | + name = "diesel_migrations" |
| 344 | + version = "2.3.2" |
| 345 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 346 | + checksum = "28d0f4a98124ba6d4ca75da535f65984badec16a003b6e2f94a01e31a79490b8" |
| 347 | + dependencies = [ |
| 348 | + "diesel", |
| 349 | + "migrations_internals", |
| 350 | + "migrations_macros", |
| 351 | + ] |
| 352 | + |
| 353 | + [[package]] |
| 354 | + name = "diesel_table_macro_syntax" |
| 355 | + version = "0.3.0" |
| 356 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 357 | + checksum = "fe2444076b48641147115697648dc743c2c00b61adade0f01ce67133c7babe8c" |
| 358 | + dependencies = [ |
| 359 | + "syn", |
| 360 | + ] |
| 361 | + |
| 362 | + [[package]] |
| 363 | name = "digest" |
| 364 | version = "0.10.7" |
| 365 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 366 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" |
| 367 | dependencies = [ |
| 368 | "block-buffer", |
| 369 | - "const-oid", |
| 370 | "crypto-common", |
| 371 | - "subtle", |
| 372 | ] |
| 373 | |
| 374 | [[package]] |
| 375 | @@ -942,10 +976,30 @@ dependencies = [ |
| 376 | ] |
| 377 | |
| 378 | [[package]] |
| 379 | - name = "dotenvy" |
| 380 | - version = "0.15.7" |
| 381 | + name = "downcast-rs" |
| 382 | + version = "2.0.2" |
| 383 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 384 | + checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" |
| 385 | + |
| 386 | + [[package]] |
| 387 | + name = "dsl_auto_type" |
| 388 | + version = "0.2.0" |
| 389 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 390 | + checksum = "dd122633e4bef06db27737f21d3738fb89c8f6d5360d6d9d7635dda142a7757e" |
| 391 | + dependencies = [ |
| 392 | + "darling 0.21.3", |
| 393 | + "either", |
| 394 | + "heck", |
| 395 | + "proc-macro2", |
| 396 | + "quote", |
| 397 | + "syn", |
| 398 | + ] |
| 399 | + |
| 400 | + [[package]] |
| 401 | + name = "dunce" |
| 402 | + version = "1.0.5" |
| 403 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 404 | - checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" |
| 405 | + checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" |
| 406 | |
| 407 | [[package]] |
| 408 | name = "dyn-clone" |
| 409 | @@ -958,9 +1012,6 @@ name = "either" |
| 410 | version = "1.15.0" |
| 411 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 412 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" |
| 413 | - dependencies = [ |
| 414 | - "serde", |
| 415 | - ] |
| 416 | |
| 417 | [[package]] |
| 418 | name = "encode_unicode" |
| 419 | @@ -1000,28 +1051,6 @@ dependencies = [ |
| 420 | ] |
| 421 | |
| 422 | [[package]] |
| 423 | - name = "etcetera" |
| 424 | - version = "0.8.0" |
| 425 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 426 | - checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" |
| 427 | - dependencies = [ |
| 428 | - "cfg-if", |
| 429 | - "home", |
| 430 | - "windows-sys 0.48.0", |
| 431 | - ] |
| 432 | - |
| 433 | - [[package]] |
| 434 | - name = "event-listener" |
| 435 | - version = "5.4.1" |
| 436 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 437 | - checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" |
| 438 | - dependencies = [ |
| 439 | - "concurrent-queue", |
| 440 | - "parking", |
| 441 | - "pin-project-lite", |
| 442 | - ] |
| 443 | - |
| 444 | - [[package]] |
| 445 | name = "fastrand" |
| 446 | version = "2.4.1" |
| 447 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 448 | @@ -1060,17 +1089,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 449 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" |
| 450 | |
| 451 | [[package]] |
| 452 | - name = "flume" |
| 453 | - version = "0.11.1" |
| 454 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 455 | - checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" |
| 456 | - dependencies = [ |
| 457 | - "futures-core", |
| 458 | - "futures-sink", |
| 459 | - "spin", |
| 460 | - ] |
| 461 | - |
| 462 | - [[package]] |
| 463 | name = "fnv" |
| 464 | version = "1.0.7" |
| 465 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 466 | @@ -1083,6 +1101,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 467 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" |
| 468 | |
| 469 | [[package]] |
| 470 | + name = "foldhash" |
| 471 | + version = "0.2.0" |
| 472 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 473 | + checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" |
| 474 | + |
| 475 | + [[package]] |
| 476 | name = "form_urlencoded" |
| 477 | version = "1.2.2" |
| 478 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 479 | @@ -1092,6 +1116,12 @@ dependencies = [ |
| 480 | ] |
| 481 | |
| 482 | [[package]] |
| 483 | + name = "fs_extra" |
| 484 | + version = "1.3.0" |
| 485 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 486 | + checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" |
| 487 | + |
| 488 | + [[package]] |
| 489 | name = "futures" |
| 490 | version = "0.3.32" |
| 491 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 492 | @@ -1134,17 +1164,6 @@ dependencies = [ |
| 493 | ] |
| 494 | |
| 495 | [[package]] |
| 496 | - name = "futures-intrusive" |
| 497 | - version = "0.5.0" |
| 498 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 499 | - checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" |
| 500 | - dependencies = [ |
| 501 | - "futures-core", |
| 502 | - "lock_api", |
| 503 | - "parking_lot", |
| 504 | - ] |
| 505 | - |
| 506 | - [[package]] |
| 507 | name = "futures-io" |
| 508 | version = "0.3.32" |
| 509 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 510 | @@ -1207,8 +1226,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 511 | checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" |
| 512 | dependencies = [ |
| 513 | "cfg-if", |
| 514 | + "js-sys", |
| 515 | "libc", |
| 516 | "wasi", |
| 517 | + "wasm-bindgen", |
| 518 | ] |
| 519 | |
| 520 | [[package]] |
| 521 | @@ -1218,9 +1239,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 522 | checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" |
| 523 | dependencies = [ |
| 524 | "cfg-if", |
| 525 | + "js-sys", |
| 526 | "libc", |
| 527 | "r-efi 5.3.0", |
| 528 | "wasip2", |
| 529 | + "wasm-bindgen", |
| 530 | ] |
| 531 | |
| 532 | [[package]] |
| 533 | @@ -1280,25 +1303,23 @@ version = "0.15.5" |
| 534 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 535 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" |
| 536 | dependencies = [ |
| 537 | - "allocator-api2", |
| 538 | - "equivalent", |
| 539 | - "foldhash", |
| 540 | + "foldhash 0.1.5", |
| 541 | ] |
| 542 | |
| 543 | [[package]] |
| 544 | name = "hashbrown" |
| 545 | - version = "0.17.0" |
| 546 | + version = "0.16.1" |
| 547 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 548 | - checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" |
| 549 | + checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" |
| 550 | + dependencies = [ |
| 551 | + "foldhash 0.2.0", |
| 552 | + ] |
| 553 | |
| 554 | [[package]] |
| 555 | - name = "hashlink" |
| 556 | - version = "0.10.0" |
| 557 | + name = "hashbrown" |
| 558 | + version = "0.17.0" |
| 559 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 560 | - checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" |
| 561 | - dependencies = [ |
| 562 | - "hashbrown 0.15.5", |
| 563 | - ] |
| 564 | + checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" |
| 565 | |
| 566 | [[package]] |
| 567 | name = "headers" |
| 568 | @@ -1337,33 +1358,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 569 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" |
| 570 | |
| 571 | [[package]] |
| 572 | - name = "hkdf" |
| 573 | - version = "0.12.4" |
| 574 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 575 | - checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" |
| 576 | - dependencies = [ |
| 577 | - "hmac", |
| 578 | - ] |
| 579 | - |
| 580 | - [[package]] |
| 581 | - name = "hmac" |
| 582 | - version = "0.12.1" |
| 583 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 584 | - checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" |
| 585 | - dependencies = [ |
| 586 | - "digest", |
| 587 | - ] |
| 588 | - |
| 589 | - [[package]] |
| 590 | - name = "home" |
| 591 | - version = "0.5.12" |
| 592 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 593 | - checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" |
| 594 | - dependencies = [ |
| 595 | - "windows-sys 0.61.2", |
| 596 | - ] |
| 597 | - |
| 598 | - [[package]] |
| 599 | name = "http" |
| 600 | version = "1.4.0" |
| 601 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 602 | @@ -1761,9 +1755,6 @@ name = "lazy_static" |
| 603 | version = "1.5.0" |
| 604 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 605 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" |
| 606 | - dependencies = [ |
| 607 | - "spin", |
| 608 | - ] |
| 609 | |
| 610 | [[package]] |
| 611 | name = "leb128fmt" |
| 612 | @@ -1800,12 +1791,6 @@ dependencies = [ |
| 613 | ] |
| 614 | |
| 615 | [[package]] |
| 616 | - name = "libm" |
| 617 | - version = "0.2.16" |
| 618 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 619 | - checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" |
| 620 | - |
| 621 | - [[package]] |
| 622 | name = "libredox" |
| 623 | version = "0.1.16" |
| 624 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 625 | @@ -1819,11 +1804,10 @@ dependencies = [ |
| 626 | |
| 627 | [[package]] |
| 628 | name = "libsqlite3-sys" |
| 629 | - version = "0.30.1" |
| 630 | + version = "0.37.0" |
| 631 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 632 | - checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" |
| 633 | + checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" |
| 634 | dependencies = [ |
| 635 | - "cc", |
| 636 | "pkg-config", |
| 637 | "vcpkg", |
| 638 | ] |
| 639 | @@ -1868,6 +1852,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 640 | checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" |
| 641 | |
| 642 | [[package]] |
| 643 | + name = "lru-slab" |
| 644 | + version = "0.1.2" |
| 645 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 646 | + checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" |
| 647 | + |
| 648 | + [[package]] |
| 649 | name = "matchers" |
| 650 | version = "0.2.0" |
| 651 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 652 | @@ -1899,6 +1889,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 653 | checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" |
| 654 | |
| 655 | [[package]] |
| 656 | + name = "migrations_internals" |
| 657 | + version = "2.3.0" |
| 658 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 659 | + checksum = "36c791ecdf977c99f45f23280405d7723727470f6689a5e6dbf513ac547ae10d" |
| 660 | + dependencies = [ |
| 661 | + "serde", |
| 662 | + "toml 0.9.12+spec-1.1.0", |
| 663 | + ] |
| 664 | + |
| 665 | + [[package]] |
| 666 | + name = "migrations_macros" |
| 667 | + version = "2.3.0" |
| 668 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 669 | + checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703" |
| 670 | + dependencies = [ |
| 671 | + "migrations_internals", |
| 672 | + "proc-macro2", |
| 673 | + "quote", |
| 674 | + ] |
| 675 | + |
| 676 | + [[package]] |
| 677 | name = "mime" |
| 678 | version = "0.3.17" |
| 679 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 680 | @@ -1941,55 +1952,18 @@ dependencies = [ |
| 681 | ] |
| 682 | |
| 683 | [[package]] |
| 684 | - name = "num-bigint-dig" |
| 685 | - version = "0.8.6" |
| 686 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 687 | - checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" |
| 688 | - dependencies = [ |
| 689 | - "lazy_static", |
| 690 | - "libm", |
| 691 | - "num-integer", |
| 692 | - "num-iter", |
| 693 | - "num-traits", |
| 694 | - "rand 0.8.6", |
| 695 | - "smallvec", |
| 696 | - "zeroize", |
| 697 | - ] |
| 698 | - |
| 699 | - [[package]] |
| 700 | name = "num-conv" |
| 701 | version = "0.2.1" |
| 702 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 703 | checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" |
| 704 | |
| 705 | [[package]] |
| 706 | - name = "num-integer" |
| 707 | - version = "0.1.46" |
| 708 | + name = "num-traits" |
| 709 | + version = "0.2.19" |
| 710 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 711 | - checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" |
| 712 | - dependencies = [ |
| 713 | - "num-traits", |
| 714 | - ] |
| 715 | - |
| 716 | - [[package]] |
| 717 | - name = "num-iter" |
| 718 | - version = "0.1.45" |
| 719 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 720 | - checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" |
| 721 | - dependencies = [ |
| 722 | - "autocfg", |
| 723 | - "num-integer", |
| 724 | - "num-traits", |
| 725 | - ] |
| 726 | - |
| 727 | - [[package]] |
| 728 | - name = "num-traits" |
| 729 | - version = "0.2.19" |
| 730 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 731 | - checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" |
| 732 | + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" |
| 733 | dependencies = [ |
| 734 | "autocfg", |
| 735 | - "libm", |
| 736 | ] |
| 737 | |
| 738 | [[package]] |
| 739 | @@ -2048,12 +2022,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 740 | checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" |
| 741 | |
| 742 | [[package]] |
| 743 | - name = "parking" |
| 744 | - version = "2.2.1" |
| 745 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 746 | - checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" |
| 747 | - |
| 748 | - [[package]] |
| 749 | name = "parking_lot" |
| 750 | version = "0.12.5" |
| 751 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 752 | @@ -2077,15 +2045,6 @@ dependencies = [ |
| 753 | ] |
| 754 | |
| 755 | [[package]] |
| 756 | - name = "pem-rfc7468" |
| 757 | - version = "0.7.0" |
| 758 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 759 | - checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" |
| 760 | - dependencies = [ |
| 761 | - "base64ct", |
| 762 | - ] |
| 763 | - |
| 764 | - [[package]] |
| 765 | name = "percent-encoding" |
| 766 | version = "2.3.2" |
| 767 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 768 | @@ -2110,27 +2069,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 769 | checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" |
| 770 | |
| 771 | [[package]] |
| 772 | - name = "pkcs1" |
| 773 | - version = "0.7.5" |
| 774 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 775 | - checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" |
| 776 | - dependencies = [ |
| 777 | - "der", |
| 778 | - "pkcs8", |
| 779 | - "spki", |
| 780 | - ] |
| 781 | - |
| 782 | - [[package]] |
| 783 | - name = "pkcs8" |
| 784 | - version = "0.10.2" |
| 785 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 786 | - checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" |
| 787 | - dependencies = [ |
| 788 | - "der", |
| 789 | - "spki", |
| 790 | - ] |
| 791 | - |
| 792 | - [[package]] |
| 793 | name = "pkg-config" |
| 794 | version = "0.3.33" |
| 795 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 796 | @@ -2196,6 +2134,62 @@ dependencies = [ |
| 797 | ] |
| 798 | |
| 799 | [[package]] |
| 800 | + name = "quinn" |
| 801 | + version = "0.11.9" |
| 802 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 803 | + checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" |
| 804 | + dependencies = [ |
| 805 | + "bytes", |
| 806 | + "cfg_aliases", |
| 807 | + "pin-project-lite", |
| 808 | + "quinn-proto", |
| 809 | + "quinn-udp", |
| 810 | + "rustc-hash", |
| 811 | + "rustls", |
| 812 | + "socket2", |
| 813 | + "thiserror 2.0.18", |
| 814 | + "tokio", |
| 815 | + "tracing", |
| 816 | + "web-time", |
| 817 | + ] |
| 818 | + |
| 819 | + [[package]] |
| 820 | + name = "quinn-proto" |
| 821 | + version = "0.11.14" |
| 822 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 823 | + checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" |
| 824 | + dependencies = [ |
| 825 | + "aws-lc-rs", |
| 826 | + "bytes", |
| 827 | + "getrandom 0.3.4", |
| 828 | + "lru-slab", |
| 829 | + "rand", |
| 830 | + "ring", |
| 831 | + "rustc-hash", |
| 832 | + "rustls", |
| 833 | + "rustls-pki-types", |
| 834 | + "slab", |
| 835 | + "thiserror 2.0.18", |
| 836 | + "tinyvec", |
| 837 | + "tracing", |
| 838 | + "web-time", |
| 839 | + ] |
| 840 | + |
| 841 | + [[package]] |
| 842 | + name = "quinn-udp" |
| 843 | + version = "0.5.14" |
| 844 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 845 | + checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" |
| 846 | + dependencies = [ |
| 847 | + "cfg_aliases", |
| 848 | + "libc", |
| 849 | + "once_cell", |
| 850 | + "socket2", |
| 851 | + "tracing", |
| 852 | + "windows-sys 0.52.0", |
| 853 | + ] |
| 854 | + |
| 855 | + [[package]] |
| 856 | name = "quipu" |
| 857 | version = "0.5.1" |
| 858 | dependencies = [ |
| 859 | @@ -2235,33 +2229,12 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" |
| 860 | |
| 861 | [[package]] |
| 862 | name = "rand" |
| 863 | - version = "0.8.6" |
| 864 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 865 | - checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" |
| 866 | - dependencies = [ |
| 867 | - "libc", |
| 868 | - "rand_chacha 0.3.1", |
| 869 | - "rand_core 0.6.4", |
| 870 | - ] |
| 871 | - |
| 872 | - [[package]] |
| 873 | - name = "rand" |
| 874 | version = "0.9.4" |
| 875 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 876 | checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" |
| 877 | dependencies = [ |
| 878 | - "rand_chacha 0.9.0", |
| 879 | - "rand_core 0.9.5", |
| 880 | - ] |
| 881 | - |
| 882 | - [[package]] |
| 883 | - name = "rand_chacha" |
| 884 | - version = "0.3.1" |
| 885 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 886 | - checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" |
| 887 | - dependencies = [ |
| 888 | - "ppv-lite86", |
| 889 | - "rand_core 0.6.4", |
| 890 | + "rand_chacha", |
| 891 | + "rand_core", |
| 892 | ] |
| 893 | |
| 894 | [[package]] |
| 895 | @@ -2271,16 +2244,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 896 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" |
| 897 | dependencies = [ |
| 898 | "ppv-lite86", |
| 899 | - "rand_core 0.9.5", |
| 900 | - ] |
| 901 | - |
| 902 | - [[package]] |
| 903 | - name = "rand_core" |
| 904 | - version = "0.6.4" |
| 905 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 906 | - checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" |
| 907 | - dependencies = [ |
| 908 | - "getrandom 0.2.17", |
| 909 | + "rand_core", |
| 910 | ] |
| 911 | |
| 912 | [[package]] |
| 913 | @@ -2380,6 +2344,7 @@ dependencies = [ |
| 914 | "log", |
| 915 | "percent-encoding", |
| 916 | "pin-project-lite", |
| 917 | + "quinn", |
| 918 | "rustls", |
| 919 | "rustls-pki-types", |
| 920 | "rustls-platform-verifier", |
| 921 | @@ -2420,23 +2385,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 922 | checksum = "323c417e1d9665a65b263ec744ba09030cfb277e9daa0b018a4ab62e57bc8189" |
| 923 | |
| 924 | [[package]] |
| 925 | - name = "rsa" |
| 926 | - version = "0.9.10" |
| 927 | + name = "rsqlite-vfs" |
| 928 | + version = "0.1.0" |
| 929 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 930 | - checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" |
| 931 | + checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" |
| 932 | dependencies = [ |
| 933 | - "const-oid", |
| 934 | - "digest", |
| 935 | - "num-bigint-dig", |
| 936 | - "num-integer", |
| 937 | - "num-traits", |
| 938 | - "pkcs1", |
| 939 | - "pkcs8", |
| 940 | - "rand_core 0.6.4", |
| 941 | - "signature", |
| 942 | - "spki", |
| 943 | - "subtle", |
| 944 | - "zeroize", |
| 945 | + "hashbrown 0.16.1", |
| 946 | + "thiserror 2.0.18", |
| 947 | ] |
| 948 | |
| 949 | [[package]] |
| 950 | @@ -2485,6 +2440,7 @@ version = "0.23.40" |
| 951 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 952 | checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" |
| 953 | dependencies = [ |
| 954 | + "aws-lc-rs", |
| 955 | "once_cell", |
| 956 | "rustls-pki-types", |
| 957 | "rustls-webpki", |
| 958 | @@ -2510,6 +2466,7 @@ version = "1.14.1" |
| 959 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 960 | checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" |
| 961 | dependencies = [ |
| 962 | + "web-time", |
| 963 | "zeroize", |
| 964 | ] |
| 965 | |
| 966 | @@ -2546,6 +2503,7 @@ version = "0.103.13" |
| 967 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 968 | checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" |
| 969 | dependencies = [ |
| 970 | + "aws-lc-rs", |
| 971 | "ring", |
| 972 | "rustls-pki-types", |
| 973 | "untrusted", |
| 974 | @@ -2718,6 +2676,15 @@ dependencies = [ |
| 975 | ] |
| 976 | |
| 977 | [[package]] |
| 978 | + name = "serde_spanned" |
| 979 | + version = "1.1.1" |
| 980 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 981 | + checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" |
| 982 | + dependencies = [ |
| 983 | + "serde_core", |
| 984 | + ] |
| 985 | + |
| 986 | + [[package]] |
| 987 | name = "serde_urlencoded" |
| 988 | version = "0.7.1" |
| 989 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 990 | @@ -2814,16 +2781,6 @@ dependencies = [ |
| 991 | ] |
| 992 | |
| 993 | [[package]] |
| 994 | - name = "signature" |
| 995 | - version = "2.2.0" |
| 996 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 997 | - checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" |
| 998 | - dependencies = [ |
| 999 | - "digest", |
| 1000 | - "rand_core 0.6.4", |
| 1001 | - ] |
| 1002 | - |
| 1003 | - [[package]] |
| 1004 | name = "simd_cesu8" |
| 1005 | version = "1.1.1" |
| 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1007 | @@ -2860,9 +2817,6 @@ name = "smallvec" |
| 1008 | version = "1.15.1" |
| 1009 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1010 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" |
| 1011 | - dependencies = [ |
| 1012 | - "serde", |
| 1013 | - ] |
| 1014 | |
| 1015 | [[package]] |
| 1016 | name = "socket2" |
| 1017 | @@ -2875,210 +2829,15 @@ dependencies = [ |
| 1018 | ] |
| 1019 | |
| 1020 | [[package]] |
| 1021 | - name = "spin" |
| 1022 | - version = "0.9.8" |
| 1023 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1024 | - checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" |
| 1025 | - dependencies = [ |
| 1026 | - "lock_api", |
| 1027 | - ] |
| 1028 | - |
| 1029 | - [[package]] |
| 1030 | - name = "spki" |
| 1031 | - version = "0.7.3" |
| 1032 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1033 | - checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" |
| 1034 | - dependencies = [ |
| 1035 | - "base64ct", |
| 1036 | - "der", |
| 1037 | - ] |
| 1038 | - |
| 1039 | - [[package]] |
| 1040 | - name = "sqlx" |
| 1041 | - version = "0.8.6" |
| 1042 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1043 | - checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" |
| 1044 | - dependencies = [ |
| 1045 | - "sqlx-core", |
| 1046 | - "sqlx-macros", |
| 1047 | - "sqlx-mysql", |
| 1048 | - "sqlx-postgres", |
| 1049 | - "sqlx-sqlite", |
| 1050 | - ] |
| 1051 | - |
| 1052 | - [[package]] |
| 1053 | - name = "sqlx-core" |
| 1054 | - version = "0.8.6" |
| 1055 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1056 | - checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" |
| 1057 | - dependencies = [ |
| 1058 | - "base64 0.22.1", |
| 1059 | - "bytes", |
| 1060 | - "crc", |
| 1061 | - "crossbeam-queue", |
| 1062 | - "either", |
| 1063 | - "event-listener", |
| 1064 | - "futures-core", |
| 1065 | - "futures-intrusive", |
| 1066 | - "futures-io", |
| 1067 | - "futures-util", |
| 1068 | - "hashbrown 0.15.5", |
| 1069 | - "hashlink", |
| 1070 | - "indexmap 2.14.0", |
| 1071 | - "log", |
| 1072 | - "memchr", |
| 1073 | - "once_cell", |
| 1074 | - "percent-encoding", |
| 1075 | - "serde", |
| 1076 | - "serde_json", |
| 1077 | - "sha2", |
| 1078 | - "smallvec", |
| 1079 | - "thiserror 2.0.18", |
| 1080 | - "tokio", |
| 1081 | - "tokio-stream", |
| 1082 | - "tracing", |
| 1083 | - "url", |
| 1084 | - ] |
| 1085 | - |
| 1086 | - [[package]] |
| 1087 | - name = "sqlx-macros" |
| 1088 | - version = "0.8.6" |
| 1089 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1090 | - checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" |
| 1091 | - dependencies = [ |
| 1092 | - "proc-macro2", |
| 1093 | - "quote", |
| 1094 | - "sqlx-core", |
| 1095 | - "sqlx-macros-core", |
| 1096 | - "syn", |
| 1097 | - ] |
| 1098 | - |
| 1099 | - [[package]] |
| 1100 | - name = "sqlx-macros-core" |
| 1101 | - version = "0.8.6" |
| 1102 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1103 | - checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" |
| 1104 | - dependencies = [ |
| 1105 | - "dotenvy", |
| 1106 | - "either", |
| 1107 | - "heck", |
| 1108 | - "hex", |
| 1109 | - "once_cell", |
| 1110 | - "proc-macro2", |
| 1111 | - "quote", |
| 1112 | - "serde", |
| 1113 | - "serde_json", |
| 1114 | - "sha2", |
| 1115 | - "sqlx-core", |
| 1116 | - "sqlx-mysql", |
| 1117 | - "sqlx-postgres", |
| 1118 | - "sqlx-sqlite", |
| 1119 | - "syn", |
| 1120 | - "tokio", |
| 1121 | - "url", |
| 1122 | - ] |
| 1123 | - |
| 1124 | - [[package]] |
| 1125 | - name = "sqlx-mysql" |
| 1126 | - version = "0.8.6" |
| 1127 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1128 | - checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" |
| 1129 | - dependencies = [ |
| 1130 | - "atoi", |
| 1131 | - "base64 0.22.1", |
| 1132 | - "bitflags", |
| 1133 | - "byteorder", |
| 1134 | - "bytes", |
| 1135 | - "crc", |
| 1136 | - "digest", |
| 1137 | - "dotenvy", |
| 1138 | - "either", |
| 1139 | - "futures-channel", |
| 1140 | - "futures-core", |
| 1141 | - "futures-io", |
| 1142 | - "futures-util", |
| 1143 | - "generic-array", |
| 1144 | - "hex", |
| 1145 | - "hkdf", |
| 1146 | - "hmac", |
| 1147 | - "itoa", |
| 1148 | - "log", |
| 1149 | - "md-5", |
| 1150 | - "memchr", |
| 1151 | - "once_cell", |
| 1152 | - "percent-encoding", |
| 1153 | - "rand 0.8.6", |
| 1154 | - "rsa", |
| 1155 | - "serde", |
| 1156 | - "sha1", |
| 1157 | - "sha2", |
| 1158 | - "smallvec", |
| 1159 | - "sqlx-core", |
| 1160 | - "stringprep", |
| 1161 | - "thiserror 2.0.18", |
| 1162 | - "tracing", |
| 1163 | - "whoami", |
| 1164 | - ] |
| 1165 | - |
| 1166 | - [[package]] |
| 1167 | - name = "sqlx-postgres" |
| 1168 | - version = "0.8.6" |
| 1169 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1170 | - checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" |
| 1171 | - dependencies = [ |
| 1172 | - "atoi", |
| 1173 | - "base64 0.22.1", |
| 1174 | - "bitflags", |
| 1175 | - "byteorder", |
| 1176 | - "crc", |
| 1177 | - "dotenvy", |
| 1178 | - "etcetera", |
| 1179 | - "futures-channel", |
| 1180 | - "futures-core", |
| 1181 | - "futures-util", |
| 1182 | - "hex", |
| 1183 | - "hkdf", |
| 1184 | - "hmac", |
| 1185 | - "home", |
| 1186 | - "itoa", |
| 1187 | - "log", |
| 1188 | - "md-5", |
| 1189 | - "memchr", |
| 1190 | - "once_cell", |
| 1191 | - "rand 0.8.6", |
| 1192 | - "serde", |
| 1193 | - "serde_json", |
| 1194 | - "sha2", |
| 1195 | - "smallvec", |
| 1196 | - "sqlx-core", |
| 1197 | - "stringprep", |
| 1198 | - "thiserror 2.0.18", |
| 1199 | - "tracing", |
| 1200 | - "whoami", |
| 1201 | - ] |
| 1202 | - |
| 1203 | - [[package]] |
| 1204 | - name = "sqlx-sqlite" |
| 1205 | - version = "0.8.6" |
| 1206 | + name = "sqlite-wasm-rs" |
| 1207 | + version = "0.5.3" |
| 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1209 | - checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" |
| 1210 | + checksum = "1b2c760607300407ddeaee518acf28c795661b7108c75421303dbefb237d3a36" |
| 1211 | dependencies = [ |
| 1212 | - "atoi", |
| 1213 | - "flume", |
| 1214 | - "futures-channel", |
| 1215 | - "futures-core", |
| 1216 | - "futures-executor", |
| 1217 | - "futures-intrusive", |
| 1218 | - "futures-util", |
| 1219 | - "libsqlite3-sys", |
| 1220 | - "log", |
| 1221 | - "percent-encoding", |
| 1222 | - "serde", |
| 1223 | - "serde_urlencoded", |
| 1224 | - "sqlx-core", |
| 1225 | - "thiserror 2.0.18", |
| 1226 | - "tracing", |
| 1227 | - "url", |
| 1228 | + "cc", |
| 1229 | + "js-sys", |
| 1230 | + "rsqlite-vfs", |
| 1231 | + "wasm-bindgen", |
| 1232 | ] |
| 1233 | |
| 1234 | [[package]] |
| 1235 | @@ -3094,17 +2853,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1236 | checksum = "2b2231b7c3057d5e4ad0156fb3dc807d900806020c5ffa3ee6ff2c8c76fb8520" |
| 1237 | |
| 1238 | [[package]] |
| 1239 | - name = "stringprep" |
| 1240 | - version = "0.1.5" |
| 1241 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1242 | - checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" |
| 1243 | - dependencies = [ |
| 1244 | - "unicode-bidi", |
| 1245 | - "unicode-normalization", |
| 1246 | - "unicode-properties", |
| 1247 | - ] |
| 1248 | - |
| 1249 | - [[package]] |
| 1250 | name = "strsim" |
| 1251 | version = "0.11.1" |
| 1252 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1253 | @@ -3285,9 +3033,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" |
| 1254 | |
| 1255 | [[package]] |
| 1256 | name = "tokio" |
| 1257 | - version = "1.52.1" |
| 1258 | + version = "1.52.2" |
| 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1260 | - checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" |
| 1261 | + checksum = "110a78583f19d5cdb2c5ccf321d1290344e71313c6c37d43520d386027d18386" |
| 1262 | dependencies = [ |
| 1263 | "bytes", |
| 1264 | "libc", |
| 1265 | @@ -3353,12 +3101,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1266 | checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" |
| 1267 | dependencies = [ |
| 1268 | "serde", |
| 1269 | - "serde_spanned", |
| 1270 | - "toml_datetime", |
| 1271 | + "serde_spanned 0.6.9", |
| 1272 | + "toml_datetime 0.6.11", |
| 1273 | "toml_edit", |
| 1274 | ] |
| 1275 | |
| 1276 | [[package]] |
| 1277 | + name = "toml" |
| 1278 | + version = "0.9.12+spec-1.1.0" |
| 1279 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1280 | + checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" |
| 1281 | + dependencies = [ |
| 1282 | + "serde_core", |
| 1283 | + "serde_spanned 1.1.1", |
| 1284 | + "toml_datetime 0.7.5+spec-1.1.0", |
| 1285 | + "toml_parser", |
| 1286 | + "winnow 0.7.15", |
| 1287 | + ] |
| 1288 | + |
| 1289 | + [[package]] |
| 1290 | name = "toml_datetime" |
| 1291 | version = "0.6.11" |
| 1292 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1293 | @@ -3368,6 +3129,15 @@ dependencies = [ |
| 1294 | ] |
| 1295 | |
| 1296 | [[package]] |
| 1297 | + name = "toml_datetime" |
| 1298 | + version = "0.7.5+spec-1.1.0" |
| 1299 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1300 | + checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" |
| 1301 | + dependencies = [ |
| 1302 | + "serde_core", |
| 1303 | + ] |
| 1304 | + |
| 1305 | + [[package]] |
| 1306 | name = "toml_edit" |
| 1307 | version = "0.22.27" |
| 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1309 | @@ -3375,10 +3145,19 @@ checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" |
| 1310 | dependencies = [ |
| 1311 | "indexmap 2.14.0", |
| 1312 | "serde", |
| 1313 | - "serde_spanned", |
| 1314 | - "toml_datetime", |
| 1315 | + "serde_spanned 0.6.9", |
| 1316 | + "toml_datetime 0.6.11", |
| 1317 | "toml_write", |
| 1318 | - "winnow", |
| 1319 | + "winnow 0.7.15", |
| 1320 | + ] |
| 1321 | + |
| 1322 | + [[package]] |
| 1323 | + name = "toml_parser" |
| 1324 | + version = "1.1.2+spec-1.1.0" |
| 1325 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1326 | + checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" |
| 1327 | + dependencies = [ |
| 1328 | + "winnow 1.0.2", |
| 1329 | ] |
| 1330 | |
| 1331 | [[package]] |
| 1332 | @@ -3553,12 +3332,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1333 | checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" |
| 1334 | |
| 1335 | [[package]] |
| 1336 | - name = "unicode-bidi" |
| 1337 | - version = "0.3.18" |
| 1338 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1339 | - checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" |
| 1340 | - |
| 1341 | - [[package]] |
| 1342 | name = "unicode-ident" |
| 1343 | version = "1.0.24" |
| 1344 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1345 | @@ -3574,12 +3347,6 @@ dependencies = [ |
| 1346 | ] |
| 1347 | |
| 1348 | [[package]] |
| 1349 | - name = "unicode-properties" |
| 1350 | - version = "0.1.4" |
| 1351 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1352 | - checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d" |
| 1353 | - |
| 1354 | - [[package]] |
| 1355 | name = "unicode-segmentation" |
| 1356 | version = "1.13.2" |
| 1357 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1358 | @@ -3702,12 +3469,6 @@ dependencies = [ |
| 1359 | ] |
| 1360 | |
| 1361 | [[package]] |
| 1362 | - name = "wasite" |
| 1363 | - version = "0.1.0" |
| 1364 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1365 | - checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" |
| 1366 | - |
| 1367 | - [[package]] |
| 1368 | name = "wasm-bindgen" |
| 1369 | version = "0.2.120" |
| 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1371 | @@ -3820,6 +3581,16 @@ dependencies = [ |
| 1372 | ] |
| 1373 | |
| 1374 | [[package]] |
| 1375 | + name = "web-time" |
| 1376 | + version = "1.1.0" |
| 1377 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1378 | + checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" |
| 1379 | + dependencies = [ |
| 1380 | + "js-sys", |
| 1381 | + "wasm-bindgen", |
| 1382 | + ] |
| 1383 | + |
| 1384 | + [[package]] |
| 1385 | name = "webfinger-rs" |
| 1386 | version = "0.0.24" |
| 1387 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1388 | @@ -3849,16 +3620,6 @@ dependencies = [ |
| 1389 | ] |
| 1390 | |
| 1391 | [[package]] |
| 1392 | - name = "whoami" |
| 1393 | - version = "1.6.1" |
| 1394 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1395 | - checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d" |
| 1396 | - dependencies = [ |
| 1397 | - "libredox", |
| 1398 | - "wasite", |
| 1399 | - ] |
| 1400 | - |
| 1401 | - [[package]] |
| 1402 | name = "winapi-util" |
| 1403 | version = "0.1.11" |
| 1404 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1405 | @@ -3928,20 +3689,11 @@ dependencies = [ |
| 1406 | |
| 1407 | [[package]] |
| 1408 | name = "windows-sys" |
| 1409 | - version = "0.48.0" |
| 1410 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1411 | - checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" |
| 1412 | - dependencies = [ |
| 1413 | - "windows-targets 0.48.5", |
| 1414 | - ] |
| 1415 | - |
| 1416 | - [[package]] |
| 1417 | - name = "windows-sys" |
| 1418 | version = "0.52.0" |
| 1419 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1420 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" |
| 1421 | dependencies = [ |
| 1422 | - "windows-targets 0.52.6", |
| 1423 | + "windows-targets", |
| 1424 | ] |
| 1425 | |
| 1426 | [[package]] |
| 1427 | @@ -3950,7 +3702,7 @@ version = "0.59.0" |
| 1428 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1429 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" |
| 1430 | dependencies = [ |
| 1431 | - "windows-targets 0.52.6", |
| 1432 | + "windows-targets", |
| 1433 | ] |
| 1434 | |
| 1435 | [[package]] |
| 1436 | @@ -3964,67 +3716,34 @@ dependencies = [ |
| 1437 | |
| 1438 | [[package]] |
| 1439 | name = "windows-targets" |
| 1440 | - version = "0.48.5" |
| 1441 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1442 | - checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" |
| 1443 | - dependencies = [ |
| 1444 | - "windows_aarch64_gnullvm 0.48.5", |
| 1445 | - "windows_aarch64_msvc 0.48.5", |
| 1446 | - "windows_i686_gnu 0.48.5", |
| 1447 | - "windows_i686_msvc 0.48.5", |
| 1448 | - "windows_x86_64_gnu 0.48.5", |
| 1449 | - "windows_x86_64_gnullvm 0.48.5", |
| 1450 | - "windows_x86_64_msvc 0.48.5", |
| 1451 | - ] |
| 1452 | - |
| 1453 | - [[package]] |
| 1454 | - name = "windows-targets" |
| 1455 | version = "0.52.6" |
| 1456 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1457 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" |
| 1458 | dependencies = [ |
| 1459 | - "windows_aarch64_gnullvm 0.52.6", |
| 1460 | - "windows_aarch64_msvc 0.52.6", |
| 1461 | - "windows_i686_gnu 0.52.6", |
| 1462 | + "windows_aarch64_gnullvm", |
| 1463 | + "windows_aarch64_msvc", |
| 1464 | + "windows_i686_gnu", |
| 1465 | "windows_i686_gnullvm", |
| 1466 | - "windows_i686_msvc 0.52.6", |
| 1467 | - "windows_x86_64_gnu 0.52.6", |
| 1468 | - "windows_x86_64_gnullvm 0.52.6", |
| 1469 | - "windows_x86_64_msvc 0.52.6", |
| 1470 | + "windows_i686_msvc", |
| 1471 | + "windows_x86_64_gnu", |
| 1472 | + "windows_x86_64_gnullvm", |
| 1473 | + "windows_x86_64_msvc", |
| 1474 | ] |
| 1475 | |
| 1476 | [[package]] |
| 1477 | name = "windows_aarch64_gnullvm" |
| 1478 | - version = "0.48.5" |
| 1479 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1480 | - checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" |
| 1481 | - |
| 1482 | - [[package]] |
| 1483 | - name = "windows_aarch64_gnullvm" |
| 1484 | version = "0.52.6" |
| 1485 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1486 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" |
| 1487 | |
| 1488 | [[package]] |
| 1489 | name = "windows_aarch64_msvc" |
| 1490 | - version = "0.48.5" |
| 1491 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1492 | - checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" |
| 1493 | - |
| 1494 | - [[package]] |
| 1495 | - name = "windows_aarch64_msvc" |
| 1496 | version = "0.52.6" |
| 1497 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1498 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" |
| 1499 | |
| 1500 | [[package]] |
| 1501 | name = "windows_i686_gnu" |
| 1502 | - version = "0.48.5" |
| 1503 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1504 | - checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" |
| 1505 | - |
| 1506 | - [[package]] |
| 1507 | - name = "windows_i686_gnu" |
| 1508 | version = "0.52.6" |
| 1509 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1510 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" |
| 1511 | @@ -4037,48 +3756,24 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" |
| 1512 | |
| 1513 | [[package]] |
| 1514 | name = "windows_i686_msvc" |
| 1515 | - version = "0.48.5" |
| 1516 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1517 | - checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" |
| 1518 | - |
| 1519 | - [[package]] |
| 1520 | - name = "windows_i686_msvc" |
| 1521 | version = "0.52.6" |
| 1522 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1523 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" |
| 1524 | |
| 1525 | [[package]] |
| 1526 | name = "windows_x86_64_gnu" |
| 1527 | - version = "0.48.5" |
| 1528 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1529 | - checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" |
| 1530 | - |
| 1531 | - [[package]] |
| 1532 | - name = "windows_x86_64_gnu" |
| 1533 | version = "0.52.6" |
| 1534 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1535 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" |
| 1536 | |
| 1537 | [[package]] |
| 1538 | name = "windows_x86_64_gnullvm" |
| 1539 | - version = "0.48.5" |
| 1540 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1541 | - checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" |
| 1542 | - |
| 1543 | - [[package]] |
| 1544 | - name = "windows_x86_64_gnullvm" |
| 1545 | version = "0.52.6" |
| 1546 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1547 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" |
| 1548 | |
| 1549 | [[package]] |
| 1550 | name = "windows_x86_64_msvc" |
| 1551 | - version = "0.48.5" |
| 1552 | - source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1553 | - checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" |
| 1554 | - |
| 1555 | - [[package]] |
| 1556 | - name = "windows_x86_64_msvc" |
| 1557 | version = "0.52.6" |
| 1558 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1559 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" |
| 1560 | @@ -4093,6 +3788,12 @@ dependencies = [ |
| 1561 | ] |
| 1562 | |
| 1563 | [[package]] |
| 1564 | + name = "winnow" |
| 1565 | + version = "1.0.2" |
| 1566 | + source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1567 | + checksum = "2ee1708bef14716a11bae175f579062d4554d95be2c6829f518df847b7b3fdd0" |
| 1568 | + |
| 1569 | + [[package]] |
| 1570 | name = "wit-bindgen" |
| 1571 | version = "0.51.0" |
| 1572 | source = "registry+https://github.com/rust-lang/crates.io-index" |
| 1573 | diff --git a/Cargo.toml b/Cargo.toml |
| 1574 | index 4ce2ac2..161fdb1 100644 |
| 1575 | --- a/Cargo.toml |
| 1576 | +++ b/Cargo.toml |
| 1577 | @@ -36,8 +36,8 @@ futures = "0.3.31" |
| 1578 | tracing-subscriber = { version = "0.3.22", features = ["env-filter"] } |
| 1579 | openssh-keys = "0.6.5" |
| 1580 | url = { version = "2.5.8", features = ["serde"]} |
| 1581 | - sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite"] } |
| 1582 | - reqwest = { version = "0.13.3", default-features = false, features = ["json", "http2", "stream"] } |
| 1583 | + |
| 1584 | + reqwest = { version = "0.13.3", default-features = false, features = ["rustls", "json", "http2", "stream"] } |
| 1585 | |
| 1586 | tokio = { version = "1.49.0", features = ["full"] } |
| 1587 | tokio-util = { version = "0.7.18", features = ["io", "compat"] } |
| 1588 | diff --git a/ayllu-build/Cargo.toml b/ayllu-build/Cargo.toml |
| 1589 | index 3c29a8b..795ba2a 100644 |
| 1590 | --- a/ayllu-build/Cargo.toml |
| 1591 | +++ b/ayllu-build/Cargo.toml |
| 1592 | @@ -15,16 +15,14 @@ ayllu_logging = {path = "../crates/logging"} |
| 1593 | ayllu_git = {path = "../crates/git"} |
| 1594 | ayllu_cmd = {path = "../crates/cmd"} |
| 1595 | |
| 1596 | - async-trait = { workspace = true } |
| 1597 | bytes = { workspace = true } |
| 1598 | tracing = { workspace = true } |
| 1599 | serde = { workspace = true } |
| 1600 | petgraph = { workspace = true } |
| 1601 | - tokio = { workspace = true } |
| 1602 | - tokio-util = { workspace = true } |
| 1603 | - futures = { workspace = true } |
| 1604 | thiserror = { workspace = true } |
| 1605 | reqwest = { workspace = true } |
| 1606 | + tokio = { workspace = true } |
| 1607 | + tokio-util = { workspace = true } |
| 1608 | |
| 1609 | serde_json = "1.0.149" |
| 1610 | tar = "0.4.45" |
| 1611 | diff --git a/ayllu-build/src/database_ext.rs b/ayllu-build/src/database_ext.rs |
| 1612 | deleted file mode 100644 |
| 1613 | index f3fdc45..0000000 |
| 1614 | --- a/ayllu-build/src/database_ext.rs |
| 1615 | +++ /dev/null |
| 1616 | @@ -1,269 +0,0 @@ |
| 1617 | - use std::collections::HashMap; |
| 1618 | - |
| 1619 | - use async_trait::async_trait; |
| 1620 | - |
| 1621 | - |
| 1622 | - |
| 1623 | - use ayllu_database::{Error, Wrapper as Database}; |
| 1624 | - |
| 1625 | - #[derive(Clone)] |
| 1626 | - // everything needed to populate the build status page |
| 1627 | - pub struct Normalized { |
| 1628 | - pub manifest: Manifest, |
| 1629 | - pub samples: Vec<Sample>, |
| 1630 | - pub workflows: Vec<Workflow>, |
| 1631 | - // TODO: for huge builds this maybe should be broken up into seperate |
| 1632 | - // calls via the API. For now everything is displayed together on a single |
| 1633 | - // huge page. |
| 1634 | - pub steps: Vec<Vec<Step>>, |
| 1635 | - } |
| 1636 | - |
| 1637 | - #[derive(Clone, Default)] |
| 1638 | - pub struct Sample { |
| 1639 | - pub id: i64, |
| 1640 | - pub load_1m: Option<i64>, |
| 1641 | - pub load_5m: Option<i64>, |
| 1642 | - pub load_15m: Option<i64>, |
| 1643 | - pub disk_total_bytes: Option<i64>, |
| 1644 | - pub disk_free_bytes: Option<i64>, |
| 1645 | - pub net_sent_bytes: Option<i64>, |
| 1646 | - pub net_received_bytes: Option<i64>, |
| 1647 | - pub net_sent_packets: Option<i64>, |
| 1648 | - pub net_received_packets: Option<i64>, |
| 1649 | - pub mem_total_bytes: Option<i64>, |
| 1650 | - pub mem_free_bytes: Option<i64>, |
| 1651 | - pub mem_available_bytes: Option<i64>, |
| 1652 | - } |
| 1653 | - |
| 1654 | - #[derive(Clone)] |
| 1655 | - pub struct Manifest { |
| 1656 | - pub id: i64, |
| 1657 | - pub repository_url: String, |
| 1658 | - pub git_hash: String, |
| 1659 | - pub created_at: i64, |
| 1660 | - pub started_at: Option<i64>, |
| 1661 | - pub duration: Option<i64>, |
| 1662 | - pub dot_content: String, |
| 1663 | - } |
| 1664 | - |
| 1665 | - // TODO |
| 1666 | - // |
| 1667 | - #[derive(Clone)] |
| 1668 | - pub struct Workflow { |
| 1669 | - pub id: i64, |
| 1670 | - pub name: String, |
| 1671 | - pub started_at: Option<i64>, |
| 1672 | - pub duration: Option<i64>, |
| 1673 | - } |
| 1674 | - |
| 1675 | - #[derive(Clone)] |
| 1676 | - pub struct Step { |
| 1677 | - pub id: i64, |
| 1678 | - pub name: String, |
| 1679 | - pub input: String, |
| 1680 | - pub stdout: Option<String>, |
| 1681 | - pub stderr: Option<String>, |
| 1682 | - pub started_at: Option<i64>, |
| 1683 | - pub duration: Option<i64>, |
| 1684 | - pub exit_code: Option<i64>, |
| 1685 | - } |
| 1686 | - |
| 1687 | - #[async_trait] |
| 1688 | - pub trait BuildExt { |
| 1689 | - // manifests |
| 1690 | - async fn create_manifest(&self, repository_url: &str, git_hash: &str) -> Result<i64, Error>; |
| 1691 | - async fn update_manifest_start(&self, manifest_id: i64) -> Result<(), Error>; |
| 1692 | - async fn update_manifest_finish(&self, manifest_id: i64, duration: i64) -> Result<(), Error>; |
| 1693 | - async fn list_manifest(&self, limit: i64, offset: i64) -> Result<Vec<Manifest>, Error>; |
| 1694 | - async fn read_manifest(&self, manifest_id: i64) -> Result<Normalized, Error>; |
| 1695 | - |
| 1696 | - // workflows |
| 1697 | - async fn create_workflow(&self, manifest_id: i64, name: &str) -> Result<i64, Error>; |
| 1698 | - async fn update_workflow_start(&self, workflow_id: i64) -> Result<(), Error>; |
| 1699 | - async fn update_workflow_finish(&self, workflow_id: i64, duration: i64) -> Result<(), Error>; |
| 1700 | - // steps |
| 1701 | - async fn create_step( |
| 1702 | - &self, |
| 1703 | - job_id: i64, |
| 1704 | - name: &str, |
| 1705 | - input: &str, |
| 1706 | - shell: &str, |
| 1707 | - environment: HashMap<String, String>, |
| 1708 | - ) -> Result<i64, Error>; |
| 1709 | - async fn update_step_start(&self, step_id: i64) -> Result<(), Error>; |
| 1710 | - async fn update_step_finish( |
| 1711 | - &self, |
| 1712 | - step_id: i64, |
| 1713 | - duration: i64, |
| 1714 | - stdout: &str, |
| 1715 | - stderr: &str, |
| 1716 | - exit_code: i8, |
| 1717 | - ) -> Result<(), Error>; |
| 1718 | - |
| 1719 | - // misc |
| 1720 | - async fn create_sample(&self, manifest_id: i64, sample: Sample) -> Result<i64, Error>; |
| 1721 | - async fn create_dag(&self, manifest_id: i64, dot_content: &str) -> Result<i64, Error>; |
| 1722 | - } |
| 1723 | - |
| 1724 | - #[async_trait] |
| 1725 | - impl BuildExt for Database { |
| 1726 | - // manifests |
| 1727 | - async fn create_manifest(&self, repository_url: &str, git_hash: &str) -> Result<i64, Error> { |
| 1728 | - let ret = sqlx::query_file!("queries/manifests_create.sql", repository_url, git_hash) |
| 1729 | - .fetch_one(&self.pool) |
| 1730 | - .await?; |
| 1731 | - Ok(ret.id) |
| 1732 | - } |
| 1733 | - |
| 1734 | - async fn update_manifest_start(&self, manifest_id: i64) -> Result<(), Error> { |
| 1735 | - sqlx::query_file!("queries/manifests_update_start.sql", manifest_id,) |
| 1736 | - .execute(&self.pool) |
| 1737 | - .await?; |
| 1738 | - Ok(()) |
| 1739 | - } |
| 1740 | - |
| 1741 | - async fn update_manifest_finish(&self, manifest_id: i64, duration: i64) -> Result<(), Error> { |
| 1742 | - sqlx::query_file!("queries/manifests_update_finish.sql", duration, manifest_id) |
| 1743 | - .execute(&self.pool) |
| 1744 | - .await?; |
| 1745 | - Ok(()) |
| 1746 | - } |
| 1747 | - |
| 1748 | - async fn list_manifest(&self, _limit: i64, _offset: i64) -> Result<Vec<Manifest>, Error> { |
| 1749 | - todo!() |
| 1750 | - } |
| 1751 | - |
| 1752 | - // return a fully normalized manifest with everything needed to return to |
| 1753 | - // the RPC client |
| 1754 | - async fn read_manifest(&self, manifest_id: i64) -> Result<Normalized, Error> { |
| 1755 | - // TODO: evaluation order needs to be preserved |
| 1756 | - let manifest = sqlx::query_file_as!(Manifest, "queries/manifests_read.sql", manifest_id) |
| 1757 | - .fetch_one(&self.pool) |
| 1758 | - .await?; |
| 1759 | - let samples: Vec<Sample> = |
| 1760 | - sqlx::query_file_as!(Sample, "queries/samples_read.sql", manifest_id) |
| 1761 | - .fetch_all(&self.pool) |
| 1762 | - .await?; |
| 1763 | - let workflows = sqlx::query_file_as!(Workflow, "queries/workflows_list.sql", manifest_id) |
| 1764 | - .fetch_all(&self.pool) |
| 1765 | - .await?; |
| 1766 | - let mut all_steps: Vec<Vec<Step>> = Vec::new(); |
| 1767 | - for workflow in workflows.iter() { |
| 1768 | - let workflow_id = workflow.id; |
| 1769 | - let steps = sqlx::query_file_as!(Step, "queries/steps_list.sql", workflow_id) |
| 1770 | - .fetch_all(&self.pool) |
| 1771 | - .await?; |
| 1772 | - all_steps.push(steps); |
| 1773 | - } |
| 1774 | - Ok(Normalized { |
| 1775 | - manifest, |
| 1776 | - samples, |
| 1777 | - workflows, |
| 1778 | - steps: all_steps, |
| 1779 | - }) |
| 1780 | - } |
| 1781 | - |
| 1782 | - // workflows |
| 1783 | - |
| 1784 | - async fn create_workflow(&self, manifest_id: i64, name: &str) -> Result<i64, Error> { |
| 1785 | - let ret = sqlx::query_file!("queries/workflows_create.sql", manifest_id, name) |
| 1786 | - .fetch_one(&self.pool) |
| 1787 | - .await?; |
| 1788 | - Ok(ret.id) |
| 1789 | - } |
| 1790 | - |
| 1791 | - async fn update_workflow_start(&self, workflow_id: i64) -> Result<(), Error> { |
| 1792 | - sqlx::query_file!("queries/workflows_update_start.sql", workflow_id,) |
| 1793 | - .execute(&self.pool) |
| 1794 | - .await?; |
| 1795 | - Ok(()) |
| 1796 | - } |
| 1797 | - |
| 1798 | - async fn update_workflow_finish(&self, workflow_id: i64, duration: i64) -> Result<(), Error> { |
| 1799 | - sqlx::query_file!("queries/workflows_update_finish.sql", duration, workflow_id) |
| 1800 | - .execute(&self.pool) |
| 1801 | - .await?; |
| 1802 | - Ok(()) |
| 1803 | - } |
| 1804 | - |
| 1805 | - // steps |
| 1806 | - |
| 1807 | - async fn create_step( |
| 1808 | - &self, |
| 1809 | - workflow_id: i64, |
| 1810 | - name: &str, |
| 1811 | - input: &str, |
| 1812 | - shell: &str, |
| 1813 | - environment: HashMap<String, String>, |
| 1814 | - ) -> Result<i64, Error> { |
| 1815 | - let environment_json = serde_json::ser::to_string(&environment).unwrap(); |
| 1816 | - let ret = sqlx::query_file!( |
| 1817 | - "queries/steps_create.sql", |
| 1818 | - workflow_id, |
| 1819 | - name, |
| 1820 | - input, |
| 1821 | - shell, |
| 1822 | - environment_json |
| 1823 | - ) |
| 1824 | - .fetch_one(&self.pool) |
| 1825 | - .await?; |
| 1826 | - Ok(ret.id) |
| 1827 | - } |
| 1828 | - |
| 1829 | - async fn update_step_start(&self, step_id: i64) -> Result<(), Error> { |
| 1830 | - sqlx::query_file!("queries/steps_update_start.sql", step_id) |
| 1831 | - .execute(&self.pool) |
| 1832 | - .await?; |
| 1833 | - Ok(()) |
| 1834 | - } |
| 1835 | - |
| 1836 | - async fn update_step_finish( |
| 1837 | - &self, |
| 1838 | - step_id: i64, |
| 1839 | - duration: i64, |
| 1840 | - stdout: &str, |
| 1841 | - stderr: &str, |
| 1842 | - exit_code: i8, |
| 1843 | - ) -> Result<(), Error> { |
| 1844 | - sqlx::query_file!( |
| 1845 | - "queries/steps_update_finish.sql", |
| 1846 | - duration, |
| 1847 | - stdout, |
| 1848 | - stderr, |
| 1849 | - exit_code, |
| 1850 | - step_id, |
| 1851 | - ) |
| 1852 | - .execute(&self.pool) |
| 1853 | - .await?; |
| 1854 | - Ok(()) |
| 1855 | - } |
| 1856 | - |
| 1857 | - async fn create_sample(&self, manifest_id: i64, sample: Sample) -> Result<i64, Error> { |
| 1858 | - let ret = sqlx::query_file!( |
| 1859 | - "queries/samples_create.sql", |
| 1860 | - manifest_id, |
| 1861 | - sample.load_1m, |
| 1862 | - sample.load_5m, |
| 1863 | - sample.load_15m, |
| 1864 | - sample.disk_total_bytes, |
| 1865 | - sample.disk_free_bytes, |
| 1866 | - sample.net_sent_bytes, |
| 1867 | - sample.net_received_bytes, |
| 1868 | - sample.net_sent_packets, |
| 1869 | - sample.net_received_packets, |
| 1870 | - sample.mem_total_bytes, |
| 1871 | - sample.mem_free_bytes, |
| 1872 | - sample.mem_available_bytes, |
| 1873 | - ) |
| 1874 | - .fetch_one(&self.pool) |
| 1875 | - .await?; |
| 1876 | - Ok(ret.id) |
| 1877 | - } |
| 1878 | - |
| 1879 | - async fn create_dag(&self, manifest_id: i64, dot_content: &str) -> Result<i64, Error> { |
| 1880 | - let ret = sqlx::query_file!("queries/dags_create.sql", manifest_id, dot_content,) |
| 1881 | - .fetch_one(&self.pool) |
| 1882 | - .await?; |
| 1883 | - Ok(ret.id) |
| 1884 | - } |
| 1885 | - } |
| 1886 | diff --git a/ayllu-build/src/error.rs b/ayllu-build/src/error.rs |
| 1887 | index bc9a3d1..9296349 100644 |
| 1888 | --- a/ayllu-build/src/error.rs |
| 1889 | +++ b/ayllu-build/src/error.rs |
| 1890 | @@ -25,10 +25,11 @@ pub enum Error { |
| 1891 | name: String, |
| 1892 | }, |
| 1893 | DuplicateWorkflows, |
| 1894 | + Database(ayllu_database::Error), |
| 1895 | // general io error during execution |
| 1896 | Io(std::io::Error), |
| 1897 | - Db(ayllu_database::Error), |
| 1898 | - Libpod(crate::libpod::Error), |
| 1899 | + Reqwest(reqwest::Error), |
| 1900 | + Libpod(crate::libpod::ErrorMessage), |
| 1901 | } |
| 1902 | |
| 1903 | impl std::fmt::Display for Error { |
| 1904 | @@ -45,7 +46,6 @@ impl std::fmt::Display for Error { |
| 1905 | Error::DuplicateStepNames { name } => write!(f, "Duplicate step detected: {name}"), |
| 1906 | Error::DuplicateWorkflows => write!(f, "Duplicate Workflows!"), |
| 1907 | Error::Io(error) => write!(f, "Io Error: {error}"), |
| 1908 | - Error::Db(error) => write!(f, "SQL Error: {error}"), |
| 1909 | Error::CannotReadManifestFromRepository { path, repo_err } => write!( |
| 1910 | f, |
| 1911 | "Cannot read manifest from repository {path:?}: {repo_err}" |
| 1912 | @@ -53,9 +53,13 @@ impl std::fmt::Display for Error { |
| 1913 | Error::RepositoryDoesNotContainManifest { path } => { |
| 1914 | write!(f, "Repository {path:?} does not contain a manifest") |
| 1915 | } |
| 1916 | - Error::Libpod(err) => { |
| 1917 | - write!(f, "Libpod failure: {err:?}") |
| 1918 | - } |
| 1919 | + Error::Database(error) => write!(f, "Database error: {error}"), |
| 1920 | + Error::Reqwest(error) => write!(f, "Error making libpod request: {error:?}"), |
| 1921 | + Error::Libpod(error_message) => write!( |
| 1922 | + f, |
| 1923 | + "Libpod API Error: {}: {} {}", |
| 1924 | + error_message.cause, error_message.message, error_message.response |
| 1925 | + ), |
| 1926 | } |
| 1927 | } |
| 1928 | } |
| 1929 | @@ -64,7 +68,7 @@ impl std::error::Error for Error {} |
| 1930 | |
| 1931 | impl From<ayllu_database::Error> for Error { |
| 1932 | fn from(value: ayllu_database::Error) -> Self { |
| 1933 | - Error::Db(value) |
| 1934 | + Self::Database(value) |
| 1935 | } |
| 1936 | } |
| 1937 | |
| 1938 | @@ -73,3 +77,9 @@ impl From<std::io::Error> for Error { |
| 1939 | Error::Io(value) |
| 1940 | } |
| 1941 | } |
| 1942 | + |
| 1943 | + impl From<reqwest::Error> for Error { |
| 1944 | + fn from(value: reqwest::Error) -> Self { |
| 1945 | + Self::Reqwest(value) |
| 1946 | + } |
| 1947 | + } |
| 1948 | diff --git a/ayllu-build/src/evaluate.rs b/ayllu-build/src/evaluate.rs |
| 1949 | index a4f3e1e..6eeed7b 100644 |
| 1950 | --- a/ayllu-build/src/evaluate.rs |
| 1951 | +++ b/ayllu-build/src/evaluate.rs |
| 1952 | @@ -2,6 +2,7 @@ use std::fs::metadata; |
| 1953 | use std::path::PathBuf; |
| 1954 | use std::{collections::HashMap, path::Path}; |
| 1955 | |
| 1956 | + use ayllu_database::build::workflows::CreateWorkflowArgs; |
| 1957 | use petgraph::{ |
| 1958 | algo::is_cyclic_directed, |
| 1959 | dot::Dot, |
| 1960 | @@ -9,22 +10,16 @@ use petgraph::{ |
| 1961 | visit::Topo, |
| 1962 | }; |
| 1963 | |
| 1964 | - use crate::executor::InitializeArgs; |
| 1965 | + use crate::libpod_executor::InitializeArgs; |
| 1966 | use crate::package::Package; |
| 1967 | use crate::{ |
| 1968 | DEFAULT_BUILD_FILE, |
| 1969 | models::{Manifest, Step}, |
| 1970 | }; |
| 1971 | - use crate::{ |
| 1972 | - error::Error, |
| 1973 | - executor::{Context, Executor}, |
| 1974 | - }; |
| 1975 | - use ayllu_database::{ |
| 1976 | - Tx, Wrapper as Database, |
| 1977 | - build::{BuildExt, BuildTx}, |
| 1978 | - }; |
| 1979 | + use crate::{error::Error, libpod_executor::Context}; |
| 1980 | |
| 1981 | use ayllu_api::build::Unit; |
| 1982 | + use ayllu_database::Wrapper as Database; |
| 1983 | |
| 1984 | pub type BuildGraph = Graph<Unit, u8>; |
| 1985 | |
| 1986 | @@ -121,13 +116,6 @@ impl Runtime { |
| 1987 | } |
| 1988 | } |
| 1989 | |
| 1990 | - fn source_dir(&self) -> &Path { |
| 1991 | - match self.source { |
| 1992 | - Source::Path(ref path_buf) => path_buf.as_path(), |
| 1993 | - _ => todo!(), |
| 1994 | - } |
| 1995 | - } |
| 1996 | - |
| 1997 | // FIXME: Fundementally broken, assumes everything is a git repo with fragile paths |
| 1998 | fn git_information(&self) -> Result<(String, String, String), ayllu_git::Error> { |
| 1999 | let manifest_path = match &self.source { |
| 2000 | @@ -147,110 +135,107 @@ impl Runtime { |
| 2001 | } |
| 2002 | |
| 2003 | /// Allocate the manifest in the database along with it's DAG |
| 2004 | - async fn allocate(&self, tx: &mut Tx) -> Result<(i64, BuildGraph), Error> { |
| 2005 | + fn allocate(&mut self) -> Result<(i32, BuildGraph), Error> { |
| 2006 | let manifest = self.setup()?; |
| 2007 | manifest.validate()?; |
| 2008 | let (collection, name, git_hash) = self.git_information().unwrap(); |
| 2009 | - let manifest_id = tx.create_manifest(&collection, &name, &git_hash).await?; |
| 2010 | - let mut workflows_by_name: HashMap<String, NodeIndex> = HashMap::new(); |
| 2011 | - let mut steps_by_name: HashMap<String, HashMap<String, NodeIndex>> = HashMap::new(); |
| 2012 | - let mut graph: BuildGraph = Graph::new(); |
| 2013 | - // Allocate components into the database |
| 2014 | - for workflow in manifest.workflows.iter() { |
| 2015 | - if workflow.steps.is_empty() { |
| 2016 | - return Err(Error::EmptyWorkflow { |
| 2017 | - name: workflow.name.clone(), |
| 2018 | - }); |
| 2019 | - } |
| 2020 | - let workflow_id = tx |
| 2021 | - .create_workflow(manifest_id, &workflow.name, &workflow.image) |
| 2022 | - .await?; |
| 2023 | - workflows_by_name.insert( |
| 2024 | - workflow.name.clone(), |
| 2025 | - graph.add_node(Unit::Workflow(workflow_id)), |
| 2026 | - ); |
| 2027 | - let mut by_name: HashMap<String, NodeIndex> = HashMap::new(); |
| 2028 | - for step in workflow.steps.iter() { |
| 2029 | - let step_id = tx |
| 2030 | - .create_step( |
| 2031 | - workflow_id, |
| 2032 | - &step.name, |
| 2033 | - &step.input, |
| 2034 | - &step.shell, |
| 2035 | - step.environment.clone(), |
| 2036 | - ) |
| 2037 | - .await?; |
| 2038 | - by_name.insert(step.name.clone(), graph.add_node(Unit::Step(step_id))); |
| 2039 | + self.db.with(move |mut tx| { |
| 2040 | + let manifest_id = tx.manifest_create(&collection, &name, &git_hash)?; |
| 2041 | + |
| 2042 | + let mut workflows_by_name: HashMap<String, NodeIndex> = HashMap::new(); |
| 2043 | + let mut steps_by_name: HashMap<String, HashMap<String, NodeIndex>> = HashMap::new(); |
| 2044 | + let mut graph: BuildGraph = Graph::new(); |
| 2045 | + // Allocate components into the database |
| 2046 | + for workflow in manifest.workflows.iter() { |
| 2047 | + if workflow.steps.is_empty() { |
| 2048 | + return Err(Error::EmptyWorkflow { |
| 2049 | + name: workflow.name.clone(), |
| 2050 | + }); |
| 2051 | + } |
| 2052 | + let workflow_id = tx.workflow_create(&CreateWorkflowArgs { |
| 2053 | + name: &workflow.name, |
| 2054 | + image: &workflow.image, |
| 2055 | + manifest_id, |
| 2056 | + })?; |
| 2057 | + workflows_by_name.insert( |
| 2058 | + workflow.name.clone(), |
| 2059 | + graph.add_node(Unit::Workflow(workflow_id)), |
| 2060 | + ); |
| 2061 | + let mut by_name: HashMap<String, NodeIndex> = HashMap::new(); |
| 2062 | + for step in workflow.steps.iter() { |
| 2063 | + let step_id = |
| 2064 | + tx.step_create(&ayllu_database::build::steps::CreateStepArgs { |
| 2065 | + name: &step.name, |
| 2066 | + shell: &step.shell, |
| 2067 | + input: &step.input, |
| 2068 | + workflow_id, |
| 2069 | + })?; |
| 2070 | + by_name.insert(step.name.clone(), graph.add_node(Unit::Step(step_id))); |
| 2071 | + } |
| 2072 | + steps_by_name.insert(workflow.name.clone(), by_name); |
| 2073 | } |
| 2074 | - steps_by_name.insert(workflow.name.clone(), by_name); |
| 2075 | - } |
| 2076 | - // set edges for steps from each workflow |
| 2077 | - for workflow in manifest.workflows.iter() { |
| 2078 | - let workflow_steps = steps_by_name.get(&workflow.name).unwrap(); |
| 2079 | - for step in workflow.steps.iter() { |
| 2080 | - let step_index = workflow_steps.get(&step.name).unwrap(); |
| 2081 | - for dependency in step.depends_on.iter() { |
| 2082 | - let dependency_index = workflow_steps.get(dependency).unwrap(); |
| 2083 | - graph.add_edge(*dependency_index, *step_index, 0); |
| 2084 | + // set edges for steps from each workflow |
| 2085 | + for workflow in manifest.workflows.iter() { |
| 2086 | + let workflow_steps = steps_by_name.get(&workflow.name).unwrap(); |
| 2087 | + for step in workflow.steps.iter() { |
| 2088 | + let step_index = workflow_steps.get(&step.name).unwrap(); |
| 2089 | + for dependency in step.depends_on.iter() { |
| 2090 | + let dependency_index = workflow_steps.get(dependency).unwrap(); |
| 2091 | + graph.add_edge(*dependency_index, *step_index, 0); |
| 2092 | + } |
| 2093 | } |
| 2094 | } |
| 2095 | - } |
| 2096 | |
| 2097 | - for workflow in manifest.workflows.iter() { |
| 2098 | - let workflow_index = workflows_by_name.get(&workflow.name).unwrap(); |
| 2099 | - let steps_with_no_dependencies: Vec<&Step> = workflow |
| 2100 | - .steps |
| 2101 | - .iter() |
| 2102 | - .filter(|step| step.depends_on.is_empty()) |
| 2103 | - .collect(); |
| 2104 | - for step in steps_with_no_dependencies.iter() { |
| 2105 | - let step_index = steps_by_name |
| 2106 | - .get(&workflow.name) |
| 2107 | - .unwrap() |
| 2108 | - .get(&step.name) |
| 2109 | - .unwrap(); |
| 2110 | - graph.add_edge(*workflow_index, *step_index, 0); |
| 2111 | + for workflow in manifest.workflows.iter() { |
| 2112 | + let workflow_index = workflows_by_name.get(&workflow.name).unwrap(); |
| 2113 | + let steps_with_no_dependencies: Vec<&Step> = workflow |
| 2114 | + .steps |
| 2115 | + .iter() |
| 2116 | + .filter(|step| step.depends_on.is_empty()) |
| 2117 | + .collect(); |
| 2118 | + for step in steps_with_no_dependencies.iter() { |
| 2119 | + let step_index = steps_by_name |
| 2120 | + .get(&workflow.name) |
| 2121 | + .unwrap() |
| 2122 | + .get(&step.name) |
| 2123 | + .unwrap(); |
| 2124 | + graph.add_edge(*workflow_index, *step_index, 0); |
| 2125 | + } |
| 2126 | } |
| 2127 | - } |
| 2128 | |
| 2129 | - for workflow in manifest.workflows.iter() { |
| 2130 | - let workflow_index = workflows_by_name.get(&workflow.name).unwrap(); |
| 2131 | - for dependency in workflow.depends_on.iter() { |
| 2132 | - let dependency_index = workflows_by_name.get(&dependency.clone()).unwrap(); |
| 2133 | - graph.add_edge(*dependency_index, *workflow_index, 1); |
| 2134 | + for workflow in manifest.workflows.iter() { |
| 2135 | + let workflow_index = workflows_by_name.get(&workflow.name).unwrap(); |
| 2136 | + for dependency in workflow.depends_on.iter() { |
| 2137 | + let dependency_index = workflows_by_name.get(&dependency.clone()).unwrap(); |
| 2138 | + graph.add_edge(*dependency_index, *workflow_index, 1); |
| 2139 | + } |
| 2140 | } |
| 2141 | - } |
| 2142 | - |
| 2143 | - if is_cyclic_directed(&graph) { |
| 2144 | - return Err(Error::CycleDetected); |
| 2145 | - } |
| 2146 | |
| 2147 | - let dag_json = serde_json::ser::to_string(&graph).unwrap(); |
| 2148 | + if is_cyclic_directed(&graph) { |
| 2149 | + return Err(Error::CycleDetected); |
| 2150 | + } |
| 2151 | |
| 2152 | - tx.create_dag(manifest_id, &dag_json).await?; |
| 2153 | + let dag_json = serde_json::ser::to_string(&graph).unwrap(); |
| 2154 | + tx.manifest_set_dag_content(manifest_id, &dag_json)?; |
| 2155 | |
| 2156 | - Ok((manifest_id, graph)) |
| 2157 | + Ok((manifest_id, graph)) |
| 2158 | + }) |
| 2159 | } |
| 2160 | |
| 2161 | /// Allocate a job graph and then execute it sequentially |
| 2162 | - pub async fn evaluate(&self, executor: &impl Executor) -> Result<i64, Error> { |
| 2163 | + pub async fn evaluate( |
| 2164 | + &mut self, |
| 2165 | + executor: &crate::libpod_executor::Libpod, |
| 2166 | + ) -> Result<i32, Error> { |
| 2167 | let this_binary = std::env::current_exe().unwrap(); |
| 2168 | - let mut tx = self.db.begin().await?; |
| 2169 | - let (manifest_id, graph) = match self.allocate(&mut tx).await { |
| 2170 | - Ok(db_op) => { |
| 2171 | - tx.commit().await?; |
| 2172 | - db_op |
| 2173 | - } |
| 2174 | - Err(e) => { |
| 2175 | - tracing::error!("Failed to allocate graph: {e:?}"); |
| 2176 | - tx.rollback().await?; |
| 2177 | - // FIXME rollback but how |
| 2178 | - return Err(e); |
| 2179 | - } |
| 2180 | + let (manifest_id, graph) = self.allocate()?; |
| 2181 | + let source_dir = match &self.source { |
| 2182 | + Source::Path(path_buf) => path_buf.as_path().parent().unwrap(), |
| 2183 | + _ => todo!(), |
| 2184 | }; |
| 2185 | let package = Package { |
| 2186 | temp_dir: &self.work_dir.join(format!("ayllu-{manifest_id}")), |
| 2187 | - source_dir: self.source_dir().parent().unwrap(), |
| 2188 | + source_dir, |
| 2189 | }; |
| 2190 | let payload = package.build()?; |
| 2191 | let dot_string = Dot::new(&graph).to_string(); |
| 2192 | @@ -260,25 +245,26 @@ impl Runtime { |
| 2193 | graph.node_count(), |
| 2194 | dot_string |
| 2195 | ); |
| 2196 | - self.db.update_manifest_start(manifest_id).await?; |
| 2197 | + let mut conn = self.db.call(); |
| 2198 | + conn.manifest_start(manifest_id)?; |
| 2199 | // TODO: Currently no parallelism is supported, need to implement the |
| 2200 | // options in the manifest and then break steps into asynchronous chunks |
| 2201 | // that can be run in parallel where appropriate. |
| 2202 | let mut topo = Topo::new(&graph); |
| 2203 | - let mut current_workflow: Option<i64> = None; |
| 2204 | + let mut current_workflow: Option<i32> = None; |
| 2205 | while let Some(nx) = topo.next(&graph) { |
| 2206 | let unit = &graph[nx]; |
| 2207 | match unit { |
| 2208 | Unit::Workflow(next_workflow_id) => { |
| 2209 | - let next_workflow = self.db.read_workflow(*next_workflow_id).await?; |
| 2210 | + let next_workflow = conn.workflow_read(*next_workflow_id)?; |
| 2211 | tracing::info!("starting workflow {}", next_workflow.name); |
| 2212 | match current_workflow.as_ref() { |
| 2213 | Some(current_workflow_id) => { |
| 2214 | - self.db.update_workflow_finish(*current_workflow_id).await?; |
| 2215 | - executor.shutdown(manifest_id, *current_workflow_id).await?; |
| 2216 | + conn.workflow_finish(*current_workflow_id)?; |
| 2217 | + executor.shutdown(manifest_id, *current_workflow_id)?; |
| 2218 | } |
| 2219 | None => { |
| 2220 | - self.db.update_workflow_start(next_workflow.id).await?; |
| 2221 | + conn.workflow_start(*next_workflow_id)?; |
| 2222 | } |
| 2223 | }; |
| 2224 | current_workflow = Some(*next_workflow_id); |
| 2225 | @@ -289,16 +275,16 @@ impl Runtime { |
| 2226 | build_dir: self.work_dir.as_path(), |
| 2227 | image: &next_workflow.image, |
| 2228 | init_args: &["/bin/sleep", "inf"], |
| 2229 | - source_dir: self.source_dir().parent().unwrap(), |
| 2230 | + source_dir, |
| 2231 | absolute_ayllu_build_binary: &this_binary, |
| 2232 | src_package: &payload, |
| 2233 | }) |
| 2234 | .await?; |
| 2235 | } |
| 2236 | Unit::Step(next_step_id) => { |
| 2237 | - let next_step = self.db.read_step(*next_step_id).await?; |
| 2238 | + let next_step = conn.step_read(*next_step_id)?; |
| 2239 | tracing::info!("starting step: {}", next_step.name); |
| 2240 | - self.db.update_step_start(next_step.id).await?; |
| 2241 | + conn.step_start(next_step.id)?; |
| 2242 | // TODO: more context |
| 2243 | let ctx = Context { |
| 2244 | manifest_id, |
| 2245 | @@ -307,20 +293,18 @@ impl Runtime { |
| 2246 | repo_url: self.source.url(), |
| 2247 | ..Default::default() |
| 2248 | }; |
| 2249 | - let (lines, exit_code) = executor.execute(&next_step, &ctx).await?; |
| 2250 | - // let (step_id, duration) = state.current_step().unwrap(); |
| 2251 | - self.db |
| 2252 | - .update_step_finish(*next_step_id, lines.as_slice(), exit_code as i8) |
| 2253 | - .await?; |
| 2254 | + let exit_code = executor.execute(&next_step, &ctx, &mut conn).await?; |
| 2255 | + conn.step_finish(*next_step_id, exit_code)?; |
| 2256 | } |
| 2257 | } |
| 2258 | } |
| 2259 | // clean up last workflow |
| 2260 | if let Some(id) = current_workflow { |
| 2261 | - self.db.update_workflow_finish(id).await?; |
| 2262 | + conn.workflow_finish(id)?; |
| 2263 | } |
| 2264 | |
| 2265 | - self.db.update_manifest_finish(manifest_id).await?; |
| 2266 | + // TODO also set results here to speed up UI summary |
| 2267 | + // self.db.update_manifest_finish(manifest_id).await?; |
| 2268 | |
| 2269 | Ok(manifest_id) |
| 2270 | } |
| 2271 | diff --git a/ayllu-build/src/executor.rs b/ayllu-build/src/executor.rs |
| 2272 | deleted file mode 100644 |
| 2273 | index 3880f9b..0000000 |
| 2274 | --- a/ayllu-build/src/executor.rs |
| 2275 | +++ /dev/null |
| 2276 | @@ -1,66 +0,0 @@ |
| 2277 | - use std::{collections::HashMap, path::Path}; |
| 2278 | - |
| 2279 | - use ayllu_database::build::{LogLine, Step}; |
| 2280 | - use serde::Deserialize; |
| 2281 | - |
| 2282 | - use crate::error::Error; |
| 2283 | - |
| 2284 | - // context exposed to the runtime of individual steps, also used in other |
| 2285 | - // parts of the build process. |
| 2286 | - #[derive(Deserialize, Debug, Clone, Default)] |
| 2287 | - pub struct Context { |
| 2288 | - pub manifest_id: i64, |
| 2289 | - pub workflow_id: i64, |
| 2290 | - pub step_id: i64, |
| 2291 | - pub git_hash: String, |
| 2292 | - pub repo_url: String, |
| 2293 | - pub environment: HashMap<String, Option<String>>, |
| 2294 | - } |
| 2295 | - |
| 2296 | - pub struct InitializeArgs<'a> { |
| 2297 | - pub manifest_id: i64, |
| 2298 | - pub workflow_id: i64, |
| 2299 | - pub build_dir: &'a Path, |
| 2300 | - pub image: &'a str, |
| 2301 | - pub init_args: &'a [&'a str], |
| 2302 | - pub source_dir: &'a Path, |
| 2303 | - pub absolute_ayllu_build_binary: &'a Path, |
| 2304 | - // path to source tree and other things needed in the ct runtime |
| 2305 | - pub src_package: &'a Path, |
| 2306 | - } |
| 2307 | - |
| 2308 | - // An executor runs the step in a process container of some kind. Currently |
| 2309 | - // the only executor that exists is the Local exector. |
| 2310 | - pub trait Executor { |
| 2311 | - async fn initialize(&self, args: &InitializeArgs) -> Result<(), Error>; |
| 2312 | - async fn execute(&self, step: &Step, context: &Context) -> Result<(Vec<LogLine>, i32), Error>; |
| 2313 | - async fn shutdown(&self, manifest_id: i64, workflow_id: i64) -> Result<(), Error>; |
| 2314 | - } |
| 2315 | - |
| 2316 | - #[cfg(test)] |
| 2317 | - mod tests { |
| 2318 | - |
| 2319 | - // use super::*; |
| 2320 | - |
| 2321 | - // #[tokio::test] |
| 2322 | - // async fn test_local_executor() { |
| 2323 | - // let executor = Local { |
| 2324 | - // temp_dir: Path::new("logs").to_path_buf(), |
| 2325 | - // tee_output: true, |
| 2326 | - // }; |
| 2327 | - // let result = executor |
| 2328 | - // .execute( |
| 2329 | - // &Step { |
| 2330 | - // name: String::from("test"), |
| 2331 | - // shell: String::from("/bin/sh"), |
| 2332 | - // input: String::from("echo -n hello"), |
| 2333 | - // depends_on: Vec::new(), |
| 2334 | - // environment: HashMap::new(), |
| 2335 | - // }, |
| 2336 | - // Context::default(), |
| 2337 | - // ) |
| 2338 | - // .expect("failed to run command"); |
| 2339 | - // assert!(result.2.success()); |
| 2340 | - // assert!(result.0 == "hello"); |
| 2341 | - // } |
| 2342 | - } |
| 2343 | diff --git a/ayllu-build/src/executor_libpod.rs b/ayllu-build/src/executor_libpod.rs |
| 2344 | deleted file mode 100644 |
| 2345 | index 344fcc7..0000000 |
| 2346 | --- a/ayllu-build/src/executor_libpod.rs |
| 2347 | +++ /dev/null |
| 2348 | @@ -1,150 +0,0 @@ |
| 2349 | - use std::{ |
| 2350 | - path::Path, |
| 2351 | - time::{Duration, Instant}, |
| 2352 | - }; |
| 2353 | - |
| 2354 | - use ayllu_database::build::LogLine; |
| 2355 | - use tokio::sync::mpsc; |
| 2356 | - |
| 2357 | - use crate::{ |
| 2358 | - executor::InitializeArgs, |
| 2359 | - libpod::{ |
| 2360 | - Client, Request, |
| 2361 | - container::{self, Mount}, |
| 2362 | - }, |
| 2363 | - }; |
| 2364 | - |
| 2365 | - pub struct Libpod { |
| 2366 | - client: Client, |
| 2367 | - } |
| 2368 | - |
| 2369 | - impl Libpod { |
| 2370 | - pub fn new(socket_path: &Path) -> Self { |
| 2371 | - Self { |
| 2372 | - client: Client::new(socket_path), |
| 2373 | - } |
| 2374 | - } |
| 2375 | - } |
| 2376 | - |
| 2377 | - impl super::executor::Executor for Libpod { |
| 2378 | - async fn initialize<'a>(&self, args: &InitializeArgs<'a>) -> Result<(), crate::error::Error> { |
| 2379 | - let container_name = format!("ayllu-build-{}-{}", args.manifest_id, args.workflow_id); |
| 2380 | - let base_dir = args.build_dir.join(&container_name); // TODO Maybe timestamp? |
| 2381 | - std::fs::create_dir_all(base_dir)?; |
| 2382 | - let ayllu_binary_path_string = args |
| 2383 | - .absolute_ayllu_build_binary |
| 2384 | - .to_string_lossy() |
| 2385 | - .to_string(); |
| 2386 | - assert!( |
| 2387 | - self.client |
| 2388 | - .call(&Request::Ping) |
| 2389 | - .await? |
| 2390 | - .status() |
| 2391 | - .is_success() |
| 2392 | - ); |
| 2393 | - if !self |
| 2394 | - .client |
| 2395 | - .call(&Request::ContainerExists(container::Exists { |
| 2396 | - name: container_name.clone(), |
| 2397 | - })) |
| 2398 | - .await? |
| 2399 | - .status() |
| 2400 | - .is_success() |
| 2401 | - { |
| 2402 | - self.client |
| 2403 | - .call(&Request::CreateContainer(container::Create { |
| 2404 | - name: container_name.clone(), |
| 2405 | - image: args.image.to_string(), |
| 2406 | - command: vec![ |
| 2407 | - String::from("/usr/bin/ayllu-build"), |
| 2408 | - String::from("monitor"), |
| 2409 | - ], |
| 2410 | - mounts: vec![ |
| 2411 | - // Mount { |
| 2412 | - // read_only: true, |
| 2413 | - // source: source_dir_string, |
| 2414 | - // destination: String::from("/_ayllu/src"), |
| 2415 | - // r#type: String::from("bind"), |
| 2416 | - // }, |
| 2417 | - Mount { |
| 2418 | - read_only: true, |
| 2419 | - source: ayllu_binary_path_string, |
| 2420 | - destination: String::from("/usr/bin/ayllu-build"), |
| 2421 | - r#type: String::from("bind"), |
| 2422 | - }, |
| 2423 | - ], |
| 2424 | - terminal: true, |
| 2425 | - })) |
| 2426 | - .await?; |
| 2427 | - } |
| 2428 | - |
| 2429 | - self.client |
| 2430 | - .upload_tree(&container_name, args.src_package, "/_ayllu") |
| 2431 | - .await?; |
| 2432 | - |
| 2433 | - self.client |
| 2434 | - .call(&Request::StartContainer(container::Start { |
| 2435 | - name: container_name.clone(), |
| 2436 | - })) |
| 2437 | - .await?; |
| 2438 | - |
| 2439 | - Ok(()) |
| 2440 | - } |
| 2441 | - |
| 2442 | - async fn execute( |
| 2443 | - &self, |
| 2444 | - step: &ayllu_database::build::Step, |
| 2445 | - context: &crate::executor::Context, |
| 2446 | - ) -> Result<(Vec<ayllu_database::build::LogLine>, i32), crate::error::Error> { |
| 2447 | - // FIXME stream directly into the database because it will result in |
| 2448 | - // fast log output in the frontend. |
| 2449 | - let (tx, mut rx) = mpsc::channel::<(crate::libpod::Stream, String)>(1); |
| 2450 | - let (tx_signal, rx_signal) = tokio::sync::oneshot::channel::<i32>(); |
| 2451 | - let shell = step.shell.to_string(); |
| 2452 | - let input = step.input.to_string(); |
| 2453 | - let client = self.client.clone(); |
| 2454 | - let ctx = context.clone(); |
| 2455 | - tokio::spawn(async move { |
| 2456 | - if let Err(err) = client.exec(&ctx, &shell, &input, tx, tx_signal).await { |
| 2457 | - tracing::error!("Error spawning step: {err:?}"); |
| 2458 | - } |
| 2459 | - }); |
| 2460 | - let mut lines: Vec<LogLine> = Vec::new(); |
| 2461 | - let start = Instant::now(); |
| 2462 | - while let Some(msg) = rx.recv().await { |
| 2463 | - match msg.0 { |
| 2464 | - crate::libpod::Stream::Stdout => tracing::info!("{}", msg.1.trim_end()), |
| 2465 | - crate::libpod::Stream::Stderr => tracing::warn!("{}", msg.1.trim_end()), |
| 2466 | - _ => unreachable!(), |
| 2467 | - } |
| 2468 | - lines.push(LogLine { |
| 2469 | - output: match msg.0 { |
| 2470 | - crate::libpod::Stream::Stdout => ayllu_database::build::Output::Stdout, |
| 2471 | - crate::libpod::Stream::Stderr => ayllu_database::build::Output::Stderr, |
| 2472 | - _ => unimplemented!(), |
| 2473 | - }, |
| 2474 | - runtime: Instant::now().duration_since(start), |
| 2475 | - line: msg.1, |
| 2476 | - }); |
| 2477 | - } |
| 2478 | - |
| 2479 | - let signal = rx_signal.await.unwrap(); |
| 2480 | - if signal == 0 { |
| 2481 | - tracing::info!("Process executed normally") |
| 2482 | - } else { |
| 2483 | - tracing::warn!("Non-zero exit code: {signal}") |
| 2484 | - } |
| 2485 | - |
| 2486 | - // self.client.call().await.unwrap(); |
| 2487 | - Ok((lines, signal)) |
| 2488 | - } |
| 2489 | - |
| 2490 | - async fn shutdown( |
| 2491 | - &self, |
| 2492 | - _manifest_id: i64, |
| 2493 | - _workflow_id: i64, |
| 2494 | - ) -> Result<(), crate::error::Error> { |
| 2495 | - // TODO |
| 2496 | - Ok(()) |
| 2497 | - } |
| 2498 | - } |
| 2499 | diff --git a/ayllu-build/src/libpod.rs b/ayllu-build/src/libpod.rs |
| 2500 | index be5e0e6..3ff7a8c 100644 |
| 2501 | --- a/ayllu-build/src/libpod.rs |
| 2502 | +++ b/ayllu-build/src/libpod.rs |
| 2503 | @@ -1,21 +1,16 @@ |
| 2504 | - use std::{collections::HashMap, io::Cursor, path::Path, sync::Arc, time::Duration}; |
| 2505 | + use std::{collections::HashMap, path::Path}; |
| 2506 | |
| 2507 | - use bytes::Bytes; |
| 2508 | use serde_json::json; |
| 2509 | - use tokio::{ |
| 2510 | - fs::File, |
| 2511 | - io::{AsyncReadExt, AsyncWriteExt}, |
| 2512 | - sync::{Mutex, RwLock, mpsc::Sender}, |
| 2513 | - }; |
| 2514 | + use tokio::{fs::File, io::AsyncReadExt, sync::mpsc::Sender}; |
| 2515 | |
| 2516 | use reqwest::{ |
| 2517 | - Body, ClientBuilder, RequestBuilder, Upgraded, Url, |
| 2518 | + Body, ClientBuilder, Url, |
| 2519 | header::{HeaderMap, HeaderName, HeaderValue}, |
| 2520 | }; |
| 2521 | use serde::{Deserialize, Serialize}; |
| 2522 | use tokio_util::codec::{BytesCodec, FramedRead}; |
| 2523 | |
| 2524 | - use crate::{executor::Context, monitor::Message}; |
| 2525 | + use crate::{error::Error, libpod_executor::Context}; |
| 2526 | |
| 2527 | #[derive(Deserialize, Debug)] |
| 2528 | pub struct ErrorMessage { |
| 2529 | @@ -25,24 +20,6 @@ pub struct ErrorMessage { |
| 2530 | } |
| 2531 | |
| 2532 | #[derive(Debug)] |
| 2533 | - pub enum Error { |
| 2534 | - Network(reqwest::Error), |
| 2535 | - Podman(ErrorMessage), |
| 2536 | - } |
| 2537 | - |
| 2538 | - impl From<Error> for crate::error::Error { |
| 2539 | - fn from(value: Error) -> Self { |
| 2540 | - todo!() |
| 2541 | - } |
| 2542 | - } |
| 2543 | - |
| 2544 | - impl From<reqwest::Error> for Error { |
| 2545 | - fn from(value: reqwest::Error) -> Self { |
| 2546 | - todo!() |
| 2547 | - } |
| 2548 | - } |
| 2549 | - |
| 2550 | - #[derive(Debug)] |
| 2551 | pub enum Stream { |
| 2552 | Stdin, |
| 2553 | Stdout, |
| 2554 | @@ -51,8 +28,6 @@ pub enum Stream { |
| 2555 | |
| 2556 | pub mod container { |
| 2557 | |
| 2558 | - use std::path::PathBuf; |
| 2559 | - |
| 2560 | use super::*; |
| 2561 | |
| 2562 | #[derive(Serialize, Debug)] |
| 2563 | @@ -298,7 +273,7 @@ impl Client { |
| 2564 | } else { |
| 2565 | tracing::error!("libpod: {}: {}", url, res.status()); |
| 2566 | let error_message = res.json::<ErrorMessage>().await?; |
| 2567 | - Err(Error::Podman(error_message)) |
| 2568 | + Err(Error::Libpod(error_message)) |
| 2569 | } |
| 2570 | } |
| 2571 | |
| 2572 | diff --git a/ayllu-build/src/libpod_executor.rs b/ayllu-build/src/libpod_executor.rs |
| 2573 | new file mode 100644 |
| 2574 | index 0000000..5711ea2 |
| 2575 | --- /dev/null |
| 2576 | +++ b/ayllu-build/src/libpod_executor.rs |
| 2577 | @@ -0,0 +1,172 @@ |
| 2578 | + use std::{collections::HashMap, path::Path}; |
| 2579 | + |
| 2580 | + use tokio::sync::{mpsc, oneshot}; |
| 2581 | + |
| 2582 | + use ayllu_database::build::logs::{Stream, WriteLineArgs}; |
| 2583 | + use ayllu_database::build::steps::Step; |
| 2584 | + use serde::Deserialize; |
| 2585 | + |
| 2586 | + use crate::libpod::{ |
| 2587 | + Client, Request, |
| 2588 | + container::{self, Mount}, |
| 2589 | + }; |
| 2590 | + |
| 2591 | + // context exposed to the runtime of individual steps, also used in other |
| 2592 | + // parts of the build process. |
| 2593 | + #[derive(Deserialize, Debug, Clone, Default)] |
| 2594 | + pub struct Context { |
| 2595 | + pub manifest_id: i32, |
| 2596 | + pub workflow_id: i32, |
| 2597 | + pub step_id: i32, |
| 2598 | + pub git_hash: String, |
| 2599 | + pub repo_url: String, |
| 2600 | + pub environment: HashMap<String, Option<String>>, |
| 2601 | + } |
| 2602 | + |
| 2603 | + pub struct InitializeArgs<'a> { |
| 2604 | + pub manifest_id: i32, |
| 2605 | + pub workflow_id: i32, |
| 2606 | + pub build_dir: &'a Path, |
| 2607 | + pub image: &'a str, |
| 2608 | + pub init_args: &'a [&'a str], |
| 2609 | + pub source_dir: &'a Path, |
| 2610 | + pub absolute_ayllu_build_binary: &'a Path, |
| 2611 | + // path to source tree and other things needed in the ct runtime |
| 2612 | + pub src_package: &'a Path, |
| 2613 | + } |
| 2614 | + |
| 2615 | + pub struct Libpod { |
| 2616 | + client: Client, |
| 2617 | + } |
| 2618 | + |
| 2619 | + impl Libpod { |
| 2620 | + pub fn new(socket_path: &Path) -> Self { |
| 2621 | + Self { |
| 2622 | + client: Client::new(socket_path), |
| 2623 | + } |
| 2624 | + } |
| 2625 | + } |
| 2626 | + |
| 2627 | + impl Libpod { |
| 2628 | + pub async fn initialize<'a>( |
| 2629 | + &self, |
| 2630 | + args: &InitializeArgs<'a>, |
| 2631 | + ) -> Result<(), crate::error::Error> { |
| 2632 | + let container_name = format!("ayllu-build-{}-{}", args.manifest_id, args.workflow_id); |
| 2633 | + let base_dir = args.build_dir.join(&container_name); // TODO Maybe timestamp? |
| 2634 | + std::fs::create_dir_all(base_dir)?; |
| 2635 | + let ayllu_binary_path_string = args |
| 2636 | + .absolute_ayllu_build_binary |
| 2637 | + .to_string_lossy() |
| 2638 | + .to_string(); |
| 2639 | + assert!( |
| 2640 | + self.client |
| 2641 | + .call(&Request::Ping) |
| 2642 | + .await? |
| 2643 | + .status() |
| 2644 | + .is_success() |
| 2645 | + ); |
| 2646 | + if !self |
| 2647 | + .client |
| 2648 | + .call(&Request::ContainerExists(container::Exists { |
| 2649 | + name: container_name.clone(), |
| 2650 | + })) |
| 2651 | + .await? |
| 2652 | + .status() |
| 2653 | + .is_success() |
| 2654 | + { |
| 2655 | + self.client |
| 2656 | + .call(&Request::CreateContainer(container::Create { |
| 2657 | + name: container_name.clone(), |
| 2658 | + image: args.image.to_string(), |
| 2659 | + command: vec![ |
| 2660 | + String::from("/usr/bin/ayllu-build"), |
| 2661 | + String::from("monitor"), |
| 2662 | + ], |
| 2663 | + mounts: vec![ |
| 2664 | + // Mount { |
| 2665 | + // read_only: true, |
| 2666 | + // source: source_dir_string, |
| 2667 | + // destination: String::from("/_ayllu/src"), |
| 2668 | + // r#type: String::from("bind"), |
| 2669 | + // }, |
| 2670 | + Mount { |
| 2671 | + read_only: true, |
| 2672 | + source: ayllu_binary_path_string, |
| 2673 | + destination: String::from("/usr/bin/ayllu-build"), |
| 2674 | + r#type: String::from("bind"), |
| 2675 | + }, |
| 2676 | + ], |
| 2677 | + terminal: true, |
| 2678 | + })) |
| 2679 | + .await?; |
| 2680 | + } |
| 2681 | + |
| 2682 | + self.client |
| 2683 | + .upload_tree(&container_name, args.src_package, "/_ayllu") |
| 2684 | + .await?; |
| 2685 | + |
| 2686 | + self.client |
| 2687 | + .call(&Request::StartContainer(container::Start { |
| 2688 | + name: container_name.clone(), |
| 2689 | + })) |
| 2690 | + .await?; |
| 2691 | + |
| 2692 | + Ok(()) |
| 2693 | + } |
| 2694 | + |
| 2695 | + pub async fn execute<'a>( |
| 2696 | + &self, |
| 2697 | + step: &Step, |
| 2698 | + context: &Context, |
| 2699 | + db: &mut ayllu_database::Ptr<'a>, |
| 2700 | + ) -> Result<i32, crate::error::Error> { |
| 2701 | + let (tx, mut rx) = mpsc::channel::<(crate::libpod::Stream, String)>(1); |
| 2702 | + let (tx_signal, rx_signal) = oneshot::channel::<i32>(); |
| 2703 | + let shell = step.shell.to_string(); |
| 2704 | + let input = step.input.to_string(); |
| 2705 | + let client = self.client.clone(); |
| 2706 | + let ctx = context.clone(); |
| 2707 | + tokio::spawn(async move { |
| 2708 | + if let Err(err) = client.exec(&ctx, &shell, &input, tx, tx_signal).await { |
| 2709 | + tracing::error!("Error spawning step: {err:?}"); |
| 2710 | + } |
| 2711 | + }); |
| 2712 | + while let Some(msg) = rx.recv().await { |
| 2713 | + match msg.0 { |
| 2714 | + crate::libpod::Stream::Stdout => tracing::info!("{}", msg.1.trim_end()), |
| 2715 | + crate::libpod::Stream::Stderr => tracing::warn!("{}", msg.1.trim_end()), |
| 2716 | + _ => unreachable!(), |
| 2717 | + } |
| 2718 | + let stream = match msg.0 { |
| 2719 | + crate::libpod::Stream::Stdin => unimplemented!(), |
| 2720 | + crate::libpod::Stream::Stdout => Stream::Stdout, |
| 2721 | + crate::libpod::Stream::Stderr => Stream::Stderr, |
| 2722 | + }; |
| 2723 | + db.log_write_line(&WriteLineArgs { |
| 2724 | + step_id: step.id, |
| 2725 | + stream, |
| 2726 | + line: &msg.1, |
| 2727 | + })?; |
| 2728 | + } |
| 2729 | + |
| 2730 | + let signal = rx_signal.await.unwrap(); |
| 2731 | + if signal == 0 { |
| 2732 | + tracing::info!("Process executed normally") |
| 2733 | + } else { |
| 2734 | + tracing::warn!("Non-zero exit code: {signal}") |
| 2735 | + } |
| 2736 | + |
| 2737 | + // self.client.call().await.unwrap(); |
| 2738 | + Ok(signal) |
| 2739 | + } |
| 2740 | + |
| 2741 | + pub fn shutdown( |
| 2742 | + &self, |
| 2743 | + _manifest_id: i32, |
| 2744 | + _workflow_id: i32, |
| 2745 | + ) -> Result<(), crate::error::Error> { |
| 2746 | + // TODO |
| 2747 | + Ok(()) |
| 2748 | + } |
| 2749 | + } |
| 2750 | diff --git a/ayllu-build/src/libpod_monitor.rs b/ayllu-build/src/libpod_monitor.rs |
| 2751 | new file mode 100644 |
| 2752 | index 0000000..1c1af6d |
| 2753 | --- /dev/null |
| 2754 | +++ b/ayllu-build/src/libpod_monitor.rs |
| 2755 | @@ -0,0 +1,21 @@ |
| 2756 | + use std::{path::Path, time::Duration}; |
| 2757 | + |
| 2758 | + pub struct InitializeArgs {} |
| 2759 | + |
| 2760 | + pub struct Libpod; |
| 2761 | + |
| 2762 | + impl Libpod { |
| 2763 | + pub fn initialize(&self, args: &InitializeArgs) -> Result<(), crate::error::Error> { |
| 2764 | + tracing::info!("Initializing build environment"); |
| 2765 | + ayllu_git::clone("/_ayllu/src.bundle", Path::new("/src"), None).unwrap(); |
| 2766 | + Ok(()) |
| 2767 | + } |
| 2768 | + |
| 2769 | + pub async fn monitor(&self) -> Result<(), crate::error::Error> { |
| 2770 | + tracing::info!("Ayllu monitor running"); |
| 2771 | + // TODO! |
| 2772 | + loop { |
| 2773 | + tokio::time::sleep(Duration::from_secs(1)).await |
| 2774 | + } |
| 2775 | + } |
| 2776 | + } |
| 2777 | diff --git a/ayllu-build/src/main.rs b/ayllu-build/src/main.rs |
| 2778 | index 002fcb7..e502b64 100644 |
| 2779 | --- a/ayllu-build/src/main.rs |
| 2780 | +++ b/ayllu-build/src/main.rs |
| 2781 | @@ -3,21 +3,17 @@ use std::path::Path; |
| 2782 | use tracing::Level; |
| 2783 | |
| 2784 | use ayllu_cmd::build::{Command, Commands}; |
| 2785 | - use ayllu_database::Builder; |
| 2786 | + use ayllu_database::Wrapper as Database; |
| 2787 | + |
| 2788 | + use crate::evaluate::{Runtime, Source}; |
| 2789 | |
| 2790 | - use crate::{ |
| 2791 | - evaluate::{Runtime, Source}, |
| 2792 | - monitor::Monitor, |
| 2793 | - }; |
| 2794 | mod config; |
| 2795 | mod error; |
| 2796 | mod evaluate; |
| 2797 | - mod executor; |
| 2798 | - mod executor_libpod; |
| 2799 | mod libpod; |
| 2800 | + mod libpod_executor; |
| 2801 | + mod libpod_monitor; |
| 2802 | mod models; |
| 2803 | - mod monitor; |
| 2804 | - mod monitor_libpod; |
| 2805 | mod package; |
| 2806 | |
| 2807 | const DEFAULT_BUILD_FILE: &str = ".ayllu-build.json"; |
| 2808 | @@ -33,29 +29,23 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 2809 | tee_output, |
| 2810 | } => { |
| 2811 | let workdir = cfg.builder.work_dir.clone(); |
| 2812 | - let db = Builder::default() |
| 2813 | - .path(cfg.database.path.as_path()) |
| 2814 | - .log_queries(false) // FIXME |
| 2815 | - .build() |
| 2816 | - .await?; |
| 2817 | + let db = Database::new(&cfg.database.path)?; |
| 2818 | let source_path = alternate_path.unwrap_or(Path::new(DEFAULT_BUILD_FILE).to_path_buf()); |
| 2819 | let source_path = std::fs::canonicalize(source_path)?; |
| 2820 | - let rt = Runtime { |
| 2821 | + let mut rt = Runtime { |
| 2822 | db, |
| 2823 | source: Source::Path(source_path), |
| 2824 | tee_output, |
| 2825 | work_dir: workdir.clone(), |
| 2826 | }; |
| 2827 | - let executor = executor_libpod::Libpod::new(Path::new("/tmp/podman.sock")); |
| 2828 | + let executor = libpod_executor::Libpod::new(Path::new("/tmp/podman.sock")); |
| 2829 | rt.evaluate(&executor).await?; |
| 2830 | Ok(()) |
| 2831 | } |
| 2832 | Commands::Monitor => { |
| 2833 | tracing::info!("Ayllu build process has started"); |
| 2834 | - let monitor = crate::monitor_libpod::Libpod { |
| 2835 | - socket_path: Path::new("/tmp/ayllu-build.socket"), |
| 2836 | - }; |
| 2837 | - monitor.initialize(&monitor::InitializeArgs {}).await?; |
| 2838 | + let monitor = libpod_monitor::Libpod; |
| 2839 | + monitor.initialize(&libpod_monitor::InitializeArgs {})?; |
| 2840 | monitor.monitor().await?; |
| 2841 | Ok(()) |
| 2842 | } |
| 2843 | diff --git a/ayllu-build/src/monitor.rs b/ayllu-build/src/monitor.rs |
| 2844 | deleted file mode 100644 |
| 2845 | index 2692d2d..0000000 |
| 2846 | --- a/ayllu-build/src/monitor.rs |
| 2847 | +++ /dev/null |
| 2848 | @@ -1,18 +0,0 @@ |
| 2849 | - use serde::{Deserialize, Serialize}; |
| 2850 | - |
| 2851 | - use crate::error::Error; |
| 2852 | - |
| 2853 | - #[derive(Serialize, Deserialize, Clone, Copy)] |
| 2854 | - pub enum Message { |
| 2855 | - Ping, |
| 2856 | - Pong, |
| 2857 | - Shutdown, |
| 2858 | - } |
| 2859 | - |
| 2860 | - pub struct InitializeArgs {} |
| 2861 | - |
| 2862 | - /// Monitor process for use within a build environment |
| 2863 | - pub trait Monitor { |
| 2864 | - async fn initialize(&self, args: &InitializeArgs) -> Result<(), Error>; |
| 2865 | - async fn monitor(&self) -> Result<(), Error>; |
| 2866 | - } |
| 2867 | diff --git a/ayllu-build/src/monitor_libpod.rs b/ayllu-build/src/monitor_libpod.rs |
| 2868 | deleted file mode 100644 |
| 2869 | index 1707987..0000000 |
| 2870 | --- a/ayllu-build/src/monitor_libpod.rs |
| 2871 | +++ /dev/null |
| 2872 | @@ -1,77 +0,0 @@ |
| 2873 | - use std::{path::Path, sync::Arc, time::Duration}; |
| 2874 | - |
| 2875 | - use tokio::{ |
| 2876 | - io::{self, AsyncBufReadExt, AsyncRead, AsyncReadExt, AsyncWriteExt, BufReader}, |
| 2877 | - net::{UnixListener, UnixStream}, |
| 2878 | - signal, |
| 2879 | - sync::Semaphore, |
| 2880 | - }; |
| 2881 | - |
| 2882 | - use crate::monitor::{Message, Monitor}; |
| 2883 | - |
| 2884 | - pub struct Libpod<'a> { |
| 2885 | - pub socket_path: &'a Path, |
| 2886 | - } |
| 2887 | - |
| 2888 | - impl Libpod<'_> { |
| 2889 | - async fn handle(stream: UnixStream) -> Result<bool, std::io::Error> { |
| 2890 | - let (reader, mut writer) = stream.into_split(); |
| 2891 | - let mut lines = BufReader::new(reader).lines(); |
| 2892 | - |
| 2893 | - while let Some(line) = lines.next_line().await? { |
| 2894 | - let line = line.trim(); |
| 2895 | - if line.is_empty() { |
| 2896 | - continue; |
| 2897 | - } |
| 2898 | - let msg = serde_json::from_str::<Message>(line).unwrap(); |
| 2899 | - match msg { |
| 2900 | - Message::Ping => { |
| 2901 | - let mut msg = serde_json::to_vec(&Message::Pong).unwrap(); |
| 2902 | - msg.push(b'\n'); |
| 2903 | - writer.write_all(&msg).await?; |
| 2904 | - } |
| 2905 | - Message::Pong => {} |
| 2906 | - Message::Shutdown => return Ok(true), |
| 2907 | - } |
| 2908 | - } |
| 2909 | - Ok(false) |
| 2910 | - } |
| 2911 | - } |
| 2912 | - |
| 2913 | - impl Monitor for Libpod<'_> { |
| 2914 | - async fn initialize( |
| 2915 | - &self, |
| 2916 | - args: &crate::monitor::InitializeArgs, |
| 2917 | - ) -> Result<(), crate::error::Error> { |
| 2918 | - tracing::info!("Initializing build environment"); |
| 2919 | - ayllu_git::clone("/_ayllu/src.bundle", Path::new("/src"), None).unwrap(); |
| 2920 | - Ok(()) |
| 2921 | - } |
| 2922 | - |
| 2923 | - async fn monitor(&self) -> Result<(), crate::error::Error> { |
| 2924 | - tracing::info!("Ayllu monitor running"); |
| 2925 | - if self.socket_path.exists() { |
| 2926 | - std::fs::remove_file(self.socket_path)?; |
| 2927 | - } |
| 2928 | - let listener = UnixListener::bind(self.socket_path)?; |
| 2929 | - tracing::info!("Starting Ayllu monitor listening @ {:?}", self.socket_path); |
| 2930 | - loop { |
| 2931 | - tokio::select! { |
| 2932 | - Ok((stream, addr)) = listener.accept() => { |
| 2933 | - tracing::debug!("Handling connection from {addr:?}"); |
| 2934 | - if Libpod::handle(stream).await.expect("Connection failed") { |
| 2935 | - tracing::info!("Got shutdown signal from client"); |
| 2936 | - break |
| 2937 | - } |
| 2938 | - } |
| 2939 | - _ = signal::ctrl_c() => { |
| 2940 | - tracing::info!("Shutting down Ayllu monitor"); |
| 2941 | - let _ = std::fs::remove_file(self.socket_path); |
| 2942 | - break; |
| 2943 | - } |
| 2944 | - } |
| 2945 | - } |
| 2946 | - |
| 2947 | - Ok(()) |
| 2948 | - } |
| 2949 | - } |
| 2950 | diff --git a/ayllu-migrate/src/main.rs b/ayllu-migrate/src/main.rs |
| 2951 | index ba7e127..c80817f 100644 |
| 2952 | --- a/ayllu-migrate/src/main.rs |
| 2953 | +++ b/ayllu-migrate/src/main.rs |
| 2954 | @@ -15,25 +15,8 @@ impl Configurable for Config {} |
| 2955 | async fn main() -> Result<(), Box<dyn std::error::Error>> { |
| 2956 | let args = ayllu_cmd::parse::<Command>(); |
| 2957 | let config: Config = ayllu_config::Reader::load(args.config.as_deref())?; |
| 2958 | - |
| 2959 | ayllu_logging::init(Level::INFO); |
| 2960 | - |
| 2961 | - let database_path = config.database.path.as_path(); |
| 2962 | - |
| 2963 | - let migrations_path = args.migrations.unwrap_or(config.database.migrations); |
| 2964 | - |
| 2965 | - tracing::info!("Running migrations from {migrations_path:?} against {database_path:?}"); |
| 2966 | - |
| 2967 | - let wrapper = ayllu_database::Builder::default() |
| 2968 | - .path(database_path) |
| 2969 | - .migrations(migrations_path.as_path()) |
| 2970 | - .log_queries(true) |
| 2971 | - .build() |
| 2972 | - .await?; |
| 2973 | - |
| 2974 | - wrapper.close().await?; |
| 2975 | - |
| 2976 | + ayllu_database::migrate(&config.database.path)?; |
| 2977 | tracing::info!("Migrations applied successfully"); |
| 2978 | - |
| 2979 | Ok(()) |
| 2980 | } |
| 2981 | diff --git a/ayllu/src/web2/dag.rs b/ayllu/src/web2/dag.rs |
| 2982 | index efdc0a6..91047ce 100644 |
| 2983 | --- a/ayllu/src/web2/dag.rs |
| 2984 | +++ b/ayllu/src/web2/dag.rs |
| 2985 | @@ -1,7 +1,7 @@ |
| 2986 | use std::collections::HashMap; |
| 2987 | |
| 2988 | use ayllu_api::build::Unit; |
| 2989 | - use ayllu_database::build::{ManifestView, Step, Workflow}; |
| 2990 | + use ayllu_database::build::{manifests::Summary, steps::Step, workflows::Workflow}; |
| 2991 | use petgraph::{Graph, dot}; |
| 2992 | |
| 2993 | #[derive(Debug)] |
| 2994 | @@ -20,8 +20,12 @@ impl std::fmt::Display for MappedUnit<'_> { |
| 2995 | } |
| 2996 | |
| 2997 | /// Generate a DAG as an SVG chart |
| 2998 | - pub fn make_svg(view: &ManifestView) -> String { |
| 2999 | - let workflows_by_id: Vec<(i64, (&Workflow, bool))> = view |
| 3000 | + pub fn make_svg(view: &Summary) -> String { |
| 3001 | + if view.manifest.dag_content.is_none() { |
| 3002 | + return String::default(); // FIXME |
| 3003 | + } |
| 3004 | + let dag_content_str = view.manifest.dag_content.as_ref().unwrap(); |
| 3005 | + let workflows_by_id: Vec<(i32, (&Workflow, bool))> = view |
| 3006 | .workflows |
| 3007 | .iter() |
| 3008 | .map(|(workflow, steps)| { |
| 3009 | @@ -36,8 +40,8 @@ pub fn make_svg(view: &ManifestView) -> String { |
| 3010 | ) |
| 3011 | }) |
| 3012 | .collect(); |
| 3013 | - let workflows_by_id: HashMap<i64, (&Workflow, bool)> = HashMap::from_iter(workflows_by_id); |
| 3014 | - let steps_by_id: Vec<(i64, &Step)> = view |
| 3015 | + let workflows_by_id: HashMap<i32, (&Workflow, bool)> = HashMap::from_iter(workflows_by_id); |
| 3016 | + let steps_by_id: Vec<(i32, &Step)> = view |
| 3017 | .workflows |
| 3018 | .iter() |
| 3019 | .flat_map(|workflow| { |
| 3020 | @@ -45,15 +49,17 @@ pub fn make_svg(view: &ManifestView) -> String { |
| 3021 | .1 |
| 3022 | .iter() |
| 3023 | .map(|step| (step.id, step)) |
| 3024 | - .collect::<Vec<(i64, &Step)>>() |
| 3025 | + .collect::<Vec<(i32, &Step)>>() |
| 3026 | }) |
| 3027 | .collect(); |
| 3028 | - let steps_by_id: HashMap<i64, &Step> = HashMap::from_iter(steps_by_id); |
| 3029 | - let graph: Graph<Unit, u8> = serde_json::de::from_str(&view.dag.dag_content).unwrap(); |
| 3030 | + let steps_by_id: HashMap<i32, &Step> = HashMap::from_iter(steps_by_id); |
| 3031 | + let graph: Graph<Unit, u8> = serde_json::de::from_str(&dag_content_str).unwrap(); // FIXME |
| 3032 | let mapped: Graph<MappedUnit, u8> = graph.map( |
| 3033 | |_, unit| match unit { |
| 3034 | - Unit::Step(step_id) => MappedUnit::Step(steps_by_id[step_id]), |
| 3035 | - Unit::Workflow(workflow_id) => MappedUnit::Workflow(workflows_by_id[workflow_id]), |
| 3036 | + Unit::Step(step_id) => MappedUnit::Step(steps_by_id[&(*step_id as i32)]), |
| 3037 | + Unit::Workflow(workflow_id) => { |
| 3038 | + MappedUnit::Workflow(workflows_by_id[&(*workflow_id as i32)]) |
| 3039 | + } |
| 3040 | }, |
| 3041 | |_, weight| *weight, |
| 3042 | ); |
| 3043 | diff --git a/ayllu/src/web2/middleware/database.rs b/ayllu/src/web2/middleware/database.rs |
| 3044 | index dfa068e..3bb028b 100644 |
| 3045 | --- a/ayllu/src/web2/middleware/database.rs |
| 3046 | +++ b/ayllu/src/web2/middleware/database.rs |
| 3047 | @@ -1,3 +1,5 @@ |
| 3048 | + use std::path::PathBuf; |
| 3049 | + |
| 3050 | use axum::{ |
| 3051 | extract::{Request, State}, |
| 3052 | middleware::Next, |
| 3053 | @@ -7,7 +9,7 @@ use axum::{ |
| 3054 | use crate::{config::Config, web2::error::Error}; |
| 3055 | |
| 3056 | #[derive(Clone)] |
| 3057 | - pub struct Builds(pub(crate) Option<ayllu_database::Wrapper>); |
| 3058 | + pub struct Builds(pub(crate) Option<PathBuf>); |
| 3059 | |
| 3060 | impl Builds { |
| 3061 | #[allow(dead_code)] |
| 3062 | @@ -15,22 +17,44 @@ impl Builds { |
| 3063 | self.0.is_some() |
| 3064 | } |
| 3065 | |
| 3066 | - pub fn db(&self) -> Result<&ayllu_database::Wrapper, Error> { |
| 3067 | - match self.0.as_ref() { |
| 3068 | - Some(wrapper) => Ok(wrapper), |
| 3069 | - None => Err(Error::ComponentNotEnabled("builds".to_string())), |
| 3070 | + /// Call SQLite operations on tokio threads since the Diesel async |
| 3071 | + /// interface does this anyways. |
| 3072 | + pub async fn call<T, F>(&self, f: F) -> Result<T, Error> |
| 3073 | + where |
| 3074 | + T: Send + 'static, |
| 3075 | + F: FnOnce(&mut ayllu_database::Ptr) -> Result<T, ayllu_database::Error> + Send + 'static, |
| 3076 | + { |
| 3077 | + if let Some(db_path) = self.0.as_ref() { |
| 3078 | + let db_path = db_path.clone(); |
| 3079 | + let db_result = tokio::task::spawn_blocking(move || { |
| 3080 | + let mut handle = ayllu_database::Wrapper::new_ro(&db_path).unwrap(); |
| 3081 | + let mut ptr = handle.call(); |
| 3082 | + f(&mut ptr) |
| 3083 | + }) |
| 3084 | + .await |
| 3085 | + .unwrap()?; |
| 3086 | + Ok(db_result) |
| 3087 | + } else { |
| 3088 | + Err(Error::ComponentNotEnabled(String::from("Database"))) |
| 3089 | } |
| 3090 | } |
| 3091 | + |
| 3092 | + // pub fn db(&self) -> Result<&ayllu_database::Wrapper, Error> { |
| 3093 | + // match self.0.as_ref() { |
| 3094 | + // Some(wrapper) => Ok(wrapper), |
| 3095 | + // None => Err(Error::ComponentNotEnabled("builds".to_string())), |
| 3096 | + // } |
| 3097 | + // } |
| 3098 | } |
| 3099 | |
| 3100 | pub async fn middleware( |
| 3101 | - State((config, db)): State<(Config, Option<ayllu_database::Wrapper>)>, |
| 3102 | + State((config, db_path)): State<(Config, Option<PathBuf>)>, |
| 3103 | mut req: Request, |
| 3104 | next: Next, |
| 3105 | ) -> Response { |
| 3106 | if config.builder.is_some() { |
| 3107 | - assert!(db.is_some()); // BUG if not enabled |
| 3108 | - req.extensions_mut().insert(Builds(db)); |
| 3109 | + assert!(db_path.is_some()); // BUG if not enabled |
| 3110 | + req.extensions_mut().insert(Builds(db_path)); |
| 3111 | } |
| 3112 | next.run(req).await |
| 3113 | } |
| 3114 | diff --git a/ayllu/src/web2/routes/build.rs b/ayllu/src/web2/routes/build.rs |
| 3115 | index 57ac3f4..8a805e7 100644 |
| 3116 | --- a/ayllu/src/web2/routes/build.rs |
| 3117 | +++ b/ayllu/src/web2/routes/build.rs |
| 3118 | @@ -1,6 +1,10 @@ |
| 3119 | use askama::Template; |
| 3120 | use axum::extract::Path; |
| 3121 | use axum::{extract::Extension, response::Html}; |
| 3122 | + use ayllu_database::build::logs::Line; |
| 3123 | + use ayllu_database::build::manifests::Manifest; |
| 3124 | + use ayllu_database::build::steps::Step; |
| 3125 | + use ayllu_database::build::workflows::Workflow; |
| 3126 | use serde::Deserialize; |
| 3127 | |
| 3128 | use crate::config::Config; |
| 3129 | @@ -12,15 +16,15 @@ use crate::web2::middleware::repository::Preamble; |
| 3130 | use crate::web2::template::Base; |
| 3131 | use crate::web2::template::{components, filters}; |
| 3132 | |
| 3133 | - use ayllu_database::build::{BuildExt, LogLine, Manifest, ManifestItem, Step, Workflow}; |
| 3134 | + // use ayllu_database::build::{BuildExt, LogLine, Manifest, ManifestItem, Step, Workflow}; |
| 3135 | |
| 3136 | - fn concat_log_lines(lines: &[LogLine]) -> String { |
| 3137 | + fn concat_log_lines(lines: &[Line]) -> String { |
| 3138 | let n_lines = lines.len(); |
| 3139 | lines |
| 3140 | .iter() |
| 3141 | .enumerate() |
| 3142 | .fold(String::default(), |mut text, (i, line)| { |
| 3143 | - text.push_str(&line.line); |
| 3144 | + text.push_str(&line.line.trim_end_matches("\n")); |
| 3145 | if i < n_lines { |
| 3146 | text.push('\n'); |
| 3147 | } |
| 3148 | @@ -30,9 +34,9 @@ fn concat_log_lines(lines: &[LogLine]) -> String { |
| 3149 | |
| 3150 | #[derive(Deserialize)] |
| 3151 | pub struct BuildParams { |
| 3152 | - pub manifest_id: i64, |
| 3153 | - pub workflow_id: Option<i64>, |
| 3154 | - pub step_id: Option<i64>, |
| 3155 | + pub manifest_id: i32, |
| 3156 | + pub workflow_id: Option<i32>, |
| 3157 | + pub step_id: Option<i32>, |
| 3158 | } |
| 3159 | |
| 3160 | #[derive(askama::Template)] |
| 3161 | @@ -41,12 +45,14 @@ struct BuildTemplate<'a> { |
| 3162 | pub base: Base, |
| 3163 | pub collection: &'a str, |
| 3164 | pub name: &'a str, |
| 3165 | - pub manifest: Manifest, |
| 3166 | + pub manifest_id: i32, |
| 3167 | + pub created_at: i32, |
| 3168 | + pub runtime: i32, |
| 3169 | + // pub manifest: Manifest, |
| 3170 | pub workflows: Vec<(Workflow, Vec<Step>)>, |
| 3171 | pub dag_svg: String, |
| 3172 | - pub current_workflow: i64, |
| 3173 | - pub current_step: Option<(i64, Step)>, |
| 3174 | - pub step_output: Option<&'a [LogLine]>, |
| 3175 | + pub current_workflow: i32, |
| 3176 | + pub current_step: Option<(i32, Step, Vec<Line>)>, |
| 3177 | } |
| 3178 | |
| 3179 | pub async fn raw( |
| 3180 | @@ -58,9 +64,13 @@ pub async fn raw( |
| 3181 | step_id, |
| 3182 | }): Path<BuildParams>, |
| 3183 | ) -> Result<String, Error> { |
| 3184 | - let db = builds.db()?; |
| 3185 | - // let step = db.read_step(step_id.unwrap()).await?; |
| 3186 | - let lines = db.read_log_lines(step_id.unwrap()).await?; |
| 3187 | + let step_id = step_id.unwrap(); |
| 3188 | + let lines = builds |
| 3189 | + .call(move |conn| { |
| 3190 | + let lines = conn.log_read(step_id, None)?; |
| 3191 | + Ok(lines) |
| 3192 | + }) |
| 3193 | + .await?; |
| 3194 | Ok(concat_log_lines(lines.as_slice())) |
| 3195 | } |
| 3196 | |
| 3197 | @@ -76,50 +86,67 @@ pub async fn build( |
| 3198 | step_id, |
| 3199 | }): Path<BuildParams>, |
| 3200 | ) -> Result<Html<String>, Error> { |
| 3201 | - let db = builds.db()?; |
| 3202 | - let view = db |
| 3203 | - .read_manifest(&preamble.collection_name, &preamble.repo_name, manifest_id) |
| 3204 | - .await?; |
| 3205 | + let (view, current_step) = builds |
| 3206 | + .call(move |conn| { |
| 3207 | + let view = conn.manifest_summary(manifest_id)?; |
| 3208 | + let current_step = if let Some(step_id) = step_id { |
| 3209 | + let step = view.workflows.iter().find_map(|wf| { |
| 3210 | + wf.1.iter() |
| 3211 | + .find(|step| step.id == step_id) |
| 3212 | + .map(|step| (wf.0.id, step)) |
| 3213 | + }); |
| 3214 | + if let Some(step) = step { |
| 3215 | + Some((step.0, step.1.clone(), conn.log_read(step_id, None)?)) |
| 3216 | + } else { |
| 3217 | + None |
| 3218 | + } |
| 3219 | + } else { |
| 3220 | + None |
| 3221 | + }; |
| 3222 | |
| 3223 | - let current_step = if let Some(step_id) = step_id { |
| 3224 | - view.workflows.iter().find_map(|wf| { |
| 3225 | - wf.1.iter() |
| 3226 | - .find(|step| step.id == step_id) |
| 3227 | - .map(|step| (wf.0.id, step.clone())) |
| 3228 | + Ok((view, current_step)) |
| 3229 | }) |
| 3230 | - } else { |
| 3231 | - None |
| 3232 | - }; |
| 3233 | + .await?; |
| 3234 | |
| 3235 | - let step_output = match ¤t_step { |
| 3236 | - Some((_, step)) => { |
| 3237 | - // FIXME: We need to change the db representaiton of log lines and merge |
| 3238 | - // them together here with stdout/stderr highlighting. For now I concat |
| 3239 | - // them together which is excessively stupid / annoying. |
| 3240 | - Some(db.read_log_lines(step.id).await?) |
| 3241 | - // let (_, highlighted) = |
| 3242 | - // highlighter.highlight(&concat_log_lines(lines.as_slice()), None, None, None, true); |
| 3243 | - // Some(highlighted) |
| 3244 | - } |
| 3245 | - None => None, |
| 3246 | - }; |
| 3247 | + // let step_output = match ¤t_step { |
| 3248 | + // Some((_, step)) => { |
| 3249 | + // // FIXME: We need to change the db representaiton of log lines and merge |
| 3250 | + // // them together here with stdout/stderr highlighting. For now I concat |
| 3251 | + // // them together which is excessively stupid / annoying. |
| 3252 | + // Some(db.read_log_lines(step.id).await?) |
| 3253 | + // // let (_, highlighted) = |
| 3254 | + // // highlighter.highlight(&concat_log_lines(lines.as_slice()), None, None, None, true); |
| 3255 | + // // Some(highlighted) |
| 3256 | + // } |
| 3257 | + // None => None, |
| 3258 | + // }; |
| 3259 | |
| 3260 | base.nav_elements = |
| 3261 | crate::web2::navigation::primary("builds", &preamble.collection_name, &preamble.repo_name); |
| 3262 | |
| 3263 | let dag_svg = make_svg(&view); |
| 3264 | |
| 3265 | + let manifest = view.manifest; |
| 3266 | + |
| 3267 | Ok(Html( |
| 3268 | BuildTemplate { |
| 3269 | base, |
| 3270 | collection: &preamble.collection_name, |
| 3271 | name: &preamble.repo_name, |
| 3272 | - manifest: view.manifest, |
| 3273 | - workflows: view.workflows, |
| 3274 | dag_svg, |
| 3275 | current_workflow: workflow_id.unwrap_or(-1), |
| 3276 | + manifest_id, |
| 3277 | + created_at: manifest.created_at, |
| 3278 | + runtime: if let Some(finished_at) = manifest.finished_at { |
| 3279 | + manifest |
| 3280 | + .started_at |
| 3281 | + .unwrap_or_default() |
| 3282 | + .strict_sub(finished_at) |
| 3283 | + } else { |
| 3284 | + -1 |
| 3285 | + }, |
| 3286 | + workflows: view.workflows, |
| 3287 | current_step, |
| 3288 | - step_output: step_output.as_deref(), |
| 3289 | } |
| 3290 | .render()?, |
| 3291 | )) |
| 3292 | @@ -131,7 +158,7 @@ struct BuildsTemplate<'a> { |
| 3293 | pub base: Base, |
| 3294 | pub collection: &'a str, |
| 3295 | pub name: &'a str, |
| 3296 | - pub items: Vec<ManifestItem>, |
| 3297 | + pub manifests: Vec<Manifest>, |
| 3298 | } |
| 3299 | |
| 3300 | pub async fn builds( |
| 3301 | @@ -140,24 +167,19 @@ pub async fn builds( |
| 3302 | Extension(preamble): Extension<Preamble>, |
| 3303 | Extension(mut base): Extension<Base>, |
| 3304 | ) -> Result<Html<String>, Error> { |
| 3305 | - let db = builds.db()?; |
| 3306 | - let items = db |
| 3307 | - .list_manifest( |
| 3308 | - Some(&preamble.collection_name), |
| 3309 | - Some(&preamble.repo_name), |
| 3310 | - None, |
| 3311 | - 9999999, |
| 3312 | - 0, |
| 3313 | - ) |
| 3314 | + // FIXME: Pagination |
| 3315 | + let (collection_name, repo_name) = |
| 3316 | + (preamble.collection_name.clone(), preamble.repo_name.clone()); |
| 3317 | + let manifests = builds |
| 3318 | + .call(move |conn| conn.manifest_list(&collection_name, &repo_name)) |
| 3319 | .await?; |
| 3320 | - // FIXME |
| 3321 | // let manifests = db.list_manifest(999999, 0).await?; |
| 3322 | base.nav_elements = |
| 3323 | crate::web2::navigation::primary("builds", &preamble.collection_name, &preamble.repo_name); |
| 3324 | Ok(Html( |
| 3325 | BuildsTemplate { |
| 3326 | base, |
| 3327 | - items, |
| 3328 | + manifests, |
| 3329 | collection: &preamble.collection_name, |
| 3330 | name: &preamble.repo_name, |
| 3331 | } |
| 3332 | diff --git a/ayllu/src/web2/server.rs b/ayllu/src/web2/server.rs |
| 3333 | index 13f8a29..7a361af 100644 |
| 3334 | --- a/ayllu/src/web2/server.rs |
| 3335 | +++ b/ayllu/src/web2/server.rs |
| 3336 | @@ -1,5 +1,6 @@ |
| 3337 | use std::error::Error; |
| 3338 | use std::net::SocketAddrV4; |
| 3339 | + use std::path::PathBuf; |
| 3340 | use std::sync::Arc; |
| 3341 | use std::{collections::HashMap, path::Path}; |
| 3342 | |
| 3343 | @@ -84,21 +85,14 @@ pub async fn serve(cfg: &Config) -> Result<(), Box<dyn Error>> { |
| 3344 | Vec::new() |
| 3345 | }; |
| 3346 | |
| 3347 | - let mut database: Option<ayllu_database::Wrapper> = None; |
| 3348 | + let mut db_path: Option<PathBuf> = None; |
| 3349 | |
| 3350 | if cfg.builder.is_some() { |
| 3351 | tracing::info!("Builder is enabled thus the database is configured"); |
| 3352 | - database = Some( |
| 3353 | - ayllu_database::Builder::default() |
| 3354 | - .path(cfg.database.as_ref().unwrap().path.as_path()) |
| 3355 | - .read_only(true) |
| 3356 | - .log_queries(false) // FIXME |
| 3357 | - .build() |
| 3358 | - .await?, |
| 3359 | - ); |
| 3360 | + db_path = Some(cfg.database.as_ref().unwrap().path.clone()); |
| 3361 | } |
| 3362 | |
| 3363 | - if database.is_some() { |
| 3364 | + if db_path.is_some() { |
| 3365 | tracing::info!("SQLite Database is serving"); |
| 3366 | } |
| 3367 | |
| 3368 | @@ -193,7 +187,7 @@ pub async fn serve(cfg: &Config) -> Result<(), Box<dyn Error>> { |
| 3369 | .layer(Extension(cfg.clone())) |
| 3370 | .layer(Extension(highlighter)) |
| 3371 | .layer(Extension(adapter)) |
| 3372 | - .layer(from_fn_with_state((cfg.clone(), database), db::middleware)) |
| 3373 | + .layer(from_fn_with_state((cfg.clone(), db_path), db::middleware)) |
| 3374 | .layer(from_fn_with_state(cfg.clone(), template::middleware)) |
| 3375 | // error handling |
| 3376 | .layer(from_fn_with_state(Arc::new(cfg.clone()), error::middleware)) |
| 3377 | diff --git a/ayllu/src/web2/template.rs b/ayllu/src/web2/template.rs |
| 3378 | index 2aac611..8fbd5f9 100644 |
| 3379 | --- a/ayllu/src/web2/template.rs |
| 3380 | +++ b/ayllu/src/web2/template.rs |
| 3381 | @@ -87,7 +87,7 @@ impl Default for Base { |
| 3382 | |
| 3383 | pub mod components { |
| 3384 | use askama::{Template, filters::Safe}; |
| 3385 | - use ayllu_database::build::{LogLine, Output}; |
| 3386 | + use ayllu_database::build::logs::{Line, Stream}; |
| 3387 | |
| 3388 | use crate::web2::template::DEFAULT_RSS_ICON; |
| 3389 | |
| 3390 | @@ -100,12 +100,12 @@ pub mod components { |
| 3391 | {%- for entry in lines -%} |
| 3392 | <tr> |
| 3393 | <td class="line-number">{{loop.index}} </td> |
| 3394 | - {%- match entry.output -%} |
| 3395 | - {% when Output::Stderr %} |
| 3396 | + {% match entry.stream %} |
| 3397 | + {% when Stream::Stderr %} |
| 3398 | <td class="negative"> |
| 3399 | - {% else %} |
| 3400 | + {% when Stream::Stdout %} |
| 3401 | <td> |
| 3402 | - {%- endmatch -%} |
| 3403 | + {% endmatch %} |
| 3404 | {{ entry.line }} |
| 3405 | </td> |
| 3406 | </tr> |
| 3407 | @@ -115,10 +115,10 @@ pub mod components { |
| 3408 | "# |
| 3409 | )] |
| 3410 | struct LogViewer<'a> { |
| 3411 | - lines: &'a [LogLine], |
| 3412 | + lines: &'a [Line], |
| 3413 | } |
| 3414 | |
| 3415 | - pub fn log_viewer(lines: &[LogLine]) -> Safe<String> { |
| 3416 | + pub fn log_viewer(lines: &[Line]) -> Safe<String> { |
| 3417 | Safe(LogViewer { lines }.render().unwrap()) |
| 3418 | } |
| 3419 | |
| 3420 | @@ -237,6 +237,10 @@ pub mod filters { |
| 3421 | Ok(timeutil::friendly(*epoch as u64)) |
| 3422 | } |
| 3423 | |
| 3424 | + pub fn friendly_time_32(epoch: &i32, _: &dyn askama::Values) -> askama::Result<String> { |
| 3425 | + Ok(timeutil::friendly(*epoch as u64)) |
| 3426 | + } |
| 3427 | + |
| 3428 | pub fn friendly_time_maybe( |
| 3429 | epoch: &Option<i64>, |
| 3430 | values: &dyn askama::Values, |
| 3431 | @@ -247,6 +251,16 @@ pub mod filters { |
| 3432 | } |
| 3433 | } |
| 3434 | |
| 3435 | + pub fn friendly_time_maybe_32( |
| 3436 | + epoch: &Option<i32>, |
| 3437 | + values: &dyn askama::Values, |
| 3438 | + ) -> askama::Result<String> { |
| 3439 | + match epoch { |
| 3440 | + Some(value) => friendly_time_32(value, values), |
| 3441 | + None => Ok("?".to_string()), |
| 3442 | + } |
| 3443 | + } |
| 3444 | + |
| 3445 | pub fn format_epoch(epoch: &i64, _: &dyn askama::Values) -> askama::Result<String> { |
| 3446 | let ts = OffsetDateTime::from_unix_timestamp(*epoch).unwrap(); |
| 3447 | let formatted = ts.format(&well_known::Rfc2822).unwrap(); |
| 3448 | diff --git a/ayllu/templates/build.html b/ayllu/templates/build.html |
| 3449 | index 2eb5a78..a1418f0 100644 |
| 3450 | --- a/ayllu/templates/build.html |
| 3451 | +++ b/ayllu/templates/build.html |
| 3452 | @@ -2,7 +2,7 @@ |
| 3453 | {% block content %} |
| 3454 | <section id="builds" class="scrollable raised"> |
| 3455 | <section class="info-bar"> |
| 3456 | - <section class="title"><a href="/{{collection}}/{{name}}/builds/{{manifest.id}}">Build for {{collection}}/{{name}}: {{manifest.id}}</a></section> |
| 3457 | + <section class="title"><a href="/{{collection}}/{{name}}/builds/{{manifest_id}}">Build for {{collection}}/{{name}}: {{manifest_id}}</a></section> |
| 3458 | </section> |
| 3459 | <section class="raised lower-half"> |
| 3460 | <table class="data-table"> |
| 3461 | @@ -19,11 +19,11 @@ |
| 3462 | </tr> |
| 3463 | <tr> |
| 3464 | <td>CreatedAt</td> |
| 3465 | - <td>{{manifest.created_at | friendly_time }}</td> |
| 3466 | + <td>{{created_at | friendly_time_32 }}</td> |
| 3467 | </tr> |
| 3468 | <tr> |
| 3469 | <td>Runtime</td> |
| 3470 | - <td>{{manifest.runtime()}}s</td> |
| 3471 | + <td>{{runtime}}</td> |
| 3472 | </tr> |
| 3473 | </tbody> |
| 3474 | </table> |
| 3475 | @@ -34,7 +34,7 @@ |
| 3476 | <section class="scrollable"> |
| 3477 | <section class="info-bar"> |
| 3478 | <section class="title"> |
| 3479 | - <a href="/{{collection}}/{{name}}/builds/{{manifest.id}}/{{workflow.0.id}}">{{ workflow.0.name }}</a> |
| 3480 | + <a href="/{{collection}}/{{name}}/builds/{{manifest_id}}/{{workflow.0.id}}">{{ workflow.0.name }}</a> |
| 3481 | </section> |
| 3482 | <section> Workflow </section> |
| 3483 | </section> |
| 3484 | @@ -59,11 +59,11 @@ |
| 3485 | {%- else -%} |
| 3486 | <tr> |
| 3487 | {%- endif -%} |
| 3488 | - <td><a href="/{{collection}}/{{name}}/builds/{{manifest.id}}/{{workflow.0.id}}/{{step.id}}"> |
| 3489 | + <td><a href="/{{collection}}/{{name}}/builds/{{manifest_id}}/{{workflow.0.id}}/{{step.id}}"> |
| 3490 | {{step.id}} |
| 3491 | </td> |
| 3492 | - <td><a href="/{{collection}}/{{name}}/builds/{{manifest.id}}/{{workflow.0.id}}/{{step.id}}">{{step.name}}</a></td> |
| 3493 | - <td>{{step.started_at | friendly_time_maybe }}</td> |
| 3494 | + <td><a href="/{{collection}}/{{name}}/builds/{{manifest_id}}/{{workflow.0.id}}/{{step.id}}">{{step.name}}</a></td> |
| 3495 | + <td>{{step.started_at | friendly_time_maybe_32 }}</td> |
| 3496 | <td>{%- if let Some(exit_code) = step.exit_code -%} {{ exit_code }} {%- else -%} ? {%- endif -%}</td> |
| 3497 | </tr> |
| 3498 | {% endfor %} |
| 3499 | @@ -98,11 +98,6 @@ |
| 3500 | </tr> |
| 3501 | </tbody> |
| 3502 | </table> |
| 3503 | - {%- if let Some(log_lines) = step_output -%} |
| 3504 | - <section id="code-viewer" class="scrollable"> |
| 3505 | - {{ components::log_viewer(log_lines)| safe}} |
| 3506 | - </section> |
| 3507 | - {%- endif -%} |
| 3508 | </section> |
| 3509 | </section> |
| 3510 | {%- endif -%} |
| 3511 | diff --git a/ayllu/templates/builds.html b/ayllu/templates/builds.html |
| 3512 | index 63bd12a..717cea4 100644 |
| 3513 | --- a/ayllu/templates/builds.html |
| 3514 | +++ b/ayllu/templates/builds.html |
| 3515 | @@ -15,27 +15,19 @@ |
| 3516 | </tr> |
| 3517 | </thead> |
| 3518 | <tbody> |
| 3519 | - {% for item in items %} |
| 3520 | + {% for manifest in manifests %} |
| 3521 | <tr class="build"> |
| 3522 | <td> |
| 3523 | <div class="name"> |
| 3524 | - <a href="/{{collection}}/{{name}}/builds/{{item.manifest.id}}">{{item.manifest.id}}</a> |
| 3525 | + <a href="/{{collection}}/{{name}}/builds/{{manifest.id}}">{{manifest.id}}</a> |
| 3526 | </div> |
| 3527 | </td> |
| 3528 | <td> |
| 3529 | - <a href="/{{collection}}/{{name}}/builds/{{item.manifest.id}}"> |
| 3530 | - {%- if let Some(success) = item.success -%} |
| 3531 | - {%- if success -%} |
| 3532 | - <span class="positive"> PASS </span> |
| 3533 | - {% else %} |
| 3534 | - <span class="positive"> FAIL </span> |
| 3535 | - {%- endif -%} |
| 3536 | - {% else -%} |
| 3537 | - <span class=""> ? </span> |
| 3538 | - {%- endif -%} |
| 3539 | + <a href="/{{collection}}/{{name}}/builds/{{manifest.id}}"> |
| 3540 | + ??? |
| 3541 | </a> |
| 3542 | </td> |
| 3543 | - <td>{{ item.manifest.created_at | friendly_time }}</td> |
| 3544 | + <td>{{ manifest.created_at | friendly_time_32 }}</td> |
| 3545 | </tr> |
| 3546 | {% endfor %} |
| 3547 | </tbody> |
| 3548 | diff --git a/crates/api/src/build.rs b/crates/api/src/build.rs |
| 3549 | index de3c49c..a5e7d98 100644 |
| 3550 | --- a/crates/api/src/build.rs |
| 3551 | +++ b/crates/api/src/build.rs |
| 3552 | @@ -5,8 +5,8 @@ use serde::{Deserialize, Serialize}; |
| 3553 | /// Unit of execution which is either a workflow or a step |
| 3554 | #[derive(Serialize, Deserialize, Debug, Clone)] |
| 3555 | pub enum Unit { |
| 3556 | - Step(i64), |
| 3557 | - Workflow(i64), |
| 3558 | + Step(i32), |
| 3559 | + Workflow(i32), |
| 3560 | } |
| 3561 | |
| 3562 | impl Display for Unit { |
| 3563 | diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml |
| 3564 | index cd94a87..350436b 100644 |
| 3565 | --- a/crates/database/Cargo.toml |
| 3566 | +++ b/crates/database/Cargo.toml |
| 3567 | @@ -6,10 +6,13 @@ edition = "2024" |
| 3568 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html |
| 3569 | |
| 3570 | [dependencies] |
| 3571 | - async-trait = { workspace = true } |
| 3572 | - futures = { workspace = true } |
| 3573 | + |
| 3574 | + timeutil = { path = "../timeutil" } |
| 3575 | + |
| 3576 | serde = { workspace = true } |
| 3577 | serde_json = { workspace = true } |
| 3578 | - sqlx = { workspace = true } |
| 3579 | - time = { workspace = true } |
| 3580 | tracing = { workspace = true } |
| 3581 | + thiserror = { workspace = true } |
| 3582 | + |
| 3583 | + diesel = { version = "2.3.9", features = ["sqlite", "returning_clauses_for_sqlite_3_35"] } |
| 3584 | + diesel_migrations = { version = "2.3.2", features = ["sqlite"] } |
| 3585 | diff --git a/crates/database/migrations/.diesel_lock b/crates/database/migrations/.diesel_lock |
| 3586 | new file mode 100644 |
| 3587 | index 0000000..e69de29 |
| 3588 | --- /dev/null |
| 3589 | +++ b/crates/database/migrations/.diesel_lock |
| 3590 | diff --git a/crates/database/migrations/.keep b/crates/database/migrations/.keep |
| 3591 | new file mode 100644 |
| 3592 | index 0000000..e69de29 |
| 3593 | --- /dev/null |
| 3594 | +++ b/crates/database/migrations/.keep |
| 3595 | diff --git a/crates/database/migrations/2026-05-04-162320-0000_init/down.sql b/crates/database/migrations/2026-05-04-162320-0000_init/down.sql |
| 3596 | new file mode 100644 |
| 3597 | index 0000000..23a5544 |
| 3598 | --- /dev/null |
| 3599 | +++ b/crates/database/migrations/2026-05-04-162320-0000_init/down.sql |
| 3600 | @@ -0,0 +1,8 @@ |
| 3601 | + -- This file should undo anything in `up.sql` |
| 3602 | + DROP TABLE samples; |
| 3603 | + DROP TABLE dags; |
| 3604 | + DROP TABLE steps_env_vars; |
| 3605 | + DROP TABLE logs; |
| 3606 | + DROP TABLE steps; |
| 3607 | + DROP TABLE workflows; |
| 3608 | + DROP TABLE manifests; |
| 3609 | diff --git a/crates/database/migrations/2026-05-04-162320-0000_init/up.sql b/crates/database/migrations/2026-05-04-162320-0000_init/up.sql |
| 3610 | new file mode 100644 |
| 3611 | index 0000000..9e3aeb0 |
| 3612 | --- /dev/null |
| 3613 | +++ b/crates/database/migrations/2026-05-04-162320-0000_init/up.sql |
| 3614 | @@ -0,0 +1,58 @@ |
| 3615 | + CREATE TABLE manifests ( |
| 3616 | + id INTEGER PRIMARY KEY NOT NULL, |
| 3617 | + collection TEXT NOT NULL, |
| 3618 | + name TEXT NOT NULL, |
| 3619 | + git_hash TEXT NOT NULL, |
| 3620 | + dag_content TEXT, |
| 3621 | + state INTEGER NOT NULL DEFAULT (1) CHECK (state IN (1, 2, 3, 4)), |
| 3622 | + created_at INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 3623 | + started_at INTEGER CHECK (started_at > 0), |
| 3624 | + finished_at INTEGER CHECK (finished_at > 0) |
| 3625 | + ) STRICT ; |
| 3626 | + |
| 3627 | + CREATE TABLE workflows ( |
| 3628 | + id INTEGER PRIMARY KEY NOT NULL, |
| 3629 | + manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 3630 | + name TEXT NOT NULL, |
| 3631 | + image TEXT NOT NULL, |
| 3632 | + started_at INTEGER CHECK (started_at > 0), |
| 3633 | + finished_at INTEGER CHECK (finished_at > 0) |
| 3634 | + ) STRICT ; |
| 3635 | + |
| 3636 | + CREATE TABLE steps ( |
| 3637 | + id INTEGER PRIMARY KEY NOT NULL, |
| 3638 | + name TEXT NOT NULL, |
| 3639 | + workflow_id INTEGER REFERENCES workflows(id) ON DELETE CASCADE NOT NULL, |
| 3640 | + shell TEXT NOT NULL DEFAULT "/bin/sh", |
| 3641 | + environment_json TEXT, |
| 3642 | + input TEXT NOT NULL, |
| 3643 | + started_at INTEGER CHECK (started_at > 0), |
| 3644 | + finished_at INTEGER CHECK (finished_at > 0), |
| 3645 | + exit_code INTEGER CHECK (exit_code <= 255) |
| 3646 | + ) STRICT ; |
| 3647 | + |
| 3648 | + CREATE TABLE logs ( |
| 3649 | + id INTEGER PRIMARY KEY NOT NULL, |
| 3650 | + step_id INTEGER REFERENCES steps(id) ON DELETE CASCADE NOT NULL, |
| 3651 | + timestamp INTEGER NOT NULL, |
| 3652 | + stream INTEGER NOT NULL CHECK (stream IN (1, 2)), |
| 3653 | + line TEXT NOT NULL |
| 3654 | + ) STRICT ; |
| 3655 | + |
| 3656 | + CREATE TABLE samples ( |
| 3657 | + id INTEGER PRIMARY KEY NOT NULL, |
| 3658 | + manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 3659 | + timestamp INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 3660 | + load_1m INTEGER, |
| 3661 | + load_5m INTEGER, |
| 3662 | + load_15m INTEGER, |
| 3663 | + disk_total_bytes INTEGER, |
| 3664 | + disk_free_bytes INTEGER, |
| 3665 | + net_sent_bytes INTEGER, |
| 3666 | + net_received_bytes INTEGER, |
| 3667 | + net_sent_packets INTEGER, |
| 3668 | + net_received_packets INTEGER, |
| 3669 | + mem_total_bytes INTEGER, |
| 3670 | + mem_free_bytes INTEGER, |
| 3671 | + mem_available_bytes INTEGER |
| 3672 | + ) STRICT ; |
| 3673 | diff --git a/crates/database/queries/authors_list_project.sql b/crates/database/queries/authors_list_project.sql |
| 3674 | deleted file mode 100644 |
| 3675 | index 832e3de..0000000 |
| 3676 | --- a/crates/database/queries/authors_list_project.sql |
| 3677 | +++ /dev/null |
| 3678 | @@ -1,30 +0,0 @@ |
| 3679 | - WITH RECURSIVE max_git_id AS |
| 3680 | - (SELECT contributions.id AS hash |
| 3681 | - FROM contributions |
| 3682 | - WHERE git_hash = ? |
| 3683 | - AND repo_path = ? |
| 3684 | - ORDER BY id DESC |
| 3685 | - LIMIT 1), |
| 3686 | - total_contributions AS |
| 3687 | - (SELECT COUNT(*) AS contributions |
| 3688 | - FROM contributions |
| 3689 | - WHERE repo_path = ? |
| 3690 | - AND id <= |
| 3691 | - (SELECT hash |
| 3692 | - FROM max_git_id) ) |
| 3693 | - SELECT authors.username, |
| 3694 | - authors.email, |
| 3695 | - COUNT(contributions.id) AS "count: i64", |
| 3696 | - SUM(contributions.lines_added) AS "lines_added: i64", |
| 3697 | - SUM(contributions.lines_removed) AS "lines_removed: i64", |
| 3698 | - ROUND((COUNT(contributions.id)/CAST( |
| 3699 | - (SELECT contributions |
| 3700 | - FROM total_contributions) AS REAL))*100, 2) AS "percentage: f64" |
| 3701 | - FROM contributions |
| 3702 | - LEFT JOIN authors ON (contributions.author_id = authors.id) |
| 3703 | - WHERE repo_path = ? |
| 3704 | - AND contributions.id <= |
| 3705 | - (SELECT hash |
| 3706 | - FROM max_git_id) |
| 3707 | - GROUP BY authors.email |
| 3708 | - ORDER BY "count: i64" DESC |
| 3709 | diff --git a/crates/database/queries/authors_upsert.sql b/crates/database/queries/authors_upsert.sql |
| 3710 | deleted file mode 100644 |
| 3711 | index 1c55636..0000000 |
| 3712 | --- a/crates/database/queries/authors_upsert.sql |
| 3713 | +++ /dev/null |
| 3714 | @@ -1,10 +0,0 @@ |
| 3715 | - INSERT INTO authors |
| 3716 | - (username, email) |
| 3717 | - VALUES |
| 3718 | - (?, ?) |
| 3719 | - ON CONFLICT |
| 3720 | - DO UPDATE |
| 3721 | - SET |
| 3722 | - username = username, |
| 3723 | - email = email |
| 3724 | - RETURNING id |
| 3725 | diff --git a/crates/database/queries/commits_count.sql b/crates/database/queries/commits_count.sql |
| 3726 | deleted file mode 100644 |
| 3727 | index 0088bb8..0000000 |
| 3728 | --- a/crates/database/queries/commits_count.sql |
| 3729 | +++ /dev/null |
| 3730 | @@ -1,9 +0,0 @@ |
| 3731 | - SELECT |
| 3732 | - COUNT(id) AS count |
| 3733 | - FROM contributions |
| 3734 | - WHERE |
| 3735 | - repo_path = ? AND |
| 3736 | - id <= ( |
| 3737 | - SELECT id FROM contributions |
| 3738 | - WHERE git_hash = ? AND repo_path = ? |
| 3739 | - ) |
| 3740 | diff --git a/crates/database/queries/contribution_add.sql b/crates/database/queries/contribution_add.sql |
| 3741 | deleted file mode 100644 |
| 3742 | index e1085e3..0000000 |
| 3743 | --- a/crates/database/queries/contribution_add.sql |
| 3744 | +++ /dev/null |
| 3745 | @@ -1,11 +0,0 @@ |
| 3746 | - WITH previous(total) AS ( |
| 3747 | - SELECT total FROM contribution_tally |
| 3748 | - WHERE |
| 3749 | - author_id = ? AND repo_path = ? |
| 3750 | - ORDER BY id DESC |
| 3751 | - LIMIT 1 |
| 3752 | - ) |
| 3753 | - INSERT INTO contribution_tally |
| 3754 | - (git_hash, repo_path, author_id, total) |
| 3755 | - VALUES |
| 3756 | - (?, ?, ?, COALESCE((SELECT(total) FROM previous), 0)+1) |
| 3757 | diff --git a/crates/database/queries/contribution_delete.sql b/crates/database/queries/contribution_delete.sql |
| 3758 | deleted file mode 100644 |
| 3759 | index 6fdbe5c..0000000 |
| 3760 | --- a/crates/database/queries/contribution_delete.sql |
| 3761 | +++ /dev/null |
| 3762 | @@ -1,3 +0,0 @@ |
| 3763 | - DELETE FROM contribution_tally |
| 3764 | - WHERE |
| 3765 | - repo_path = ? |
| 3766 | diff --git a/crates/database/queries/contributions_add.sql b/crates/database/queries/contributions_add.sql |
| 3767 | deleted file mode 100644 |
| 3768 | index 9883d94..0000000 |
| 3769 | --- a/crates/database/queries/contributions_add.sql |
| 3770 | +++ /dev/null |
| 3771 | @@ -1,4 +0,0 @@ |
| 3772 | - INSERT INTO contributions |
| 3773 | - (author_id, git_hash, repo_path, time, lines_added, lines_removed) |
| 3774 | - VALUES |
| 3775 | - (?, ?, ?, ?, ?, ?) |
| 3776 | diff --git a/crates/database/queries/contributions_bucket.sql b/crates/database/queries/contributions_bucket.sql |
| 3777 | deleted file mode 100644 |
| 3778 | index c4e2e55..0000000 |
| 3779 | --- a/crates/database/queries/contributions_bucket.sql |
| 3780 | +++ /dev/null |
| 3781 | @@ -1,10 +0,0 @@ |
| 3782 | - SELECT |
| 3783 | - COUNT(id) AS "count!: i64", |
| 3784 | - time, |
| 3785 | - SUM(lines_added) AS "added!: i64", |
| 3786 | - SUM(lines_removed) AS "removed!: i64" |
| 3787 | - FROM contributions WHERE |
| 3788 | - repo_path = ? AND |
| 3789 | - id <= (SELECT id FROM contributions WHERE git_hash = ?) AND |
| 3790 | - time <= ? AND time >= ? |
| 3791 | - GROUP BY strftime(?, time) |
| 3792 | diff --git a/crates/database/queries/contributions_delete.sql b/crates/database/queries/contributions_delete.sql |
| 3793 | deleted file mode 100644 |
| 3794 | index 0ee5563..0000000 |
| 3795 | --- a/crates/database/queries/contributions_delete.sql |
| 3796 | +++ /dev/null |
| 3797 | @@ -1,2 +0,0 @@ |
| 3798 | - DELETE FROM contributions |
| 3799 | - WHERE repo_path = ? |
| 3800 | diff --git a/crates/database/queries/contributions_list.sql b/crates/database/queries/contributions_list.sql |
| 3801 | deleted file mode 100644 |
| 3802 | index fae5633..0000000 |
| 3803 | --- a/crates/database/queries/contributions_list.sql |
| 3804 | +++ /dev/null |
| 3805 | @@ -1,42 +0,0 @@ |
| 3806 | - WITH RECURSIVE |
| 3807 | - tallys AS ( |
| 3808 | - SELECT |
| 3809 | - authors.username AS name, |
| 3810 | - authors.email AS email, |
| 3811 | - MAX(contribution_tally.total) AS total |
| 3812 | - FROM contribution_tally |
| 3813 | - LEFT JOIN authors ON |
| 3814 | - (authors.id = contribution_tally.author_id) |
| 3815 | - WHERE |
| 3816 | - contribution_tally.id < ( |
| 3817 | - SELECT id FROM contributions |
| 3818 | - WHERE |
| 3819 | - repo_path = ? AND git_hash = ? |
| 3820 | - ORDER BY id DESC |
| 3821 | - LIMIT 1 |
| 3822 | - ) AND |
| 3823 | - contribution_tally.repo_path = ? |
| 3824 | - GROUP BY authors.email |
| 3825 | - ORDER BY contribution_tally.total DESC |
| 3826 | - LIMIT 5), |
| 3827 | - raw_commits AS ( |
| 3828 | - SELECT |
| 3829 | - COUNT(*) as total |
| 3830 | - FROM contributions |
| 3831 | - WHERE |
| 3832 | - contributions.id < ( |
| 3833 | - SELECT id FROM contributions |
| 3834 | - WHERE |
| 3835 | - repo_path = ? AND git_hash = ? |
| 3836 | - ORDER BY id DESC |
| 3837 | - LIMIT 1 |
| 3838 | - ) AND |
| 3839 | - contributions.repo_path = ? |
| 3840 | - ) |
| 3841 | - SELECT |
| 3842 | - name, |
| 3843 | - email, |
| 3844 | - ( |
| 3845 | - CAST(tallys.total AS REAL)/(SELECT total FROM raw_commits) |
| 3846 | - ) * 100 AS "percentage: i64" |
| 3847 | - FROM tallys |
| 3848 | diff --git a/crates/database/queries/dags_create.sql b/crates/database/queries/dags_create.sql |
| 3849 | deleted file mode 100644 |
| 3850 | index 07bd1bb..0000000 |
| 3851 | --- a/crates/database/queries/dags_create.sql |
| 3852 | +++ /dev/null |
| 3853 | @@ -1,2 +0,0 @@ |
| 3854 | - INSERT INTO dags (manifest_id, dag_content) |
| 3855 | - VALUES (?, ?) RETURNING id |
| 3856 | diff --git a/crates/database/queries/dags_read.sql b/crates/database/queries/dags_read.sql |
| 3857 | deleted file mode 100644 |
| 3858 | index d2bb6ca..0000000 |
| 3859 | --- a/crates/database/queries/dags_read.sql |
| 3860 | +++ /dev/null |
| 3861 | @@ -1,3 +0,0 @@ |
| 3862 | - SELECT |
| 3863 | - id, manifest_id, dag_content |
| 3864 | - FROM dags WHERE manifest_id = ? |
| 3865 | diff --git a/crates/database/queries/job_tracking_add.sql b/crates/database/queries/job_tracking_add.sql |
| 3866 | deleted file mode 100644 |
| 3867 | index 7e70756..0000000 |
| 3868 | --- a/crates/database/queries/job_tracking_add.sql |
| 3869 | +++ /dev/null |
| 3870 | @@ -1,4 +0,0 @@ |
| 3871 | - INSERT INTO job_tracking |
| 3872 | - (repo_path, git_hash, kind, job_id) |
| 3873 | - VALUES |
| 3874 | - (?, ?, ?, ?) |
| 3875 | diff --git a/crates/database/queries/job_tracking_delete.sql b/crates/database/queries/job_tracking_delete.sql |
| 3876 | deleted file mode 100644 |
| 3877 | index 3aef33d..0000000 |
| 3878 | --- a/crates/database/queries/job_tracking_delete.sql |
| 3879 | +++ /dev/null |
| 3880 | @@ -1,3 +0,0 @@ |
| 3881 | - DELETE FROM job_tracking |
| 3882 | - WHERE |
| 3883 | - repo_path = ? |
| 3884 | diff --git a/crates/database/queries/job_tracking_delete_by_repo.sql b/crates/database/queries/job_tracking_delete_by_repo.sql |
| 3885 | deleted file mode 100644 |
| 3886 | index ebd0363..0000000 |
| 3887 | --- a/crates/database/queries/job_tracking_delete_by_repo.sql |
| 3888 | +++ /dev/null |
| 3889 | @@ -1,3 +0,0 @@ |
| 3890 | - DELETE FROM jobs |
| 3891 | - WHERE |
| 3892 | - repo_path = ? |
| 3893 | diff --git a/crates/database/queries/job_tracking_read.sql b/crates/database/queries/job_tracking_read.sql |
| 3894 | deleted file mode 100644 |
| 3895 | index 823dfc5..0000000 |
| 3896 | --- a/crates/database/queries/job_tracking_read.sql |
| 3897 | +++ /dev/null |
| 3898 | @@ -1,8 +0,0 @@ |
| 3899 | - SELECT |
| 3900 | - git_hash AS "git_hash!" |
| 3901 | - FROM job_tracking |
| 3902 | - WHERE |
| 3903 | - repo_path = ? AND |
| 3904 | - kind = ? |
| 3905 | - ORDER BY id DESC |
| 3906 | - LIMIT 1 |
| 3907 | diff --git a/crates/database/queries/jobs_create.sql b/crates/database/queries/jobs_create.sql |
| 3908 | deleted file mode 100644 |
| 3909 | index 4a1bea5..0000000 |
| 3910 | --- a/crates/database/queries/jobs_create.sql |
| 3911 | +++ /dev/null |
| 3912 | @@ -1,5 +0,0 @@ |
| 3913 | - INSERT INTO jobs |
| 3914 | - (created_at, repo_path, kind) |
| 3915 | - VALUES |
| 3916 | - (?, ?, ?) |
| 3917 | - RETURNING id |
| 3918 | diff --git a/crates/database/queries/jobs_delete.sql b/crates/database/queries/jobs_delete.sql |
| 3919 | deleted file mode 100644 |
| 3920 | index c70ba25..0000000 |
| 3921 | --- a/crates/database/queries/jobs_delete.sql |
| 3922 | +++ /dev/null |
| 3923 | @@ -1,2 +0,0 @@ |
| 3924 | - DELETE FROM jobs |
| 3925 | - WHERE jobs.id = ? |
| 3926 | diff --git a/crates/database/queries/jobs_list.sql b/crates/database/queries/jobs_list.sql |
| 3927 | deleted file mode 100644 |
| 3928 | index b1e7f72..0000000 |
| 3929 | --- a/crates/database/queries/jobs_list.sql |
| 3930 | +++ /dev/null |
| 3931 | @@ -1,15 +0,0 @@ |
| 3932 | - SELECT |
| 3933 | - jobs.id AS "id!", |
| 3934 | - created_at AS "created_at: OffsetDateTime", |
| 3935 | - jobs.repo_path AS "repo_path!: String", |
| 3936 | - jobs.kind AS "kind!: String", |
| 3937 | - runtime AS "runtime: u32", |
| 3938 | - success AS "success: bool", |
| 3939 | - ( |
| 3940 | - SELECT COUNT(id) FROM job_tracking |
| 3941 | - WHERE job_tracking.job_id = jobs.id |
| 3942 | - ) AS "commits!: i32" |
| 3943 | - FROM jobs |
| 3944 | - WHERE |
| 3945 | - jobs.repo_path = ? OR ? IS NULL |
| 3946 | - ORDER BY DATETIME(created_at) ASC |
| 3947 | diff --git a/crates/database/queries/jobs_update.sql b/crates/database/queries/jobs_update.sql |
| 3948 | deleted file mode 100644 |
| 3949 | index ea7e521..0000000 |
| 3950 | --- a/crates/database/queries/jobs_update.sql |
| 3951 | +++ /dev/null |
| 3952 | @@ -1,6 +0,0 @@ |
| 3953 | - UPDATE jobs |
| 3954 | - SET |
| 3955 | - runtime = ?, |
| 3956 | - success = ? |
| 3957 | - WHERE |
| 3958 | - jobs.id = ? |
| 3959 | diff --git a/crates/database/queries/languages_add.sql b/crates/database/queries/languages_add.sql |
| 3960 | deleted file mode 100644 |
| 3961 | index 54551b3..0000000 |
| 3962 | --- a/crates/database/queries/languages_add.sql |
| 3963 | +++ /dev/null |
| 3964 | @@ -1,4 +0,0 @@ |
| 3965 | - INSERT INTO languages |
| 3966 | - (git_hash, repo_path, language, loc) |
| 3967 | - VALUES |
| 3968 | - (?,?,?,?) |
| 3969 | diff --git a/crates/database/queries/languages_delete.sql b/crates/database/queries/languages_delete.sql |
| 3970 | deleted file mode 100644 |
| 3971 | index 06c4349..0000000 |
| 3972 | --- a/crates/database/queries/languages_delete.sql |
| 3973 | +++ /dev/null |
| 3974 | @@ -1,3 +0,0 @@ |
| 3975 | - DELETE FROM languages |
| 3976 | - WHERE |
| 3977 | - repo_path = ? |
| 3978 | diff --git a/crates/database/queries/languages_list.sql b/crates/database/queries/languages_list.sql |
| 3979 | deleted file mode 100644 |
| 3980 | index 608a719..0000000 |
| 3981 | --- a/crates/database/queries/languages_list.sql |
| 3982 | +++ /dev/null |
| 3983 | @@ -1,13 +0,0 @@ |
| 3984 | - SELECT |
| 3985 | - language, |
| 3986 | - loc, |
| 3987 | - ROUND( |
| 3988 | - CAST(loc AS REAL)/CAST( |
| 3989 | - (SELECT SUM(loc) FROM languages |
| 3990 | - WHERE repo_path = ? AND git_hash = ?) AS REAL)*100) |
| 3991 | - AS "percentage: f64" |
| 3992 | - FROM languages |
| 3993 | - WHERE |
| 3994 | - repo_path = ? AND git_hash = ? |
| 3995 | - ORDER BY "percentage: f64" DESC |
| 3996 | - LIMIT 5 |
| 3997 | diff --git a/crates/database/queries/latest_commit.sql b/crates/database/queries/latest_commit.sql |
| 3998 | deleted file mode 100644 |
| 3999 | index bd26eac..0000000 |
| 4000 | --- a/crates/database/queries/latest_commit.sql |
| 4001 | +++ /dev/null |
| 4002 | @@ -1,7 +0,0 @@ |
| 4003 | - SELECT |
| 4004 | - git_hash |
| 4005 | - FROM contributions |
| 4006 | - WHERE |
| 4007 | - repo_path = ? |
| 4008 | - ORDER BY id DESC |
| 4009 | - LIMIT 1 |
| 4010 | diff --git a/crates/database/queries/mail_deactivate_unused.sql b/crates/database/queries/mail_deactivate_unused.sql |
| 4011 | deleted file mode 100644 |
| 4012 | index 730dc92..0000000 |
| 4013 | --- a/crates/database/queries/mail_deactivate_unused.sql |
| 4014 | +++ /dev/null |
| 4015 | @@ -1 +0,0 @@ |
| 4016 | - UPDATE lists SET enabled = 0 WHERE address NOT IN (?) |
| 4017 | diff --git a/crates/database/queries/mail_deliver_message.sql b/crates/database/queries/mail_deliver_message.sql |
| 4018 | deleted file mode 100644 |
| 4019 | index 6763a82..0000000 |
| 4020 | --- a/crates/database/queries/mail_deliver_message.sql |
| 4021 | +++ /dev/null |
| 4022 | @@ -1,10 +0,0 @@ |
| 4023 | - INSERT INTO messages |
| 4024 | - (message_id, list_id, in_reply_to, subject, mail_from, content_body, raw_message) |
| 4025 | - VALUES ( |
| 4026 | - ?, |
| 4027 | - ( SELECT id FROM lists WHERE address = ? LIMIT 1 ), |
| 4028 | - ?, |
| 4029 | - ?, |
| 4030 | - ?, |
| 4031 | - ?, ? |
| 4032 | - ) RETURNING messages.id |
| 4033 | diff --git a/crates/database/queries/mail_has_message.sql b/crates/database/queries/mail_has_message.sql |
| 4034 | deleted file mode 100644 |
| 4035 | index e32ce95..0000000 |
| 4036 | --- a/crates/database/queries/mail_has_message.sql |
| 4037 | +++ /dev/null |
| 4038 | @@ -1,5 +0,0 @@ |
| 4039 | - SELECT |
| 4040 | - CASE |
| 4041 | - WHEN (SELECT COUNT(*) FROM messages WHERE message_id = ?) >= 1 THEN TRUE |
| 4042 | - ELSE FALSE |
| 4043 | - END AS "has_message!: bool" |
| 4044 | diff --git a/crates/database/queries/mail_list_create.sql b/crates/database/queries/mail_list_create.sql |
| 4045 | deleted file mode 100644 |
| 4046 | index 770b76a..0000000 |
| 4047 | --- a/crates/database/queries/mail_list_create.sql |
| 4048 | +++ /dev/null |
| 4049 | @@ -1,9 +0,0 @@ |
| 4050 | - INSERT INTO lists |
| 4051 | - (name, address, description, enabled) |
| 4052 | - VALUES |
| 4053 | - (?, ?, ?, ?) |
| 4054 | - ON CONFLICT (address) DO |
| 4055 | - UPDATE SET |
| 4056 | - name = ?, |
| 4057 | - description = ?, |
| 4058 | - enabled = ? |
| 4059 | diff --git a/crates/database/queries/mail_list_outbox.sql b/crates/database/queries/mail_list_outbox.sql |
| 4060 | deleted file mode 100644 |
| 4061 | index 8eaa79e..0000000 |
| 4062 | --- a/crates/database/queries/mail_list_outbox.sql |
| 4063 | +++ /dev/null |
| 4064 | @@ -1,13 +0,0 @@ |
| 4065 | - SELECT |
| 4066 | - outbox.id, |
| 4067 | - messages.message_id AS "message_id!: String", |
| 4068 | - lists.name AS "list_name!: String", |
| 4069 | - participants.address AS "address!: String", |
| 4070 | - messages.raw_message AS raw_message |
| 4071 | - FROM outbox |
| 4072 | - LEFT JOIN participants ON outbox.recipient = participants.address |
| 4073 | - LEFT JOIN messages ON messages.id = outbox.message_id |
| 4074 | - LEFT JOIN lists ON messages.list_id = lists.id |
| 4075 | - WHERE |
| 4076 | - (SELECT COUNT(*) FROM delivery_failures |
| 4077 | - WHERE delivery_failures.outbox_id = outbox.id) < ? |
| 4078 | diff --git a/crates/database/queries/mail_outbox_failed.sql b/crates/database/queries/mail_outbox_failed.sql |
| 4079 | deleted file mode 100644 |
| 4080 | index c7dafcb..0000000 |
| 4081 | --- a/crates/database/queries/mail_outbox_failed.sql |
| 4082 | +++ /dev/null |
| 4083 | @@ -1,3 +0,0 @@ |
| 4084 | - INSERT INTO delivery_failures |
| 4085 | - (outbox_id, error_kind, message) |
| 4086 | - VALUES (?, ?, ?) |
| 4087 | diff --git a/crates/database/queries/mail_outbox_successful.sql b/crates/database/queries/mail_outbox_successful.sql |
| 4088 | deleted file mode 100644 |
| 4089 | index 0b0269c..0000000 |
| 4090 | --- a/crates/database/queries/mail_outbox_successful.sql |
| 4091 | +++ /dev/null |
| 4092 | @@ -1 +0,0 @@ |
| 4093 | - DELETE FROM outbox WHERE id = ? |
| 4094 | diff --git a/crates/database/queries/mail_read_message.sql b/crates/database/queries/mail_read_message.sql |
| 4095 | deleted file mode 100644 |
| 4096 | index 1696cae..0000000 |
| 4097 | --- a/crates/database/queries/mail_read_message.sql |
| 4098 | +++ /dev/null |
| 4099 | @@ -1 +0,0 @@ |
| 4100 | - SELECT * FROM messages WHERE id = ? |
| 4101 | diff --git a/crates/database/queries/mail_read_thread.sql b/crates/database/queries/mail_read_thread.sql |
| 4102 | deleted file mode 100644 |
| 4103 | index 09342d0..0000000 |
| 4104 | --- a/crates/database/queries/mail_read_thread.sql |
| 4105 | +++ /dev/null |
| 4106 | @@ -1,18 +0,0 @@ |
| 4107 | - WITH RECURSIVE tree AS ( |
| 4108 | - SELECT messages.*, 0 AS depth FROM messages |
| 4109 | - WHERE messages.message_id = ? |
| 4110 | - UNION ALL |
| 4111 | - SELECT other.*, depth + 1 FROM messages other |
| 4112 | - JOIN tree ON other.in_reply_to = tree.message_id |
| 4113 | - ) |
| 4114 | - SELECT |
| 4115 | - message_id, |
| 4116 | - in_reply_to, |
| 4117 | - subject, |
| 4118 | - (SELECT address FROM participants WHERE participants.id = tree.mail_from LIMIT 1) |
| 4119 | - mail_from, |
| 4120 | - raw_message, |
| 4121 | - content_body, |
| 4122 | - reply_count, |
| 4123 | - depth AS "depth!: i64" |
| 4124 | - FROM tree ORDER BY depth |
| 4125 | diff --git a/crates/database/queries/mail_read_threads.sql b/crates/database/queries/mail_read_threads.sql |
| 4126 | deleted file mode 100644 |
| 4127 | index d2e3b4a..0000000 |
| 4128 | --- a/crates/database/queries/mail_read_threads.sql |
| 4129 | +++ /dev/null |
| 4130 | @@ -1,9 +0,0 @@ |
| 4131 | - SELECT |
| 4132 | - messages.message_id, |
| 4133 | - messages.subject, |
| 4134 | - messages.reply_count, |
| 4135 | - participants.address AS "mail_from!: String" |
| 4136 | - FROM messages |
| 4137 | - LEFT JOIN lists ON lists.id = messages.id |
| 4138 | - LEFT JOIN participants ON participants.id = messages.mail_from |
| 4139 | - WHERE lists.name = ? AND messages.in_reply_to IS NULL |
| 4140 | diff --git a/crates/database/queries/mail_thread_count.sql b/crates/database/queries/mail_thread_count.sql |
| 4141 | deleted file mode 100644 |
| 4142 | index 5dc619a..0000000 |
| 4143 | --- a/crates/database/queries/mail_thread_count.sql |
| 4144 | +++ /dev/null |
| 4145 | @@ -1,4 +0,0 @@ |
| 4146 | - SELECT COUNT(*) AS "count: i64" FROM messages |
| 4147 | - WHERE |
| 4148 | - list_id = (SELECT list_id FROM lists WHERE list_id = ?) AND |
| 4149 | - in_reply_to IS NULL |
| 4150 | diff --git a/crates/database/queries/mail_thread_summary.sql b/crates/database/queries/mail_thread_summary.sql |
| 4151 | deleted file mode 100644 |
| 4152 | index c76aa55..0000000 |
| 4153 | --- a/crates/database/queries/mail_thread_summary.sql |
| 4154 | +++ /dev/null |
| 4155 | @@ -1,3 +0,0 @@ |
| 4156 | - SELECT messages.* FROM messages |
| 4157 | - LEFT JOIN lists ON lists.id = messages.id |
| 4158 | - WHERE lists.name = ? AND messages.reply_to IS NULL |
| 4159 | diff --git a/crates/database/queries/mail_upsert_participant.sql b/crates/database/queries/mail_upsert_participant.sql |
| 4160 | deleted file mode 100644 |
| 4161 | index 67b0973..0000000 |
| 4162 | --- a/crates/database/queries/mail_upsert_participant.sql |
| 4163 | +++ /dev/null |
| 4164 | @@ -1,6 +0,0 @@ |
| 4165 | - INSERT INTO participants |
| 4166 | - (address, authorized_sender) |
| 4167 | - VALUES (?, ?) |
| 4168 | - ON CONFLICT DO NOTHING; |
| 4169 | - |
| 4170 | - SELECT id FROM participants WHERE address = ? |
| 4171 | diff --git a/crates/database/queries/mail_upsert_subscription.sql b/crates/database/queries/mail_upsert_subscription.sql |
| 4172 | deleted file mode 100644 |
| 4173 | index 78cd886..0000000 |
| 4174 | --- a/crates/database/queries/mail_upsert_subscription.sql |
| 4175 | +++ /dev/null |
| 4176 | @@ -1,6 +0,0 @@ |
| 4177 | - INSERT INTO subscriptions |
| 4178 | - (participant_id, list_id) |
| 4179 | - VALUES ( |
| 4180 | - (SELECT id FROM participants WHERE address = ? LIMIT 1), |
| 4181 | - (SELECT id FROM lists WHERE address = ? LIMIT 1) |
| 4182 | - ) ON CONFLICT DO NOTHING; |
| 4183 | diff --git a/crates/database/queries/manifests_concise.sql b/crates/database/queries/manifests_concise.sql |
| 4184 | deleted file mode 100644 |
| 4185 | index ff04dcf..0000000 |
| 4186 | --- a/crates/database/queries/manifests_concise.sql |
| 4187 | +++ /dev/null |
| 4188 | @@ -1,25 +0,0 @@ |
| 4189 | - WITH params AS ( |
| 4190 | - SELECT |
| 4191 | - ? AS collection, |
| 4192 | - ? AS name, |
| 4193 | - ? AS manifest_id, |
| 4194 | - ? AS git_hash |
| 4195 | - ) |
| 4196 | - SELECT |
| 4197 | - steps.id AS step_id, |
| 4198 | - steps.name AS step_name, |
| 4199 | - workflows.id AS workflow_id, |
| 4200 | - workflows.name AS workflow_name, |
| 4201 | - manifests.id AS manifest_id, |
| 4202 | - steps.exit_code, |
| 4203 | - steps.finished_at |
| 4204 | - FROM steps |
| 4205 | - LEFT JOIN workflows ON workflows.id = steps.workflow_id |
| 4206 | - LEFT JOIN manifests ON manifests.id = workflows.manifest_id |
| 4207 | - WHERE |
| 4208 | - (manifests.collection IS (SELECT collection FROM params) OR (SELECT collection FROM params) IS NULL) |
| 4209 | - AND (manifests.name IS (SELECT name FROM params) OR (SELECT name FROM params) IS NULL) |
| 4210 | - AND (manifests.id IS (SELECT manifest_id FROM params) OR (SELECT manifest_id FROM params) IS NULL) |
| 4211 | - AND (manifests.git_hash IS (SELECT git_hash FROM params) OR (SELECT git_hash FROM params) IS NULL) |
| 4212 | - LIMIT ? |
| 4213 | - OFFSET ? |
| 4214 | diff --git a/crates/database/queries/manifests_create.sql b/crates/database/queries/manifests_create.sql |
| 4215 | deleted file mode 100644 |
| 4216 | index e826336..0000000 |
| 4217 | --- a/crates/database/queries/manifests_create.sql |
| 4218 | +++ /dev/null |
| 4219 | @@ -1,2 +0,0 @@ |
| 4220 | - INSERT INTO manifests (collection, name, git_hash) |
| 4221 | - VALUES (?, ?, ?) RETURNING id |
| 4222 | diff --git a/crates/database/queries/manifests_list.sql b/crates/database/queries/manifests_list.sql |
| 4223 | deleted file mode 100644 |
| 4224 | index 55ea5b1..0000000 |
| 4225 | --- a/crates/database/queries/manifests_list.sql |
| 4226 | +++ /dev/null |
| 4227 | @@ -1,14 +0,0 @@ |
| 4228 | - SELECT id, |
| 4229 | - collection, |
| 4230 | - name, |
| 4231 | - git_hash, |
| 4232 | - created_at, |
| 4233 | - started_at, |
| 4234 | - duration |
| 4235 | - FROM manifests |
| 4236 | - WHERE |
| 4237 | - collection = ? OR collection IS NULL |
| 4238 | - AND name = ? OR name IS NULL |
| 4239 | - AND git_hash = ? OR git_hash IS NULL |
| 4240 | - LIMIT ? |
| 4241 | - OFFSET ? |
| 4242 | diff --git a/crates/database/queries/manifests_read.sql b/crates/database/queries/manifests_read.sql |
| 4243 | deleted file mode 100644 |
| 4244 | index e74b333..0000000 |
| 4245 | --- a/crates/database/queries/manifests_read.sql |
| 4246 | +++ /dev/null |
| 4247 | @@ -1,18 +0,0 @@ |
| 4248 | - WITH params AS ( |
| 4249 | - SELECT |
| 4250 | - ? AS _manifest_id, |
| 4251 | - ? AS _collection, |
| 4252 | - ? AS _name |
| 4253 | - ) |
| 4254 | - SELECT manifests.id, |
| 4255 | - name, |
| 4256 | - collection, |
| 4257 | - git_hash, |
| 4258 | - created_at, |
| 4259 | - started_at, |
| 4260 | - finished_at |
| 4261 | - FROM manifests |
| 4262 | - WHERE |
| 4263 | - manifests.id = (SELECT _manifest_id FROM params) |
| 4264 | - AND (manifests.collection IS (SELECT _collection FROM params) OR (SELECT _collection FROM params) IS NULL) |
| 4265 | - AND (manifests.name IS (SELECT _name FROM params) OR (SELECT _name FROM params) IS NULL) |
| 4266 | diff --git a/crates/database/queries/manifests_update_finish.sql b/crates/database/queries/manifests_update_finish.sql |
| 4267 | deleted file mode 100644 |
| 4268 | index d0a6513..0000000 |
| 4269 | --- a/crates/database/queries/manifests_update_finish.sql |
| 4270 | +++ /dev/null |
| 4271 | @@ -1,4 +0,0 @@ |
| 4272 | - UPDATE manifests |
| 4273 | - SET |
| 4274 | - finished_at = UNIXEPOCH() |
| 4275 | - WHERE id = ? |
| 4276 | diff --git a/crates/database/queries/manifests_update_start.sql b/crates/database/queries/manifests_update_start.sql |
| 4277 | deleted file mode 100644 |
| 4278 | index fc85a4d..0000000 |
| 4279 | --- a/crates/database/queries/manifests_update_start.sql |
| 4280 | +++ /dev/null |
| 4281 | @@ -1,3 +0,0 @@ |
| 4282 | - UPDATE manifests |
| 4283 | - SET started_at = UNIXEPOCH() |
| 4284 | - WHERE id = ? |
| 4285 | diff --git a/crates/database/queries/samples_create.sql b/crates/database/queries/samples_create.sql |
| 4286 | deleted file mode 100644 |
| 4287 | index 7fc297f..0000000 |
| 4288 | --- a/crates/database/queries/samples_create.sql |
| 4289 | +++ /dev/null |
| 4290 | @@ -1,18 +0,0 @@ |
| 4291 | - INSERT INTO samples |
| 4292 | - ( |
| 4293 | - manifest_id, |
| 4294 | - load_1m, |
| 4295 | - load_5m, |
| 4296 | - load_15m, |
| 4297 | - disk_total_bytes, |
| 4298 | - disk_free_bytes, |
| 4299 | - net_sent_bytes, |
| 4300 | - net_received_bytes, |
| 4301 | - net_sent_packets, |
| 4302 | - net_received_packets, |
| 4303 | - mem_total_bytes, |
| 4304 | - mem_free_bytes, |
| 4305 | - mem_available_bytes |
| 4306 | - ) |
| 4307 | - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) |
| 4308 | - RETURNING id |
| 4309 | diff --git a/crates/database/queries/samples_read.sql b/crates/database/queries/samples_read.sql |
| 4310 | deleted file mode 100644 |
| 4311 | index 6842939..0000000 |
| 4312 | --- a/crates/database/queries/samples_read.sql |
| 4313 | +++ /dev/null |
| 4314 | @@ -1,15 +0,0 @@ |
| 4315 | - SELECT id, |
| 4316 | - load_1m, |
| 4317 | - load_5m, |
| 4318 | - load_15m, |
| 4319 | - disk_total_bytes, |
| 4320 | - disk_free_bytes, |
| 4321 | - net_sent_bytes, |
| 4322 | - net_received_bytes, |
| 4323 | - net_sent_packets, |
| 4324 | - net_received_packets, |
| 4325 | - mem_total_bytes, |
| 4326 | - mem_free_bytes, |
| 4327 | - mem_available_bytes |
| 4328 | - FROM samples |
| 4329 | - WHERE manifest_id = ? |
| 4330 | diff --git a/crates/database/queries/steps_create.sql b/crates/database/queries/steps_create.sql |
| 4331 | deleted file mode 100644 |
| 4332 | index ababf23..0000000 |
| 4333 | --- a/crates/database/queries/steps_create.sql |
| 4334 | +++ /dev/null |
| 4335 | @@ -1,2 +0,0 @@ |
| 4336 | - INSERT INTO steps (workflow_id, name, input, shell, environment_json) |
| 4337 | - VALUES (?, ?, ?, ?, json_array(?)) RETURNING id |
| 4338 | diff --git a/crates/database/queries/steps_list.sql b/crates/database/queries/steps_list.sql |
| 4339 | deleted file mode 100644 |
| 4340 | index f3f22d8..0000000 |
| 4341 | --- a/crates/database/queries/steps_list.sql |
| 4342 | +++ /dev/null |
| 4343 | @@ -1,9 +0,0 @@ |
| 4344 | - SELECT id, |
| 4345 | - name, |
| 4346 | - shell, |
| 4347 | - input, |
| 4348 | - started_at, |
| 4349 | - finished_at, |
| 4350 | - exit_code |
| 4351 | - FROM steps |
| 4352 | - WHERE workflow_id = ? |
| 4353 | diff --git a/crates/database/queries/steps_read.sql b/crates/database/queries/steps_read.sql |
| 4354 | deleted file mode 100644 |
| 4355 | index 9228c4d..0000000 |
| 4356 | --- a/crates/database/queries/steps_read.sql |
| 4357 | +++ /dev/null |
| 4358 | @@ -1,9 +0,0 @@ |
| 4359 | - SELECT |
| 4360 | - id, |
| 4361 | - name, |
| 4362 | - shell, |
| 4363 | - input, |
| 4364 | - started_at, |
| 4365 | - finished_at, |
| 4366 | - exit_code |
| 4367 | - FROM steps WHERE id = ? |
| 4368 | diff --git a/crates/database/queries/steps_read_env.sql b/crates/database/queries/steps_read_env.sql |
| 4369 | deleted file mode 100644 |
| 4370 | index 2312f2b..0000000 |
| 4371 | --- a/crates/database/queries/steps_read_env.sql |
| 4372 | +++ /dev/null |
| 4373 | @@ -1 +0,0 @@ |
| 4374 | - SELECT name, value FROM steps_env_vars WHERE step_id = ? |
| 4375 | diff --git a/crates/database/queries/steps_read_log_lines.sql b/crates/database/queries/steps_read_log_lines.sql |
| 4376 | deleted file mode 100644 |
| 4377 | index 5515e25..0000000 |
| 4378 | --- a/crates/database/queries/steps_read_log_lines.sql |
| 4379 | +++ /dev/null |
| 4380 | @@ -1 +0,0 @@ |
| 4381 | - SELECT runtime, stream, line FROM logs WHERE step_id = ? |
| 4382 | diff --git a/crates/database/queries/steps_update_finish.sql b/crates/database/queries/steps_update_finish.sql |
| 4383 | deleted file mode 100644 |
| 4384 | index 5faaf81..0000000 |
| 4385 | --- a/crates/database/queries/steps_update_finish.sql |
| 4386 | +++ /dev/null |
| 4387 | @@ -1,6 +0,0 @@ |
| 4388 | - UPDATE steps |
| 4389 | - SET |
| 4390 | - finished_at = UNIXEPOCH(), |
| 4391 | - exit_code = ? |
| 4392 | - WHERE |
| 4393 | - id = ? |
| 4394 | diff --git a/crates/database/queries/steps_update_log_line.sql b/crates/database/queries/steps_update_log_line.sql |
| 4395 | deleted file mode 100644 |
| 4396 | index 8e3bae0..0000000 |
| 4397 | --- a/crates/database/queries/steps_update_log_line.sql |
| 4398 | +++ /dev/null |
| 4399 | @@ -1,4 +0,0 @@ |
| 4400 | - INSERT INTO logs |
| 4401 | - (step_id, runtime, stream, line) |
| 4402 | - VALUES |
| 4403 | - (?, ?, ?, ?) |
| 4404 | diff --git a/crates/database/queries/steps_update_start.sql b/crates/database/queries/steps_update_start.sql |
| 4405 | deleted file mode 100644 |
| 4406 | index 387654b..0000000 |
| 4407 | --- a/crates/database/queries/steps_update_start.sql |
| 4408 | +++ /dev/null |
| 4409 | @@ -1,5 +0,0 @@ |
| 4410 | - UPDATE steps |
| 4411 | - SET |
| 4412 | - started_at = UNIXEPOCH() |
| 4413 | - WHERE |
| 4414 | - id = ? |
| 4415 | diff --git a/crates/database/queries/workflows_create.sql b/crates/database/queries/workflows_create.sql |
| 4416 | deleted file mode 100644 |
| 4417 | index ac4b392..0000000 |
| 4418 | --- a/crates/database/queries/workflows_create.sql |
| 4419 | +++ /dev/null |
| 4420 | @@ -1,2 +0,0 @@ |
| 4421 | - INSERT INTO workflows (manifest_id, name, image) |
| 4422 | - VALUES (?, ?, ?) RETURNING id |
| 4423 | diff --git a/crates/database/queries/workflows_list.sql b/crates/database/queries/workflows_list.sql |
| 4424 | deleted file mode 100644 |
| 4425 | index 8914be1..0000000 |
| 4426 | --- a/crates/database/queries/workflows_list.sql |
| 4427 | +++ /dev/null |
| 4428 | @@ -1,7 +0,0 @@ |
| 4429 | - SELECT id, |
| 4430 | - name, |
| 4431 | - image, |
| 4432 | - started_at, |
| 4433 | - finished_at |
| 4434 | - FROM workflows |
| 4435 | - WHERE manifest_id = ? |
| 4436 | diff --git a/crates/database/queries/workflows_read.sql b/crates/database/queries/workflows_read.sql |
| 4437 | deleted file mode 100644 |
| 4438 | index 9335ff0..0000000 |
| 4439 | --- a/crates/database/queries/workflows_read.sql |
| 4440 | +++ /dev/null |
| 4441 | @@ -1 +0,0 @@ |
| 4442 | - SELECT id, name, image, started_at, finished_at FROM workflows WHERE id = ? |
| 4443 | diff --git a/crates/database/queries/workflows_update_finish.sql b/crates/database/queries/workflows_update_finish.sql |
| 4444 | deleted file mode 100644 |
| 4445 | index 769a8be..0000000 |
| 4446 | --- a/crates/database/queries/workflows_update_finish.sql |
| 4447 | +++ /dev/null |
| 4448 | @@ -1,5 +0,0 @@ |
| 4449 | - UPDATE workflows |
| 4450 | - SET |
| 4451 | - finished_at = UNIXEPOCH() |
| 4452 | - WHERE |
| 4453 | - id = ? |
| 4454 | diff --git a/crates/database/queries/workflows_update_start.sql b/crates/database/queries/workflows_update_start.sql |
| 4455 | deleted file mode 100644 |
| 4456 | index 11be057..0000000 |
| 4457 | --- a/crates/database/queries/workflows_update_start.sql |
| 4458 | +++ /dev/null |
| 4459 | @@ -1,5 +0,0 @@ |
| 4460 | - UPDATE workflows |
| 4461 | - SET |
| 4462 | - started_at = UNIXEPOCH() |
| 4463 | - WHERE |
| 4464 | - id = ? |
| 4465 | diff --git a/crates/database/src/build.rs b/crates/database/src/build.rs |
| 4466 | index b2fc00f..8823a75 100644 |
| 4467 | --- a/crates/database/src/build.rs |
| 4468 | +++ b/crates/database/src/build.rs |
| 4469 | @@ -1,639 +1,410 @@ |
| 4470 | - use std::{collections::HashMap, fmt::Display, time::Duration}; |
| 4471 | - |
| 4472 | - use async_trait::async_trait; |
| 4473 | + use diesel::{ |
| 4474 | + Associations, BelongingToDsl, Identifiable, Insertable, QueryDsl, Queryable, Selectable, |
| 4475 | + SelectableHelper, deserialize::FromSql, serialize::ToSql, sql_types::Text, sqlite::Sqlite, |
| 4476 | + }; |
| 4477 | use serde::{Deserialize, Serialize}; |
| 4478 | |
| 4479 | - use crate::{Error, Tx, Wrapper as Database}; |
| 4480 | - |
| 4481 | - pub type ConciseStep = (i64, String, Option<bool>); |
| 4482 | - pub type ConciseWorkflow = (i64, String, Vec<ConciseStep>); |
| 4483 | - |
| 4484 | - /// An environment variable |
| 4485 | - pub struct Env((String, Option<String>)); |
| 4486 | - /// Environment Variables |
| 4487 | - pub struct Environment(Vec<Env>); |
| 4488 | - |
| 4489 | - impl From<Environment> for HashMap<String, Option<String>> { |
| 4490 | - fn from(val: Environment) -> Self { |
| 4491 | - let values: Vec<(String, Option<String>)> = val |
| 4492 | - .0 |
| 4493 | - .iter() |
| 4494 | - .map(|env| (env.0.0.clone(), env.0.1.clone())) |
| 4495 | - .collect(); |
| 4496 | - HashMap::from_iter(values) |
| 4497 | - } |
| 4498 | - } |
| 4499 | - |
| 4500 | - // Manifest item with all of it's inner state for quick display |
| 4501 | - #[derive(Clone, Serialize, Deserialize)] |
| 4502 | - pub struct ManifestItem { |
| 4503 | - pub manifest: Manifest, |
| 4504 | - // Present if the manifest job is completed, true if all items within were successful |
| 4505 | - pub success: Option<bool>, |
| 4506 | - // Concise representation of workflows and steps for display in the UI |
| 4507 | - pub workflows: Vec<ConciseWorkflow>, |
| 4508 | - } |
| 4509 | - |
| 4510 | - #[derive(Clone, Serialize, Deserialize)] |
| 4511 | - // everything needed to populate the build status page |
| 4512 | - pub struct ManifestView { |
| 4513 | - pub manifest: Manifest, |
| 4514 | - // pub samples: Vec<Sample>, |
| 4515 | - pub workflows: Vec<(Workflow, Vec<Step>)>, |
| 4516 | - pub dag: Dag, |
| 4517 | - } |
| 4518 | - |
| 4519 | - #[derive(Clone, Default, Serialize, Deserialize)] |
| 4520 | - pub struct Sample { |
| 4521 | - pub id: i64, |
| 4522 | - pub load_1m: Option<i64>, |
| 4523 | - pub load_5m: Option<i64>, |
| 4524 | - pub load_15m: Option<i64>, |
| 4525 | - pub disk_total_bytes: Option<i64>, |
| 4526 | - pub disk_free_bytes: Option<i64>, |
| 4527 | - pub net_sent_bytes: Option<i64>, |
| 4528 | - pub net_received_bytes: Option<i64>, |
| 4529 | - pub net_sent_packets: Option<i64>, |
| 4530 | - pub net_received_packets: Option<i64>, |
| 4531 | - pub mem_total_bytes: Option<i64>, |
| 4532 | - pub mem_free_bytes: Option<i64>, |
| 4533 | - pub mem_available_bytes: Option<i64>, |
| 4534 | - } |
| 4535 | - |
| 4536 | - #[derive(Clone, Serialize, Deserialize)] |
| 4537 | - pub struct Manifest { |
| 4538 | - pub id: i64, |
| 4539 | - pub collection: String, |
| 4540 | - pub name: String, |
| 4541 | - pub git_hash: String, |
| 4542 | - pub created_at: i64, |
| 4543 | - pub started_at: Option<i64>, |
| 4544 | - pub finished_at: Option<i64>, |
| 4545 | - // pub dot_content: String, |
| 4546 | - } |
| 4547 | - |
| 4548 | - impl Manifest { |
| 4549 | - pub fn runtime(&self) -> i64 { |
| 4550 | - self.finished_at |
| 4551 | - .map(|finished_at| finished_at - self.started_at.unwrap_or_default()) |
| 4552 | - .unwrap_or_default() |
| 4553 | - } |
| 4554 | - } |
| 4555 | + // use crate::schema::{dags, logs, manifests, steps, workflows}; |
| 4556 | + use crate::{Error, Ptr}; |
| 4557 | |
| 4558 | - // TODO |
| 4559 | - // |
| 4560 | - #[derive(Debug, Clone, Serialize, Deserialize)] |
| 4561 | - pub struct Workflow { |
| 4562 | - pub id: i64, |
| 4563 | - pub name: String, |
| 4564 | - pub image: String, |
| 4565 | - pub started_at: Option<i64>, |
| 4566 | - pub finished_at: Option<i64>, |
| 4567 | + /// State of a Manifest, Workflow, or Step |
| 4568 | + #[derive(Clone, Copy)] |
| 4569 | + pub enum State { |
| 4570 | + Success, |
| 4571 | + Partial, |
| 4572 | + Fail, |
| 4573 | } |
| 4574 | |
| 4575 | - pub struct WorkflowView { |
| 4576 | - pub workflow: Workflow, |
| 4577 | - pub steps: Vec<Step>, |
| 4578 | - } |
| 4579 | - |
| 4580 | - #[derive(Debug, Clone, Serialize, Deserialize)] |
| 4581 | - pub struct Step { |
| 4582 | - pub id: i64, |
| 4583 | - pub name: String, |
| 4584 | - pub shell: String, |
| 4585 | - pub input: String, |
| 4586 | - pub started_at: Option<i64>, |
| 4587 | - pub finished_at: Option<i64>, |
| 4588 | - pub exit_code: Option<i64>, |
| 4589 | - } |
| 4590 | - |
| 4591 | - #[derive(Clone, Serialize, Deserialize)] |
| 4592 | - pub struct Dag { |
| 4593 | - pub id: i64, |
| 4594 | - pub manifest_id: i64, |
| 4595 | - pub dag_content: String, |
| 4596 | - } |
| 4597 | - |
| 4598 | - /// Used to list manifests from the UI |
| 4599 | - #[derive(Clone)] |
| 4600 | - pub enum Identifier { |
| 4601 | - GitSHA(String), |
| 4602 | - Id(i64), |
| 4603 | - } |
| 4604 | - |
| 4605 | - #[derive(Serialize, Deserialize, Debug, Clone)] |
| 4606 | - pub struct LogLine { |
| 4607 | - pub output: Output, |
| 4608 | - pub runtime: Duration, |
| 4609 | - pub line: String, |
| 4610 | - } |
| 4611 | - |
| 4612 | - /// standard stream when logging output |
| 4613 | - #[derive(Serialize, Deserialize, Debug, Clone)] |
| 4614 | - pub enum Output { |
| 4615 | - Stdout, |
| 4616 | - Stderr, |
| 4617 | - } |
| 4618 | - |
| 4619 | - impl Display for Output { |
| 4620 | - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 4621 | - match self { |
| 4622 | - Output::Stdout => write!(f, "stdout"), |
| 4623 | - Output::Stderr => write!(f, "stderr"), |
| 4624 | + impl FromSql<Text, Sqlite> for State { |
| 4625 | + fn from_sql( |
| 4626 | + mut bytes: <Sqlite as diesel::backend::Backend>::RawValue<'_>, |
| 4627 | + ) -> diesel::deserialize::Result<Self> { |
| 4628 | + match String::from_utf8(bytes.read_blob().to_vec())?.as_str() { |
| 4629 | + "Success" => Ok(State::Success), |
| 4630 | + "Partial" => Ok(State::Partial), |
| 4631 | + "Fail" => Ok(State::Fail), |
| 4632 | + _ => unreachable!(), |
| 4633 | } |
| 4634 | } |
| 4635 | } |
| 4636 | |
| 4637 | - #[async_trait] |
| 4638 | - pub trait BuildTx { |
| 4639 | - async fn create_manifest( |
| 4640 | - &mut self, |
| 4641 | - collection: &str, |
| 4642 | - name: &str, |
| 4643 | - git_hash: &str, |
| 4644 | - ) -> Result<i64, Error>; |
| 4645 | - async fn create_workflow( |
| 4646 | - &mut self, |
| 4647 | - manifest_id: i64, |
| 4648 | - name: &str, |
| 4649 | - image: &str, |
| 4650 | - ) -> Result<i64, Error>; |
| 4651 | - async fn create_step( |
| 4652 | - &mut self, |
| 4653 | - job_id: i64, |
| 4654 | - name: &str, |
| 4655 | - input: &str, |
| 4656 | - shell: &str, |
| 4657 | - environment: HashMap<String, String>, |
| 4658 | - ) -> Result<i64, Error>; |
| 4659 | - async fn create_dag(&mut self, manifest_id: i64, dag_content: &str) -> Result<i64, Error>; |
| 4660 | - } |
| 4661 | - |
| 4662 | - #[async_trait] |
| 4663 | - impl BuildTx for Tx { |
| 4664 | - // manifests |
| 4665 | - async fn create_manifest( |
| 4666 | - &mut self, |
| 4667 | - collection: &str, |
| 4668 | - name: &str, |
| 4669 | - git_hash: &str, |
| 4670 | - ) -> Result<i64, Error> { |
| 4671 | - let ret = sqlx::query_file!("queries/manifests_create.sql", collection, name, git_hash) |
| 4672 | - .fetch_one(&mut *self.inner) |
| 4673 | - .await?; |
| 4674 | - Ok(ret.id) |
| 4675 | + pub mod manifests { |
| 4676 | + |
| 4677 | + use super::*; |
| 4678 | + use crate::schema::manifests::{dsl, table}; |
| 4679 | + use diesel::{ |
| 4680 | + ExpressionMethods, RunQueryDsl, |
| 4681 | + backend::Backend, |
| 4682 | + deserialize::{self, FromSqlRow}, |
| 4683 | + expression::AsExpression, |
| 4684 | + serialize::{self, Output}, |
| 4685 | + sql_types::Integer, |
| 4686 | + }; |
| 4687 | + |
| 4688 | + #[derive(AsExpression, Debug, Clone, Copy, Serialize, Deserialize, FromSqlRow, PartialEq)] |
| 4689 | + #[diesel(sql_type = Integer)] |
| 4690 | + pub enum State { |
| 4691 | + // Stdin = 0 |
| 4692 | + Created = 1, |
| 4693 | + Running = 2, |
| 4694 | + Passed = 3, |
| 4695 | + Failed = 4, |
| 4696 | } |
| 4697 | |
| 4698 | - async fn create_workflow( |
| 4699 | - &mut self, |
| 4700 | - manifest_id: i64, |
| 4701 | - name: &str, |
| 4702 | - image: &str, |
| 4703 | - ) -> Result<i64, Error> { |
| 4704 | - let ret = sqlx::query_file!("queries/workflows_create.sql", manifest_id, name, image) |
| 4705 | - .fetch_one(&mut *self.inner) |
| 4706 | - .await?; |
| 4707 | - Ok(ret.id) |
| 4708 | + impl std::fmt::Display for State { |
| 4709 | + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 4710 | + match self { |
| 4711 | + State::Created => write!(f, "Created"), |
| 4712 | + State::Running => write!(f, "Running"), |
| 4713 | + State::Passed => write!(f, "Passed"), |
| 4714 | + State::Failed => write!(f, "Failed"), |
| 4715 | + } |
| 4716 | + } |
| 4717 | } |
| 4718 | |
| 4719 | - async fn create_step( |
| 4720 | - &mut self, |
| 4721 | - workflow_id: i64, |
| 4722 | - name: &str, |
| 4723 | - input: &str, |
| 4724 | - shell: &str, |
| 4725 | - environment: HashMap<String, String>, |
| 4726 | - ) -> Result<i64, Error> { |
| 4727 | - let environment_json = serde_json::ser::to_string(&environment).unwrap(); |
| 4728 | - let ret = sqlx::query_file!( |
| 4729 | - "queries/steps_create.sql", |
| 4730 | - workflow_id, |
| 4731 | - name, |
| 4732 | - input, |
| 4733 | - shell, |
| 4734 | - environment_json |
| 4735 | - ) |
| 4736 | - .fetch_one(&mut *self.inner) |
| 4737 | - .await?; |
| 4738 | - Ok(ret.id) |
| 4739 | + impl<DB> FromSql<Integer, DB> for State |
| 4740 | + where |
| 4741 | + DB: Backend, |
| 4742 | + i32: FromSql<Integer, DB>, |
| 4743 | + { |
| 4744 | + fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> { |
| 4745 | + match i32::from_sql(bytes)? { |
| 4746 | + 1 => Ok(State::Created), |
| 4747 | + 2 => Ok(State::Running), |
| 4748 | + 3 => Ok(State::Passed), |
| 4749 | + 4 => Ok(State::Failed), |
| 4750 | + x => Err(format!("Unrecognized variant {}", x).into()), |
| 4751 | + } |
| 4752 | + } |
| 4753 | } |
| 4754 | |
| 4755 | - async fn create_dag(&mut self, manifest_id: i64, dag_content: &str) -> Result<i64, Error> { |
| 4756 | - let ret = sqlx::query_file!("queries/dags_create.sql", manifest_id, dag_content) |
| 4757 | - .fetch_one(&mut *self.inner) |
| 4758 | - .await?; |
| 4759 | - Ok(ret.id) |
| 4760 | + impl<DB> ToSql<Integer, DB> for State |
| 4761 | + where |
| 4762 | + DB: Backend, |
| 4763 | + i32: ToSql<Integer, DB>, |
| 4764 | + { |
| 4765 | + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result { |
| 4766 | + match *self { |
| 4767 | + State::Created => 1_i32.to_sql(out), |
| 4768 | + State::Running => 2_i32.to_sql(out), |
| 4769 | + State::Passed => 3_i32.to_sql(out), |
| 4770 | + State::Failed => 4_i32.to_sql(out), |
| 4771 | + } |
| 4772 | + } |
| 4773 | } |
| 4774 | - } |
| 4775 | |
| 4776 | - #[async_trait] |
| 4777 | - pub trait BuildExt { |
| 4778 | - // manifests |
| 4779 | - async fn create_manifest( |
| 4780 | - &self, |
| 4781 | - collection: &str, |
| 4782 | - name: &str, |
| 4783 | - git_hash: &str, |
| 4784 | - ) -> Result<i64, Error>; |
| 4785 | - async fn update_manifest_start(&self, manifest_id: i64) -> Result<(), Error>; |
| 4786 | - async fn update_manifest_finish(&self, manifest_id: i64) -> Result<(), Error>; |
| 4787 | - async fn list_manifest( |
| 4788 | - &self, |
| 4789 | - collection: Option<&str>, |
| 4790 | - name: Option<&str>, |
| 4791 | - filter: Option<&Identifier>, |
| 4792 | - limit: i64, |
| 4793 | - offset: i64, |
| 4794 | - ) -> Result<Vec<ManifestItem>, Error>; |
| 4795 | - async fn read_manifest( |
| 4796 | - &self, |
| 4797 | - collection: &str, |
| 4798 | - name: &str, |
| 4799 | - manifest_id: i64, |
| 4800 | - ) -> Result<ManifestView, Error>; |
| 4801 | - |
| 4802 | - // workflows |
| 4803 | - async fn create_workflow( |
| 4804 | - &self, |
| 4805 | - manifest_id: i64, |
| 4806 | - name: &str, |
| 4807 | - image: &str, |
| 4808 | - ) -> Result<i64, Error>; |
| 4809 | - async fn update_workflow_start(&self, workflow_id: i64) -> Result<(), Error>; |
| 4810 | - async fn update_workflow_finish(&self, workflow_id: i64) -> Result<(), Error>; |
| 4811 | - async fn read_workflow(&self, workflow_id: i64) -> Result<Workflow, Error>; |
| 4812 | - async fn read_workflow_view(&self, workflow_id: i64) -> Result<WorkflowView, Error>; |
| 4813 | - // steps |
| 4814 | - async fn create_step( |
| 4815 | - &self, |
| 4816 | - job_id: i64, |
| 4817 | - name: &str, |
| 4818 | - input: &str, |
| 4819 | - shell: &str, |
| 4820 | - environment: HashMap<String, String>, |
| 4821 | - ) -> Result<i64, Error>; |
| 4822 | - async fn read_step(&self, step_id: i64) -> Result<Step, Error>; |
| 4823 | - async fn read_step_env(&self, step_id: i64) -> Result<Environment, Error>; |
| 4824 | - async fn update_step_start(&self, step_id: i64) -> Result<(), Error>; |
| 4825 | - async fn update_step_finish( |
| 4826 | - &self, |
| 4827 | - step_id: i64, |
| 4828 | - lines: &[LogLine], |
| 4829 | - exit_code: i8, |
| 4830 | - ) -> Result<(), Error>; |
| 4831 | - async fn read_log_lines(&self, step_id: i64) -> Result<Vec<LogLine>, Error>; |
| 4832 | - |
| 4833 | - // misc |
| 4834 | - async fn create_sample(&self, manifest_id: i64, sample: Sample) -> Result<i64, Error>; |
| 4835 | - async fn read_dag(&self, manifest_id: i64) -> Result<Dag, Error>; |
| 4836 | - } |
| 4837 | - |
| 4838 | - #[async_trait] |
| 4839 | - impl BuildExt for Database { |
| 4840 | - // manifests |
| 4841 | - async fn create_manifest( |
| 4842 | - &self, |
| 4843 | - collection: &str, |
| 4844 | - name: &str, |
| 4845 | - git_hash: &str, |
| 4846 | - ) -> Result<i64, Error> { |
| 4847 | - let ret = sqlx::query_file!("queries/manifests_create.sql", collection, name, git_hash) |
| 4848 | - .fetch_one(&self.pool) |
| 4849 | - .await?; |
| 4850 | - Ok(ret.id) |
| 4851 | + #[derive(Clone, Debug, Serialize, Deserialize)] |
| 4852 | + pub struct Summary { |
| 4853 | + pub manifest: Manifest, |
| 4854 | + pub workflows: Vec<(super::workflows::Workflow, Vec<super::steps::Step>)>, |
| 4855 | } |
| 4856 | |
| 4857 | - async fn update_manifest_start(&self, manifest_id: i64) -> Result<(), Error> { |
| 4858 | - sqlx::query_file!("queries/manifests_update_start.sql", manifest_id,) |
| 4859 | - .execute(&self.pool) |
| 4860 | - .await?; |
| 4861 | - Ok(()) |
| 4862 | + #[derive( |
| 4863 | + Clone, Debug, Deserialize, Serialize, Queryable, Selectable, PartialEq, Identifiable, |
| 4864 | + )] |
| 4865 | + #[diesel(table_name = crate::schema::manifests)] |
| 4866 | + #[diesel(check_for_backend(Sqlite))] |
| 4867 | + pub struct Manifest { |
| 4868 | + pub id: i32, |
| 4869 | + pub collection: String, |
| 4870 | + pub name: String, |
| 4871 | + pub git_hash: String, |
| 4872 | + pub state: State, |
| 4873 | + pub created_at: i32, |
| 4874 | + pub dag_content: Option<String>, |
| 4875 | + pub started_at: Option<i32>, |
| 4876 | + pub finished_at: Option<i32>, |
| 4877 | } |
| 4878 | |
| 4879 | - async fn update_manifest_finish(&self, manifest_id: i64) -> Result<(), Error> { |
| 4880 | - sqlx::query_file!("queries/manifests_update_finish.sql", manifest_id) |
| 4881 | - .execute(&self.pool) |
| 4882 | - .await?; |
| 4883 | - Ok(()) |
| 4884 | - } |
| 4885 | + impl Ptr<'_> { |
| 4886 | + pub fn manifest_create( |
| 4887 | + &mut self, |
| 4888 | + collection: &str, |
| 4889 | + name: &str, |
| 4890 | + git_hash: &str, |
| 4891 | + ) -> Result<i32, Error> { |
| 4892 | + diesel::insert_into(table) |
| 4893 | + .values(( |
| 4894 | + dsl::collection.eq(collection), |
| 4895 | + dsl::name.eq(name), |
| 4896 | + dsl::git_hash.eq(git_hash), |
| 4897 | + )) |
| 4898 | + .returning(dsl::id) |
| 4899 | + .get_result(self.0) |
| 4900 | + } |
| 4901 | |
| 4902 | - async fn list_manifest( |
| 4903 | - &self, |
| 4904 | - collection: Option<&str>, |
| 4905 | - name: Option<&str>, |
| 4906 | - filter: Option<&Identifier>, |
| 4907 | - limit: i64, |
| 4908 | - offset: i64, |
| 4909 | - ) -> Result<Vec<ManifestItem>, Error> { |
| 4910 | - let (manifest_id, git_hash) = match filter { |
| 4911 | - Some(Identifier::GitSHA(gitsha)) => (None, Some(gitsha.clone())), |
| 4912 | - Some(Identifier::Id(manifest_id)) => (Some(manifest_id.to_string()), None), |
| 4913 | - None => (None, None), |
| 4914 | - }; |
| 4915 | - let records = sqlx::query_file!( |
| 4916 | - "queries/manifests_concise.sql", |
| 4917 | - collection, |
| 4918 | - name, |
| 4919 | - manifest_id, |
| 4920 | - git_hash, |
| 4921 | - limit, |
| 4922 | - offset |
| 4923 | - ) |
| 4924 | - .fetch_all(&self.pool) |
| 4925 | - .await?; |
| 4926 | - let invocations: HashMap<i64, HashMap<i64, (String, Vec<ConciseStep>)>> = |
| 4927 | - records.iter().fold(HashMap::new(), |mut mapped, record| { |
| 4928 | - match mapped.get_mut(&record.manifest_id) { |
| 4929 | - Some(workflow) => match workflow.get_mut(&record.workflow_id) { |
| 4930 | - Some(steps) => steps.1.push(( |
| 4931 | - record.step_id, |
| 4932 | - record.step_name.clone(), |
| 4933 | - record.exit_code.map(|code| code == 0), |
| 4934 | - )), |
| 4935 | - None => { |
| 4936 | - workflow.insert( |
| 4937 | - record.workflow_id, |
| 4938 | - ( |
| 4939 | - record.workflow_name.clone().unwrap_or_default(), |
| 4940 | - vec![( |
| 4941 | - record.step_id, |
| 4942 | - record.step_name.clone(), |
| 4943 | - record.exit_code.map(|code| code == 0), |
| 4944 | - )], |
| 4945 | - ), |
| 4946 | - ); |
| 4947 | - } |
| 4948 | - }, |
| 4949 | - None => { |
| 4950 | - let workflow: HashMap<i64, (String, Vec<ConciseStep>)> = HashMap::from([( |
| 4951 | - record.workflow_id, |
| 4952 | - ( |
| 4953 | - record.workflow_name.clone().unwrap_or_default(), |
| 4954 | - vec![( |
| 4955 | - record.step_id, |
| 4956 | - record.step_name.clone(), |
| 4957 | - record.exit_code.map(|code| code == 0), |
| 4958 | - )], |
| 4959 | - ), |
| 4960 | - )]); |
| 4961 | - mapped.insert(record.manifest_id, workflow); |
| 4962 | - } |
| 4963 | - }; |
| 4964 | - mapped |
| 4965 | - }); |
| 4966 | - |
| 4967 | - let mut as_ordered_vec: Vec<(i64, Vec<ConciseWorkflow>)> = |
| 4968 | - invocations |
| 4969 | - .iter() |
| 4970 | - .fold(Vec::new(), |mut accm, (manifest_id, workflows)| { |
| 4971 | - let mut workflows: Vec<ConciseWorkflow> = workflows.iter().fold( |
| 4972 | - Vec::new(), |
| 4973 | - |mut wf_accm, (workflow_id, (workflow_name, steps))| { |
| 4974 | - wf_accm.push((*workflow_id, workflow_name.clone(), steps.clone())); |
| 4975 | - wf_accm |
| 4976 | - }, |
| 4977 | - ); |
| 4978 | - workflows.sort_by(|first, second| first.0.cmp(&second.0)); |
| 4979 | - accm.push((*manifest_id, workflows)); |
| 4980 | - accm |
| 4981 | - }); |
| 4982 | - |
| 4983 | - as_ordered_vec.sort_by(|first, second| first.0.cmp(&second.0)); |
| 4984 | - |
| 4985 | - let mut items: Vec<ManifestItem> = Vec::new(); |
| 4986 | - for (manifest_id, workflows) in as_ordered_vec { |
| 4987 | - let manifest = sqlx::query_file_as!( |
| 4988 | - Manifest, |
| 4989 | - "queries/manifests_read.sql", |
| 4990 | - manifest_id, |
| 4991 | - None::<String>, |
| 4992 | - None::<String> |
| 4993 | - ) |
| 4994 | - .fetch_one(&self.pool) |
| 4995 | - .await?; |
| 4996 | - let success = workflows |
| 4997 | - .iter() |
| 4998 | - .all(|(_, _, steps)| steps.iter().all(|(_, _, success)| success.is_some())) |
| 4999 | - .then(|| { |
| 5000 | - workflows.iter().all(|(_, _, steps)| { |
| 5001 | - steps |
| 5002 | - .iter() |
| 5003 | - .all(|(_, _, success)| success.is_some_and(|success| success)) |
| 5004 | - }) |
| 5005 | - }); |
| 5006 | - |
| 5007 | - items.push(ManifestItem { |
| 5008 | + pub fn manifest_summary(&mut self, id: i32) -> Result<Summary, Error> { |
| 5009 | + let manifest = table |
| 5010 | + .filter(manifests::dsl::id.eq(id)) |
| 5011 | + .select(Manifest::as_select()) |
| 5012 | + .get_result(self.0)?; |
| 5013 | + let workflows = super::workflows::Workflow::belonging_to(&manifest) |
| 5014 | + .select(super::workflows::Workflow::as_select()) |
| 5015 | + .load(self.0)?; |
| 5016 | + let workflows: Vec<(super::workflows::Workflow, Vec<super::steps::Step>)> = workflows |
| 5017 | + .into_iter() |
| 5018 | + .try_fold(Vec::new(), |mut workflows, workflow| { |
| 5019 | + let steps = super::steps::Step::belonging_to(&workflow) |
| 5020 | + .select(super::steps::Step::as_select()) |
| 5021 | + .load(self.0)?; |
| 5022 | + workflows.push((workflow, steps)); |
| 5023 | + Ok::<_, Error>(workflows) |
| 5024 | + })?; |
| 5025 | + Ok(Summary { |
| 5026 | manifest, |
| 5027 | - success, |
| 5028 | workflows, |
| 5029 | - }); |
| 5030 | + }) |
| 5031 | } |
| 5032 | - items.sort_by(|first, second| second.manifest.id.cmp(&first.manifest.id)); |
| 5033 | - Ok(items) |
| 5034 | - } |
| 5035 | |
| 5036 | - async fn read_manifest( |
| 5037 | - &self, |
| 5038 | - collection: &str, |
| 5039 | - name: &str, |
| 5040 | - manifest_id: i64, |
| 5041 | - ) -> Result<ManifestView, Error> { |
| 5042 | - let manifest = sqlx::query_file_as!( |
| 5043 | - Manifest, |
| 5044 | - "queries/manifests_read.sql", |
| 5045 | - manifest_id, |
| 5046 | - collection, |
| 5047 | - name |
| 5048 | - ) |
| 5049 | - .fetch_one(&self.pool) |
| 5050 | - .await?; |
| 5051 | - let dag = sqlx::query_file_as!(Dag, "queries/dags_read.sql", manifest_id) |
| 5052 | - .fetch_one(&self.pool) |
| 5053 | - .await?; |
| 5054 | - let mut normalized = ManifestView { |
| 5055 | - manifest, |
| 5056 | - workflows: Vec::default(), |
| 5057 | - dag, |
| 5058 | - }; |
| 5059 | - let workflows = sqlx::query_file_as!(Workflow, "queries/workflows_list.sql", manifest_id) |
| 5060 | - .fetch_all(&self.pool) |
| 5061 | - .await?; |
| 5062 | - for workflow in workflows { |
| 5063 | - let steps = sqlx::query_file_as!(Step, "queries/steps_list.sql", workflow.id) |
| 5064 | - .fetch_all(&self.pool) |
| 5065 | - .await?; |
| 5066 | - normalized.workflows.push((workflow, steps)); |
| 5067 | + pub fn manifest_list( |
| 5068 | + &mut self, |
| 5069 | + collection: &str, |
| 5070 | + name: &str, |
| 5071 | + ) -> Result<Vec<Manifest>, Error> { |
| 5072 | + table |
| 5073 | + .select(Manifest::as_select()) |
| 5074 | + .filter(dsl::collection.eq(collection)) |
| 5075 | + .filter(dsl::name.eq(name)) |
| 5076 | + .load(self.0) |
| 5077 | } |
| 5078 | - Ok(normalized) |
| 5079 | - } |
| 5080 | |
| 5081 | - // workflows |
| 5082 | + pub fn manifest_set_dag_content( |
| 5083 | + &mut self, |
| 5084 | + id: i32, |
| 5085 | + dag_content: &str, |
| 5086 | + ) -> Result<(), Error> { |
| 5087 | + diesel::update(table) |
| 5088 | + .filter(dsl::id.eq(id)) |
| 5089 | + .set(dsl::dag_content.eq(dag_content)) |
| 5090 | + .execute(self.0)?; |
| 5091 | + Ok(()) |
| 5092 | + } |
| 5093 | |
| 5094 | - async fn read_workflow(&self, workflow_id: i64) -> Result<Workflow, Error> { |
| 5095 | - let workflow = sqlx::query_file_as!(Workflow, "queries/workflows_read.sql", workflow_id) |
| 5096 | - .fetch_one(&self.pool) |
| 5097 | - .await?; |
| 5098 | - Ok(workflow) |
| 5099 | - } |
| 5100 | + pub fn manifest_start(&mut self, id: i32) -> Result<(), Error> { |
| 5101 | + diesel::update(table) |
| 5102 | + .filter(dsl::id.eq(id)) |
| 5103 | + .set(dsl::started_at.eq(timeutil::epoch_secs() as i32)) |
| 5104 | + .execute(self.0)?; |
| 5105 | + Ok(()) |
| 5106 | + } |
| 5107 | |
| 5108 | - async fn read_workflow_view(&self, workflow_id: i64) -> Result<WorkflowView, Error> { |
| 5109 | - let workflow = sqlx::query_file_as!(Workflow, "queries/workflows_read.sql", workflow_id) |
| 5110 | - .fetch_one(&self.pool) |
| 5111 | - .await?; |
| 5112 | - let steps = sqlx::query_file_as!(Step, "queries/steps_list.sql", workflow_id) |
| 5113 | - .fetch_all(&self.pool) |
| 5114 | - .await?; |
| 5115 | - Ok(WorkflowView { workflow, steps }) |
| 5116 | + pub fn manifest_end(&mut self, id: i32) -> Result<(), Error> { |
| 5117 | + diesel::update(table) |
| 5118 | + .filter(dsl::id.eq(id)) |
| 5119 | + .set(dsl::finished_at.eq(timeutil::epoch_secs() as i32)) |
| 5120 | + .execute(self.0)?; |
| 5121 | + Ok(()) |
| 5122 | + } |
| 5123 | } |
| 5124 | + } |
| 5125 | |
| 5126 | - async fn create_workflow( |
| 5127 | - &self, |
| 5128 | - manifest_id: i64, |
| 5129 | - name: &str, |
| 5130 | - image: &str, |
| 5131 | - ) -> Result<i64, Error> { |
| 5132 | - let ret = sqlx::query_file!("queries/workflows_create.sql", manifest_id, name, image) |
| 5133 | - .fetch_one(&self.pool) |
| 5134 | - .await?; |
| 5135 | - Ok(ret.id) |
| 5136 | + pub mod workflows { |
| 5137 | + use super::*; |
| 5138 | + use crate::schema::workflows::{dsl, table}; |
| 5139 | + use diesel::{ExpressionMethods, RunQueryDsl}; |
| 5140 | + |
| 5141 | + #[derive(Insertable)] |
| 5142 | + #[diesel(table_name = crate::schema::workflows)] |
| 5143 | + pub struct CreateWorkflowArgs<'a> { |
| 5144 | + pub manifest_id: i32, |
| 5145 | + pub name: &'a str, |
| 5146 | + pub image: &'a str, |
| 5147 | } |
| 5148 | |
| 5149 | - async fn update_workflow_start(&self, workflow_id: i64) -> Result<(), Error> { |
| 5150 | - sqlx::query_file!("queries/workflows_update_start.sql", workflow_id,) |
| 5151 | - .execute(&self.pool) |
| 5152 | - .await?; |
| 5153 | - Ok(()) |
| 5154 | + #[derive( |
| 5155 | + Clone, Debug, Serialize, Deserialize, Queryable, Identifiable, Selectable, Associations, |
| 5156 | + )] |
| 5157 | + #[diesel(table_name = crate::schema::workflows)] |
| 5158 | + #[diesel(belongs_to(super::manifests::Manifest))] |
| 5159 | + pub struct Workflow { |
| 5160 | + pub id: i32, |
| 5161 | + pub manifest_id: i32, |
| 5162 | + pub name: String, |
| 5163 | + pub image: String, |
| 5164 | + pub started_at: Option<i32>, |
| 5165 | + pub finished_at: Option<i32>, |
| 5166 | } |
| 5167 | |
| 5168 | - async fn update_workflow_finish(&self, workflow_id: i64) -> Result<(), Error> { |
| 5169 | - sqlx::query_file!("queries/workflows_update_finish.sql", workflow_id) |
| 5170 | - .execute(&self.pool) |
| 5171 | - .await?; |
| 5172 | - Ok(()) |
| 5173 | + impl Ptr<'_> { |
| 5174 | + pub fn workflow_create(&mut self, args: &CreateWorkflowArgs) -> Result<i32, Error> { |
| 5175 | + diesel::insert_into(table) |
| 5176 | + .values(args) |
| 5177 | + .returning(dsl::id) |
| 5178 | + .get_result(self.0) |
| 5179 | + } |
| 5180 | + |
| 5181 | + pub fn workflow_read(&mut self, workflow_id: i32) -> Result<Workflow, Error> { |
| 5182 | + table |
| 5183 | + .select(Workflow::as_select()) |
| 5184 | + .filter(dsl::id.eq(workflow_id)) |
| 5185 | + .first::<Workflow>(self.0) |
| 5186 | + } |
| 5187 | + |
| 5188 | + pub fn workflow_start(&mut self, workflow_id: i32) -> Result<(), Error> { |
| 5189 | + diesel::update(table) |
| 5190 | + .filter(dsl::id.eq(workflow_id)) |
| 5191 | + .set(dsl::started_at.eq(timeutil::epoch_secs() as i32)) |
| 5192 | + .execute(self.0)?; |
| 5193 | + Ok(()) |
| 5194 | + } |
| 5195 | + pub fn workflow_finish(&mut self, workflow_id: i32) -> Result<(), Error> { |
| 5196 | + diesel::update(table) |
| 5197 | + .filter(dsl::id.eq(workflow_id)) |
| 5198 | + .set(dsl::finished_at.eq(timeutil::epoch_secs() as i32)) |
| 5199 | + .execute(self.0)?; |
| 5200 | + Ok(()) |
| 5201 | + } |
| 5202 | } |
| 5203 | + } |
| 5204 | |
| 5205 | - // steps |
| 5206 | - |
| 5207 | - async fn create_step( |
| 5208 | - &self, |
| 5209 | - workflow_id: i64, |
| 5210 | - name: &str, |
| 5211 | - input: &str, |
| 5212 | - shell: &str, |
| 5213 | - environment: HashMap<String, String>, |
| 5214 | - ) -> Result<i64, Error> { |
| 5215 | - let environment_json = serde_json::ser::to_string(&environment).unwrap(); |
| 5216 | - let ret = sqlx::query_file!( |
| 5217 | - "queries/steps_create.sql", |
| 5218 | - workflow_id, |
| 5219 | - name, |
| 5220 | - input, |
| 5221 | - shell, |
| 5222 | - environment_json |
| 5223 | - ) |
| 5224 | - .fetch_one(&self.pool) |
| 5225 | - .await?; |
| 5226 | - Ok(ret.id) |
| 5227 | + pub mod steps { |
| 5228 | + use super::*; |
| 5229 | + use crate::schema::steps::{dsl, table}; |
| 5230 | + use diesel::{ExpressionMethods, RunQueryDsl}; |
| 5231 | + |
| 5232 | + #[derive(Insertable)] |
| 5233 | + #[diesel(table_name = crate::schema::steps)] |
| 5234 | + pub struct CreateStepArgs<'a> { |
| 5235 | + pub workflow_id: i32, |
| 5236 | + pub name: &'a str, |
| 5237 | + pub shell: &'a str, |
| 5238 | + pub input: &'a str, |
| 5239 | } |
| 5240 | |
| 5241 | - async fn read_step(&self, step_id: i64) -> Result<Step, Error> { |
| 5242 | - sqlx::query_file_as!(Step, "queries/steps_read.sql", step_id) |
| 5243 | - .fetch_one(&self.pool) |
| 5244 | - .await |
| 5245 | + #[derive( |
| 5246 | + Clone, Debug, Serialize, Deserialize, Queryable, Identifiable, Associations, Selectable, |
| 5247 | + )] |
| 5248 | + #[diesel(table_name = crate::schema::steps)] |
| 5249 | + #[diesel(belongs_to(super::workflows::Workflow))] |
| 5250 | + pub struct Step { |
| 5251 | + pub id: i32, |
| 5252 | + pub workflow_id: i32, |
| 5253 | + pub name: String, |
| 5254 | + pub shell: String, |
| 5255 | + pub input: String, |
| 5256 | + pub environment_json: Option<String>, |
| 5257 | + pub exit_code: Option<i32>, |
| 5258 | + pub started_at: Option<i32>, |
| 5259 | + pub finished_at: Option<i32>, |
| 5260 | } |
| 5261 | |
| 5262 | - async fn read_step_env(&self, step_id: i64) -> Result<Environment, Error> { |
| 5263 | - let rows = sqlx::query_file!("queries/steps_read_env.sql", step_id) |
| 5264 | - .fetch_all(&self.pool) |
| 5265 | - .await?; |
| 5266 | + impl Ptr<'_> { |
| 5267 | + pub fn step_create(&mut self, args: &CreateStepArgs) -> Result<i32, Error> { |
| 5268 | + diesel::insert_into(table) |
| 5269 | + .values(args) |
| 5270 | + .returning(dsl::id) |
| 5271 | + .get_result(self.0) |
| 5272 | + } |
| 5273 | + |
| 5274 | + pub fn step_read(&mut self, id: i32) -> Result<Step, Error> { |
| 5275 | + table |
| 5276 | + .select(Step::as_select()) |
| 5277 | + .filter(dsl::id.eq(id)) |
| 5278 | + .first::<Step>(self.0) |
| 5279 | + } |
| 5280 | |
| 5281 | - let envs: Vec<Env> = rows |
| 5282 | - .iter() |
| 5283 | - .map(|record| Env((record.name.clone(), record.value.clone()))) |
| 5284 | - .collect(); |
| 5285 | + pub fn step_start(&mut self, id: i32) -> Result<(), Error> { |
| 5286 | + diesel::update(table) |
| 5287 | + .filter(dsl::id.eq(id)) |
| 5288 | + .set(dsl::started_at.eq(timeutil::epoch_secs() as i32)) |
| 5289 | + .execute(self.0)?; |
| 5290 | + Ok(()) |
| 5291 | + } |
| 5292 | |
| 5293 | - Ok(Environment(envs)) |
| 5294 | + pub fn step_finish(&mut self, id: i32, exit_code: i32) -> Result<(), Error> { |
| 5295 | + diesel::update(table) |
| 5296 | + .filter(dsl::id.eq(id)) |
| 5297 | + .set(( |
| 5298 | + dsl::finished_at.eq(timeutil::epoch_secs() as i32), |
| 5299 | + dsl::exit_code.eq(exit_code), |
| 5300 | + )) |
| 5301 | + .execute(self.0)?; |
| 5302 | + Ok(()) |
| 5303 | + } |
| 5304 | } |
| 5305 | + } |
| 5306 | |
| 5307 | - async fn update_step_start(&self, step_id: i64) -> Result<(), Error> { |
| 5308 | - sqlx::query_file!("queries/steps_update_start.sql", step_id) |
| 5309 | - .execute(&self.pool) |
| 5310 | - .await?; |
| 5311 | - Ok(()) |
| 5312 | + pub mod logs { |
| 5313 | + use super::*; |
| 5314 | + use crate::schema::logs::{dsl, table}; |
| 5315 | + use diesel::{ |
| 5316 | + ExpressionMethods, RunQueryDsl, |
| 5317 | + backend::Backend, |
| 5318 | + deserialize::{self, FromSqlRow}, |
| 5319 | + expression::AsExpression, |
| 5320 | + serialize::{self, Output}, |
| 5321 | + sql_types::Integer, |
| 5322 | + }; |
| 5323 | + |
| 5324 | + #[derive(AsExpression, Debug, Clone, Copy, Serialize, Deserialize, FromSqlRow)] |
| 5325 | + #[diesel(sql_type = Integer)] |
| 5326 | + pub enum Stream { |
| 5327 | + // Stdin = 0 |
| 5328 | + Stdout = 1, |
| 5329 | + Stderr = 2, |
| 5330 | } |
| 5331 | |
| 5332 | - async fn update_step_finish( |
| 5333 | - &self, |
| 5334 | - step_id: i64, |
| 5335 | - logs: &[LogLine], |
| 5336 | - exit_code: i8, |
| 5337 | - ) -> Result<(), Error> { |
| 5338 | - sqlx::query_file!("queries/steps_update_finish.sql", exit_code, step_id) |
| 5339 | - .execute(&self.pool) |
| 5340 | - .await?; |
| 5341 | - for log_line in logs { |
| 5342 | - let runtime_ms = log_line.runtime.as_millis() as i64; |
| 5343 | - let output = log_line.output.to_string(); |
| 5344 | - let line = log_line.line.clone(); |
| 5345 | - sqlx::query_file!( |
| 5346 | - "queries/steps_update_log_line.sql", |
| 5347 | - step_id, |
| 5348 | - runtime_ms, |
| 5349 | - output, |
| 5350 | - line, |
| 5351 | - ) |
| 5352 | - .execute(&self.pool) |
| 5353 | - .await?; |
| 5354 | + impl<DB> FromSql<Integer, DB> for Stream |
| 5355 | + where |
| 5356 | + DB: Backend, |
| 5357 | + i32: FromSql<Integer, DB>, |
| 5358 | + { |
| 5359 | + fn from_sql(bytes: DB::RawValue<'_>) -> deserialize::Result<Self> { |
| 5360 | + match i32::from_sql(bytes)? { |
| 5361 | + 1 => Ok(Stream::Stdout), |
| 5362 | + 2 => Ok(Stream::Stderr), |
| 5363 | + x => Err(format!("Unrecognized variant {}", x).into()), |
| 5364 | + } |
| 5365 | } |
| 5366 | + } |
| 5367 | |
| 5368 | - Ok(()) |
| 5369 | + impl<DB> ToSql<Integer, DB> for Stream |
| 5370 | + where |
| 5371 | + DB: Backend, |
| 5372 | + i32: ToSql<Integer, DB>, |
| 5373 | + { |
| 5374 | + fn to_sql<'b>(&'b self, out: &mut Output<'b, '_, DB>) -> serialize::Result { |
| 5375 | + match *self { |
| 5376 | + Stream::Stdout => 1_i32.to_sql(out), |
| 5377 | + Stream::Stderr => 2_i32.to_sql(out), |
| 5378 | + } |
| 5379 | + } |
| 5380 | } |
| 5381 | |
| 5382 | - async fn read_log_lines(&self, step_id: i64) -> Result<Vec<LogLine>, Error> { |
| 5383 | - let records = sqlx::query_file!("queries/steps_read_log_lines.sql", step_id) |
| 5384 | - .fetch_all(&self.pool) |
| 5385 | - .await?; |
| 5386 | - Ok(records |
| 5387 | - .into_iter() |
| 5388 | - .map(|record| LogLine { |
| 5389 | - output: match record.stream.as_str() { |
| 5390 | - "stdout" => Output::Stdout, |
| 5391 | - "stderr" => Output::Stderr, |
| 5392 | - other => unimplemented!("Unknown stream: {other}"), |
| 5393 | - }, |
| 5394 | - runtime: Duration::from_millis(record.runtime as u64), |
| 5395 | - line: record.line.unwrap_or_default(), |
| 5396 | - }) |
| 5397 | - .collect()) |
| 5398 | + #[derive(Insertable)] |
| 5399 | + #[diesel(table_name = crate::schema::logs)] |
| 5400 | + pub struct WriteLineArgs<'a> { |
| 5401 | + pub step_id: i32, |
| 5402 | + pub stream: Stream, |
| 5403 | + pub line: &'a str, |
| 5404 | } |
| 5405 | |
| 5406 | - // misc |
| 5407 | - |
| 5408 | - async fn create_sample(&self, manifest_id: i64, sample: Sample) -> Result<i64, Error> { |
| 5409 | - let ret = sqlx::query_file!( |
| 5410 | - "queries/samples_create.sql", |
| 5411 | - manifest_id, |
| 5412 | - sample.load_1m, |
| 5413 | - sample.load_5m, |
| 5414 | - sample.load_15m, |
| 5415 | - sample.disk_total_bytes, |
| 5416 | - sample.disk_free_bytes, |
| 5417 | - sample.net_sent_bytes, |
| 5418 | - sample.net_received_bytes, |
| 5419 | - sample.net_sent_packets, |
| 5420 | - sample.net_received_packets, |
| 5421 | - sample.mem_total_bytes, |
| 5422 | - sample.mem_free_bytes, |
| 5423 | - sample.mem_available_bytes, |
| 5424 | - ) |
| 5425 | - .fetch_one(&self.pool) |
| 5426 | - .await?; |
| 5427 | - Ok(ret.id) |
| 5428 | + #[derive( |
| 5429 | + Clone, Debug, Serialize, Deserialize, Queryable, Identifiable, Associations, Selectable, |
| 5430 | + )] |
| 5431 | + #[diesel(table_name = crate::schema::logs)] |
| 5432 | + #[diesel(belongs_to(super::steps::Step))] |
| 5433 | + pub struct Line { |
| 5434 | + pub id: i32, |
| 5435 | + pub step_id: i32, |
| 5436 | + pub timestamp: i32, |
| 5437 | + pub stream: Stream, |
| 5438 | + pub line: String, |
| 5439 | } |
| 5440 | |
| 5441 | - async fn read_dag(&self, manifest_id: i64) -> Result<Dag, Error> { |
| 5442 | - sqlx::query_file_as!(Dag, "queries/dags_read.sql", manifest_id) |
| 5443 | - .fetch_one(&self.pool) |
| 5444 | - .await |
| 5445 | + impl Ptr<'_> { |
| 5446 | + pub fn log_write_line(&mut self, args: &WriteLineArgs) -> Result<i32, Error> { |
| 5447 | + diesel::insert_into(table) |
| 5448 | + .values((args, dsl::timestamp.eq(timeutil::epoch_secs() as i32))) // FIXME should be offset from start of step |
| 5449 | + .returning(dsl::id) |
| 5450 | + .get_result(self.0) |
| 5451 | + } |
| 5452 | + |
| 5453 | + pub fn log_read(&mut self, step_id: i32, _offset: Option<i32>) -> Result<Vec<Line>, Error> { |
| 5454 | + table |
| 5455 | + .select(Line::as_select()) |
| 5456 | + .filter(dsl::step_id.eq(step_id)) |
| 5457 | + .load(self.0) |
| 5458 | + } |
| 5459 | } |
| 5460 | } |
| 5461 | diff --git a/crates/database/src/contributors.rs b/crates/database/src/contributors.rs |
| 5462 | deleted file mode 100644 |
| 5463 | index ca44e2b..0000000 |
| 5464 | --- a/crates/database/src/contributors.rs |
| 5465 | +++ /dev/null |
| 5466 | @@ -1,101 +0,0 @@ |
| 5467 | - use futures::TryStreamExt; |
| 5468 | - use serde::{Deserialize, Serialize}; |
| 5469 | - use sqlx::Error; |
| 5470 | - use time::OffsetDateTime; |
| 5471 | - |
| 5472 | - use crate::Wrapper; |
| 5473 | - |
| 5474 | - #[derive(Clone, Serialize, Deserialize)] |
| 5475 | - pub struct AuthorWithStats { |
| 5476 | - pub username: Option<String>, |
| 5477 | - pub email: Option<String>, |
| 5478 | - pub count: Option<i64>, |
| 5479 | - pub lines_added: Option<i64>, |
| 5480 | - pub lines_removed: Option<i64>, |
| 5481 | - pub percentage: Option<f64>, |
| 5482 | - } |
| 5483 | - |
| 5484 | - pub struct Database<'a>(pub &'a Wrapper); |
| 5485 | - |
| 5486 | - impl Database<'_> { |
| 5487 | - pub async fn upsert_author(&self, name: &str, email: &str) -> Result<i64, Error> { |
| 5488 | - let ret = sqlx::query_file!("../../queries/authors_upsert.sql", name, email) |
| 5489 | - .fetch_one(&self.0.pool) |
| 5490 | - .await?; |
| 5491 | - Ok(ret.id) |
| 5492 | - } |
| 5493 | - |
| 5494 | - pub async fn authors_list( |
| 5495 | - &self, |
| 5496 | - repo_path: &str, |
| 5497 | - git_hash: &str, |
| 5498 | - ) -> Result<Vec<AuthorWithStats>, Error> { |
| 5499 | - sqlx::query_file_as!( |
| 5500 | - AuthorWithStats, |
| 5501 | - "../../queries/authors_list_project.sql", |
| 5502 | - git_hash, |
| 5503 | - repo_path, |
| 5504 | - repo_path, |
| 5505 | - repo_path, |
| 5506 | - ) |
| 5507 | - .fetch_all(&self.0.pool) |
| 5508 | - .await |
| 5509 | - } |
| 5510 | - |
| 5511 | - pub async fn contribution_add( |
| 5512 | - &self, |
| 5513 | - author_id: i64, |
| 5514 | - repo_path: &str, |
| 5515 | - git_hash: &str, |
| 5516 | - timestamp: OffsetDateTime, |
| 5517 | - lines_added: i64, |
| 5518 | - lines_removed: i64, |
| 5519 | - ) -> Result<(), Error> { |
| 5520 | - sqlx::query_file!( |
| 5521 | - "../../queries/contributions_add.sql", |
| 5522 | - author_id, |
| 5523 | - git_hash, |
| 5524 | - repo_path, |
| 5525 | - timestamp, |
| 5526 | - lines_added, |
| 5527 | - lines_removed |
| 5528 | - ) |
| 5529 | - .execute(&self.0.pool) |
| 5530 | - .await? |
| 5531 | - .last_insert_rowid(); |
| 5532 | - sqlx::query_file!( |
| 5533 | - "../../queries/contribution_add.sql", |
| 5534 | - author_id, |
| 5535 | - repo_path, |
| 5536 | - git_hash, |
| 5537 | - repo_path, |
| 5538 | - author_id, |
| 5539 | - ) |
| 5540 | - .execute(&self.0.pool) |
| 5541 | - .await?; |
| 5542 | - |
| 5543 | - Ok(()) |
| 5544 | - } |
| 5545 | - |
| 5546 | - pub async fn contributors_list( |
| 5547 | - &self, |
| 5548 | - repo_path: &str, |
| 5549 | - git_hash: &str, |
| 5550 | - ) -> Result<Vec<(String, String, i64)>, Error> { |
| 5551 | - let mut ret: Vec<(String, String, i64)> = Vec::new(); |
| 5552 | - let mut rows = sqlx::query_file!( |
| 5553 | - "../../queries/contributions_list.sql", |
| 5554 | - repo_path, |
| 5555 | - git_hash, |
| 5556 | - repo_path, |
| 5557 | - repo_path, |
| 5558 | - git_hash, |
| 5559 | - repo_path, |
| 5560 | - ) |
| 5561 | - .fetch(&self.0.pool); |
| 5562 | - while let Some(row) = rows.try_next().await? { |
| 5563 | - ret.push((row.name.unwrap(), row.email.unwrap(), row.percentage)) |
| 5564 | - } |
| 5565 | - Ok(ret) |
| 5566 | - } |
| 5567 | - } |
| 5568 | diff --git a/crates/database/src/jobs.rs b/crates/database/src/jobs.rs |
| 5569 | deleted file mode 100644 |
| 5570 | index 9e3cbcf..0000000 |
| 5571 | --- a/crates/database/src/jobs.rs |
| 5572 | +++ /dev/null |
| 5573 | @@ -1,101 +0,0 @@ |
| 5574 | - use sqlx::Error; |
| 5575 | - use time::OffsetDateTime; |
| 5576 | - |
| 5577 | - use crate::Wrapper; |
| 5578 | - |
| 5579 | - #[derive(Clone)] |
| 5580 | - pub struct Job { |
| 5581 | - pub id: i64, |
| 5582 | - pub created_at: OffsetDateTime, |
| 5583 | - pub repo_path: String, |
| 5584 | - pub kind: String, |
| 5585 | - pub runtime: Option<u32>, |
| 5586 | - pub success: Option<bool>, |
| 5587 | - pub commits: i32, |
| 5588 | - } |
| 5589 | - |
| 5590 | - pub struct Database<'a>(pub &'a Wrapper); |
| 5591 | - |
| 5592 | - impl Database<'_> { |
| 5593 | - pub async fn create_job(&self, repo_path: Option<&str>, kind: &str) -> Result<i64, Error> { |
| 5594 | - let created_at = OffsetDateTime::now_utc(); |
| 5595 | - let ret = sqlx::query_file!("../../queries/jobs_create.sql", created_at, repo_path, kind,) |
| 5596 | - .fetch_one(&self.0.pool) |
| 5597 | - .await?; |
| 5598 | - Ok(ret.id) |
| 5599 | - } |
| 5600 | - |
| 5601 | - pub async fn update_job(&self, job_id: i64, runtime: i64, success: bool) -> Result<(), Error> { |
| 5602 | - sqlx::query_file!("../../queries/jobs_update.sql", runtime, success, job_id) |
| 5603 | - .execute(&self.0.pool) |
| 5604 | - .await?; |
| 5605 | - Ok(()) |
| 5606 | - } |
| 5607 | - |
| 5608 | - pub async fn list_jobs(&self, repo_path: Option<&str>) -> Result<Vec<Job>, Error> { |
| 5609 | - let jobs = sqlx::query_file_as!(Job, "../../queries/jobs_list.sql", repo_path, repo_path) |
| 5610 | - .fetch_all(&self.0.pool) |
| 5611 | - .await?; |
| 5612 | - Ok(jobs) |
| 5613 | - } |
| 5614 | - |
| 5615 | - pub async fn delete_job(&self, job_id: i64) -> Result<(), Error> { |
| 5616 | - sqlx::query_file_as!(Job, "../../queries/jobs_delete.sql", job_id) |
| 5617 | - .execute(&self.0.pool) |
| 5618 | - .await?; |
| 5619 | - Ok(()) |
| 5620 | - } |
| 5621 | - |
| 5622 | - pub async fn purge(&self, repo_path: &str) -> Result<(), Error> { |
| 5623 | - sqlx::query_file!("../../queries/job_tracking_delete_by_repo.sql", repo_path) |
| 5624 | - .execute(&self.0.pool) |
| 5625 | - .await?; |
| 5626 | - sqlx::query_file!("../../queries/jobs_delete.sql", repo_path) |
| 5627 | - .execute(&self.0.pool) |
| 5628 | - .await?; |
| 5629 | - sqlx::query_file!("../../queries/languages_delete.sql", repo_path) |
| 5630 | - .execute(&self.0.pool) |
| 5631 | - .await?; |
| 5632 | - sqlx::query_file!("../../queries/contribution_delete.sql", repo_path) |
| 5633 | - .execute(&self.0.pool) |
| 5634 | - .await?; |
| 5635 | - sqlx::query_file!("../../queries/contributions_delete.sql", repo_path) |
| 5636 | - .execute(&self.0.pool) |
| 5637 | - .await?; |
| 5638 | - Ok(()) |
| 5639 | - } |
| 5640 | - |
| 5641 | - pub async fn create_hash( |
| 5642 | - &self, |
| 5643 | - repo_path: &str, |
| 5644 | - git_hash: &str, |
| 5645 | - kind: &str, |
| 5646 | - job_id: i64, |
| 5647 | - ) -> Result<(), Error> { |
| 5648 | - sqlx::query_file!( |
| 5649 | - "../../queries/job_tracking_add.sql", |
| 5650 | - repo_path, |
| 5651 | - git_hash, |
| 5652 | - kind, |
| 5653 | - job_id |
| 5654 | - ) |
| 5655 | - .execute(&self.0.pool) |
| 5656 | - .await?; |
| 5657 | - Ok(()) |
| 5658 | - } |
| 5659 | - |
| 5660 | - // lookup the latest hash for the job kind |
| 5661 | - pub async fn read_hash(&self, repo_path: &str, kind: &str) -> Result<Option<String>, Error> { |
| 5662 | - let ret = sqlx::query_file!("../../queries/job_tracking_read.sql", repo_path, kind,) |
| 5663 | - .fetch_optional(&self.0.pool) |
| 5664 | - .await?; |
| 5665 | - Ok(ret.map(|record| record.git_hash)) |
| 5666 | - } |
| 5667 | - |
| 5668 | - pub async fn latest_commit(&self, repo_path: &str) -> Result<Option<String>, Error> { |
| 5669 | - let ret = sqlx::query_file!("../../queries/latest_commit.sql", repo_path) |
| 5670 | - .fetch_optional(&self.0.pool) |
| 5671 | - .await?; |
| 5672 | - Ok(ret.map(|record| record.git_hash)) |
| 5673 | - } |
| 5674 | - } |
| 5675 | diff --git a/crates/database/src/languages.rs b/crates/database/src/languages.rs |
| 5676 | deleted file mode 100644 |
| 5677 | index d730069..0000000 |
| 5678 | --- a/crates/database/src/languages.rs |
| 5679 | +++ /dev/null |
| 5680 | @@ -1,52 +0,0 @@ |
| 5681 | - use futures::TryStreamExt; |
| 5682 | - use sqlx::Error; |
| 5683 | - |
| 5684 | - use crate::Wrapper; |
| 5685 | - |
| 5686 | - pub struct Database<'a>(pub &'a Wrapper); |
| 5687 | - |
| 5688 | - impl Database<'_> { |
| 5689 | - pub async fn language_create( |
| 5690 | - &self, |
| 5691 | - repo_path: &str, |
| 5692 | - git_hash: &str, |
| 5693 | - languages: Vec<(String, i64)>, |
| 5694 | - ) -> Result<(), Error> { |
| 5695 | - for language in languages { |
| 5696 | - sqlx::query_file!( |
| 5697 | - "../../queries/languages_add.sql", |
| 5698 | - git_hash, |
| 5699 | - repo_path, |
| 5700 | - language.0, |
| 5701 | - language.1, |
| 5702 | - ) |
| 5703 | - .execute(&self.0.pool) |
| 5704 | - .await?; |
| 5705 | - } |
| 5706 | - Ok(()) |
| 5707 | - } |
| 5708 | - |
| 5709 | - pub async fn languages_list( |
| 5710 | - &self, |
| 5711 | - repo_path: &str, |
| 5712 | - git_hash: &str, |
| 5713 | - ) -> Result<Vec<(String, u8, u32)>, Error> { |
| 5714 | - let mut languages: Vec<(String, u8, u32)> = Vec::new(); |
| 5715 | - let mut rows = sqlx::query_file!( |
| 5716 | - "../../queries/languages_list.sql", |
| 5717 | - repo_path, |
| 5718 | - git_hash, |
| 5719 | - repo_path, |
| 5720 | - git_hash |
| 5721 | - ) |
| 5722 | - .fetch(&self.0.pool); |
| 5723 | - while let Some(row) = rows.try_next().await? { |
| 5724 | - languages.push(( |
| 5725 | - row.language.clone(), |
| 5726 | - row.percentage.unwrap_or(0.0) as u8, |
| 5727 | - row.loc as u32, |
| 5728 | - )); |
| 5729 | - } |
| 5730 | - Ok(languages) |
| 5731 | - } |
| 5732 | - } |
| 5733 | diff --git a/crates/database/src/lib.rs b/crates/database/src/lib.rs |
| 5734 | index 2e3329f..b2561f6 100644 |
| 5735 | --- a/crates/database/src/lib.rs |
| 5736 | +++ b/crates/database/src/lib.rs |
| 5737 | @@ -1,143 +1,81 @@ |
| 5738 | - use std::fs::create_dir_all; |
| 5739 | - use std::path::{Path, PathBuf}; |
| 5740 | + use std::path::Path; |
| 5741 | |
| 5742 | - use sqlx::ConnectOptions; |
| 5743 | - use sqlx::migrate::Migrator; |
| 5744 | - use sqlx::sqlite::{SqliteConnectOptions, SqliteLockingMode, SqlitePool, SqlitePoolOptions}; |
| 5745 | - use sqlx::{Error as SqlxError, Sqlite, Transaction}; |
| 5746 | - use tracing::log; |
| 5747 | - |
| 5748 | - // pub mod contributors; |
| 5749 | - // pub mod jobs; |
| 5750 | - // pub mod languages; |
| 5751 | - // pub mod mail; |
| 5752 | - // pub mod stats; |
| 5753 | + use diesel::{Connection, SqliteConnection}; |
| 5754 | + use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; |
| 5755 | |
| 5756 | pub mod build; |
| 5757 | + pub mod schema; |
| 5758 | |
| 5759 | - pub type Error = SqlxError; |
| 5760 | + pub use diesel::result::Error; |
| 5761 | |
| 5762 | - pub async fn migrate(path: &str, migrations: &str) -> Result<(), Error> { |
| 5763 | - if let Some(path) = Path::new(path).parent() { |
| 5764 | - create_dir_all(path)? |
| 5765 | - } |
| 5766 | - log::info!("running migrations"); |
| 5767 | - let opts = SqliteConnectOptions::new() |
| 5768 | - .filename(path) |
| 5769 | - .create_if_missing(true); |
| 5770 | - let pool = SqlitePool::connect_with(opts).await?; |
| 5771 | - Migrator::new(Path::new(migrations)) |
| 5772 | - .await? |
| 5773 | - .run(&pool) |
| 5774 | - .await?; |
| 5775 | - Ok(()) |
| 5776 | - } |
| 5777 | + const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); |
| 5778 | |
| 5779 | - #[derive(Default)] |
| 5780 | - pub struct Builder { |
| 5781 | - pub url: Option<String>, |
| 5782 | - pub read_only: bool, |
| 5783 | - pub log_queries: bool, |
| 5784 | - pub migrations: Option<PathBuf>, |
| 5785 | + #[derive(Debug, thiserror::Error)] |
| 5786 | + pub enum MigrationError { |
| 5787 | + #[error("SQLite Connection Failed: {0}")] |
| 5788 | + Connection(#[from] diesel::ConnectionError), |
| 5789 | + #[error("Migration failed: {0}")] |
| 5790 | + Migration(String), |
| 5791 | } |
| 5792 | |
| 5793 | - impl Builder { |
| 5794 | - pub fn path(mut self, path: &Path) -> Self { |
| 5795 | - self.url = Some(path.to_str().unwrap().to_string()); |
| 5796 | - self |
| 5797 | - } |
| 5798 | - |
| 5799 | - pub fn read_only(mut self, read_only: bool) -> Self { |
| 5800 | - self.read_only = read_only; |
| 5801 | - self |
| 5802 | - } |
| 5803 | - |
| 5804 | - pub fn log_queries(mut self, log_queries: bool) -> Self { |
| 5805 | - self.log_queries = log_queries; |
| 5806 | - self |
| 5807 | - } |
| 5808 | - |
| 5809 | - pub fn migrations(mut self, path: &Path) -> Self { |
| 5810 | - self.migrations = Some(path.to_path_buf()); |
| 5811 | - self |
| 5812 | - } |
| 5813 | - |
| 5814 | - pub async fn build(self) -> Result<Wrapper, Error> { |
| 5815 | - let log_level = if self.log_queries { |
| 5816 | - // don't log queries when the global logger is at level INFO |
| 5817 | - log::LevelFilter::Info |
| 5818 | - } else { |
| 5819 | - log::LevelFilter::Debug |
| 5820 | - }; |
| 5821 | - |
| 5822 | - let mut pool_opts = SqlitePoolOptions::new(); |
| 5823 | - // TODO: set read-only for main web serving mode |
| 5824 | - let mut opts = SqliteConnectOptions::new() |
| 5825 | - .log_statements(log_level) |
| 5826 | - // TODO |
| 5827 | - .serialized(true) |
| 5828 | - // .read_only(read_only) |
| 5829 | - .create_if_missing(true); |
| 5830 | - match self.url { |
| 5831 | - Some(url) => { |
| 5832 | - opts = opts.filename(url); |
| 5833 | - } |
| 5834 | - None => { |
| 5835 | - // no path will automatically place SQLite in :memory: mode |
| 5836 | - // this code path is only for testing. See |
| 5837 | - // https://github.com/launchbadge/sqlx/issues/362 for details. |
| 5838 | - log::warn!("SQLite is configured for debugging"); |
| 5839 | - pool_opts = pool_opts |
| 5840 | - .max_connections(1) |
| 5841 | - .idle_timeout(None) |
| 5842 | - .max_lifetime(None); |
| 5843 | - } |
| 5844 | - } |
| 5845 | + fn connect(connection_url: &Path, read_only: bool) -> Result<SqliteConnection, MigrationError> { |
| 5846 | + let as_str = format!( |
| 5847 | + "file://{}{}", |
| 5848 | + connection_url.to_string_lossy(), |
| 5849 | + if read_only { "?mode=ro" } else { "" } |
| 5850 | + ); |
| 5851 | + tracing::info!("Connecting to SQLite with connection string: {as_str}"); |
| 5852 | + let conn = SqliteConnection::establish(&as_str)?; |
| 5853 | + Ok(conn) |
| 5854 | + } |
| 5855 | |
| 5856 | - if self.read_only { |
| 5857 | - opts = opts.read_only(true) |
| 5858 | - } else { |
| 5859 | - opts = opts.locking_mode(SqliteLockingMode::Normal) |
| 5860 | - } |
| 5861 | - let pool = pool_opts.connect_with(opts).await?; |
| 5862 | - if let Some(migrations_path) = self.migrations { |
| 5863 | - log::info!("running migrations"); |
| 5864 | - Migrator::new(Path::new(&migrations_path)) |
| 5865 | - .await? |
| 5866 | - .run(&pool) |
| 5867 | - .await? |
| 5868 | - } |
| 5869 | - Ok(Wrapper { pool }) |
| 5870 | + /// Apply all pending migrations. |
| 5871 | + /// TODO: Once Ayllu reaches 1.0 we can make this more flexible. |
| 5872 | + pub fn migrate(connection_url: &Path) -> Result<(), MigrationError> { |
| 5873 | + let mut conn = connect(connection_url, false)?; |
| 5874 | + for migration in conn |
| 5875 | + .pending_migrations(MIGRATIONS) |
| 5876 | + .map_err(|e| MigrationError::Migration(e.to_string()))? |
| 5877 | + { |
| 5878 | + tracing::info!("Applying migration {}", migration.name()); |
| 5879 | + let version = conn |
| 5880 | + .run_migration(&migration) |
| 5881 | + .map_err(|e| MigrationError::Migration(e.to_string()))?; |
| 5882 | + tracing::info!("Success: {}", version); |
| 5883 | } |
| 5884 | + Ok(()) |
| 5885 | } |
| 5886 | |
| 5887 | - pub struct Tx { |
| 5888 | - inner: Transaction<'static, Sqlite>, |
| 5889 | + pub struct Ptr<'a>(&'a mut SqliteConnection); |
| 5890 | + |
| 5891 | + pub struct Wrapper { |
| 5892 | + conn: SqliteConnection, |
| 5893 | } |
| 5894 | |
| 5895 | - impl Tx { |
| 5896 | - pub async fn commit(self) -> Result<(), Error> { |
| 5897 | - self.inner.commit().await |
| 5898 | + impl Wrapper { |
| 5899 | + pub fn new(path: &Path) -> Result<Self, MigrationError> { |
| 5900 | + Ok(Self { |
| 5901 | + conn: connect(path, false)?, |
| 5902 | + }) |
| 5903 | } |
| 5904 | |
| 5905 | - pub async fn rollback(self) -> Result<(), Error> { |
| 5906 | - self.inner.rollback().await |
| 5907 | + pub fn new_ro(path: &Path) -> Result<Self, MigrationError> { |
| 5908 | + Ok(Self { |
| 5909 | + conn: connect(path, true)?, |
| 5910 | + }) |
| 5911 | } |
| 5912 | - } |
| 5913 | |
| 5914 | - #[derive(Clone, Debug)] |
| 5915 | - pub struct Wrapper { |
| 5916 | - pub pool: SqlitePool, |
| 5917 | - } |
| 5918 | - |
| 5919 | - impl Wrapper { |
| 5920 | - pub async fn begin(&self) -> Result<Tx, Error> { |
| 5921 | - let inner = self.pool.begin().await?; |
| 5922 | - Ok(Tx { inner }) |
| 5923 | + /// Get a synchronous connection to the database |
| 5924 | + pub fn call<'a>(&'a mut self) -> Ptr<'a> { |
| 5925 | + Ptr(&mut self.conn) |
| 5926 | } |
| 5927 | |
| 5928 | - pub async fn close(&self) -> Result<(), Error> { |
| 5929 | - self.pool.close().await; |
| 5930 | - Ok(()) |
| 5931 | + /// Execute the closure in a transaction |
| 5932 | + pub fn with<F, T, E>(&mut self, f: F) -> Result<T, E> |
| 5933 | + where |
| 5934 | + E: From<diesel::result::Error>, |
| 5935 | + F: FnOnce(Ptr) -> Result<T, E>, |
| 5936 | + { |
| 5937 | + self.conn.transaction(move |conn| f(Ptr(conn))) |
| 5938 | } |
| 5939 | } |
| 5940 | diff --git a/crates/database/src/mail.rs b/crates/database/src/mail.rs |
| 5941 | deleted file mode 100644 |
| 5942 | index 8b15da9..0000000 |
| 5943 | --- a/crates/database/src/mail.rs |
| 5944 | +++ /dev/null |
| 5945 | @@ -1,280 +0,0 @@ |
| 5946 | - use std::fmt::Display; |
| 5947 | - |
| 5948 | - use serde::{Deserialize, Serialize}; |
| 5949 | - use sqlx::{QueryBuilder, Sqlite}; |
| 5950 | - |
| 5951 | - use crate::Error; |
| 5952 | - use crate::Wrapper; |
| 5953 | - |
| 5954 | - /// RFC2919 List-Id |
| 5955 | - /// List-Id: List Header Mailing List <list-header.nisto.com> |
| 5956 | - /// (Description, Address) |
| 5957 | - #[derive(Clone, Default)] |
| 5958 | - pub struct ListId(pub String, pub String); |
| 5959 | - |
| 5960 | - impl Display for ListId { |
| 5961 | - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
| 5962 | - write!(f, "{} <{}>", self.0, self.1) |
| 5963 | - } |
| 5964 | - } |
| 5965 | - |
| 5966 | - #[derive(Clone, Default, Serialize, Deserialize)] |
| 5967 | - pub struct List { |
| 5968 | - pub name: String, |
| 5969 | - pub address: String, |
| 5970 | - pub enabled: bool, |
| 5971 | - pub description: Option<String>, |
| 5972 | - } |
| 5973 | - |
| 5974 | - #[derive(Clone, Default, Serialize, Deserialize)] |
| 5975 | - pub struct Participant { |
| 5976 | - pub address: String, |
| 5977 | - pub name: String, |
| 5978 | - pub authorized_sender: bool, |
| 5979 | - pub subscriptions: Option<Vec<String>>, |
| 5980 | - } |
| 5981 | - |
| 5982 | - #[derive(Clone, Default, Serialize, Deserialize)] |
| 5983 | - pub struct Message { |
| 5984 | - pub id: i64, |
| 5985 | - pub message_id: String, |
| 5986 | - pub list_id: i64, |
| 5987 | - pub in_reply_to: Option<String>, |
| 5988 | - pub subject: Option<String>, |
| 5989 | - pub mail_from: i64, |
| 5990 | - pub raw_message: Option<Vec<u8>>, |
| 5991 | - pub content_body: Option<String>, |
| 5992 | - pub reply_count: i64, |
| 5993 | - } |
| 5994 | - |
| 5995 | - #[derive(Clone, Default, Serialize, Deserialize)] |
| 5996 | - pub struct ThreadMessage { |
| 5997 | - pub message_id: String, |
| 5998 | - pub in_reply_to: Option<String>, |
| 5999 | - pub subject: Option<String>, |
| 6000 | - pub mail_from: String, |
| 6001 | - pub raw_message: Option<Vec<u8>>, |
| 6002 | - pub content_body: Option<String>, |
| 6003 | - pub reply_count: i64, |
| 6004 | - pub depth: i64, |
| 6005 | - } |
| 6006 | - |
| 6007 | - impl Message { |
| 6008 | - pub fn is_patch(&self) -> bool { |
| 6009 | - todo!() |
| 6010 | - } |
| 6011 | - } |
| 6012 | - |
| 6013 | - #[derive(Clone, Default, Serialize, Deserialize)] |
| 6014 | - pub struct ThreadSummary { |
| 6015 | - pub message_id: String, |
| 6016 | - pub mail_from: String, |
| 6017 | - pub subject: Option<String>, |
| 6018 | - pub reply_count: i64, |
| 6019 | - } |
| 6020 | - |
| 6021 | - pub struct DeliveryParams<'a> { |
| 6022 | - pub message_id: &'a str, |
| 6023 | - pub mail_to: &'a [&'a str], |
| 6024 | - pub mail_from: &'a str, |
| 6025 | - pub subject: Option<&'a str>, |
| 6026 | - pub raw_message: &'a [u8], |
| 6027 | - pub content_body: &'a str, |
| 6028 | - pub in_reply_to: Option<&'a str>, |
| 6029 | - } |
| 6030 | - |
| 6031 | - #[derive(Clone)] |
| 6032 | - pub struct OutgoingMessage { |
| 6033 | - pub id: i64, |
| 6034 | - pub message_id: String, |
| 6035 | - pub list_name: String, |
| 6036 | - pub address: String, |
| 6037 | - pub raw_message: Option<Vec<u8>>, |
| 6038 | - } |
| 6039 | - |
| 6040 | - pub enum DeliveryError { |
| 6041 | - // TODO |
| 6042 | - Generic(String), |
| 6043 | - } |
| 6044 | - |
| 6045 | - impl DeliveryError { |
| 6046 | - pub fn kind(&self) -> String { |
| 6047 | - match self { |
| 6048 | - DeliveryError::Generic(_) => String::from("Generic"), |
| 6049 | - } |
| 6050 | - } |
| 6051 | - } |
| 6052 | - |
| 6053 | - pub struct Database<'a>(pub &'a Wrapper); |
| 6054 | - |
| 6055 | - impl Database<'_> { |
| 6056 | - pub async fn setup( |
| 6057 | - &self, |
| 6058 | - lists: Vec<List>, |
| 6059 | - participants: Option<Vec<Participant>>, |
| 6060 | - ) -> Result<(), Error> { |
| 6061 | - let mut tx = self.0.pool.begin().await?; |
| 6062 | - tracing::info!("Deactivating any unused mailing lists"); |
| 6063 | - let addresses: Vec<String> = lists.iter().map(|list| list.name.clone()).collect(); |
| 6064 | - // NOTE: Macros cannot construct WHERE address IN ($) so we have |
| 6065 | - // to build it by hand. |
| 6066 | - // See this note: |
| 6067 | - // https://github.com/launchbadge/sqlx/blob/main/FAQ.md#how-can-i-do-a-select--where-foo-in--query |
| 6068 | - let mut query: QueryBuilder<Sqlite> = |
| 6069 | - QueryBuilder::new("UPDATE lists SET enabled = 0 WHERE address NOT IN"); |
| 6070 | - let update_query = query.push_tuples(addresses, |mut array, value| { |
| 6071 | - array.push_bind(value.clone()); |
| 6072 | - }); |
| 6073 | - update_query.build().execute(&mut *tx).await?; |
| 6074 | - for list in lists.iter() { |
| 6075 | - tracing::info!("Updating mailing list {}", list.address); |
| 6076 | - sqlx::query_file!( |
| 6077 | - "../../queries/mail_list_create.sql", |
| 6078 | - list.name, |
| 6079 | - list.address, |
| 6080 | - list.description, |
| 6081 | - list.enabled, |
| 6082 | - list.name, |
| 6083 | - list.description, |
| 6084 | - list.enabled, |
| 6085 | - ) |
| 6086 | - .execute(&mut *tx) |
| 6087 | - .await?; |
| 6088 | - } |
| 6089 | - if let Some(participants) = participants.as_ref() { |
| 6090 | - for participant in participants.iter() { |
| 6091 | - tracing::info!("Updating participant: {}", participant.address); |
| 6092 | - sqlx::query_file!( |
| 6093 | - "../../queries/mail_upsert_participant.sql", |
| 6094 | - participant.address, |
| 6095 | - participant.authorized_sender, |
| 6096 | - participant.address, |
| 6097 | - ) |
| 6098 | - .fetch_one(&mut *tx) |
| 6099 | - .await?; |
| 6100 | - if let Some(subscriptions) = &participant.subscriptions { |
| 6101 | - for subscription in subscriptions { |
| 6102 | - // FIXME declarative |
| 6103 | - tracing::info!("Creating subscription: {}", subscription); |
| 6104 | - sqlx::query_file!( |
| 6105 | - "../../queries/mail_upsert_subscription.sql", |
| 6106 | - participant.address, |
| 6107 | - subscription |
| 6108 | - ) |
| 6109 | - .execute(&mut *tx) |
| 6110 | - .await?; |
| 6111 | - } |
| 6112 | - }; |
| 6113 | - } |
| 6114 | - } |
| 6115 | - tx.commit().await?; |
| 6116 | - Ok(()) |
| 6117 | - } |
| 6118 | - |
| 6119 | - pub async fn deliver(&self, params: &DeliveryParams<'_>) -> Result<Vec<i64>, Error> { |
| 6120 | - let mut tx = self.0.pool.begin().await?; |
| 6121 | - let participant_id = sqlx::query_file!( |
| 6122 | - "../../queries/mail_upsert_participant.sql", |
| 6123 | - params.mail_from, |
| 6124 | - false, |
| 6125 | - params.mail_from |
| 6126 | - ) |
| 6127 | - .fetch_one(&mut *tx) |
| 6128 | - .await? |
| 6129 | - .id; |
| 6130 | - let mut message_ids: Vec<i64> = Vec::new(); |
| 6131 | - for mail_to_addr in params.mail_to.iter() { |
| 6132 | - let ret = sqlx::query_file!( |
| 6133 | - "../../queries/mail_deliver_message.sql", |
| 6134 | - params.message_id, |
| 6135 | - mail_to_addr, |
| 6136 | - params.in_reply_to, |
| 6137 | - params.subject, |
| 6138 | - participant_id, |
| 6139 | - params.content_body, |
| 6140 | - params.raw_message, |
| 6141 | - ) |
| 6142 | - .fetch_one(&mut *tx) |
| 6143 | - .await?; |
| 6144 | - message_ids.push(ret.id.unwrap()) |
| 6145 | - } |
| 6146 | - tx.commit().await?; |
| 6147 | - // TODO Lookup all subscribers and place new messages in an outbound |
| 6148 | - // queue. |
| 6149 | - Ok(message_ids) |
| 6150 | - } |
| 6151 | - |
| 6152 | - pub async fn has_message(&self, message_id: &str) -> Result<bool, Error> { |
| 6153 | - let rec = sqlx::query_file!("../../queries/mail_has_message.sql", message_id) |
| 6154 | - .fetch_one(&self.0.pool) |
| 6155 | - .await?; |
| 6156 | - Ok(rec.has_message) |
| 6157 | - } |
| 6158 | - |
| 6159 | - pub async fn thread_count(&self, list_id: &ListId) -> Result<i64, Error> { |
| 6160 | - let rec = sqlx::query_file!("../../queries/mail_thread_count.sql", list_id.1) |
| 6161 | - .fetch_one(&self.0.pool) |
| 6162 | - .await?; |
| 6163 | - Ok(rec.count) |
| 6164 | - } |
| 6165 | - |
| 6166 | - // pub async fn read_message(&self, list_id: &ListId, message_id: &str) -> Result<Message, Error> { |
| 6167 | - // todo!() |
| 6168 | - // } |
| 6169 | - |
| 6170 | - pub async fn read_thread( |
| 6171 | - &self, |
| 6172 | - _list_id: &ListId, // FIXME |
| 6173 | - message_id: &str, |
| 6174 | - ) -> Result<Vec<ThreadMessage>, Error> { |
| 6175 | - sqlx::query_file_as!( |
| 6176 | - ThreadMessage, |
| 6177 | - "../../queries/mail_read_thread.sql", |
| 6178 | - message_id, |
| 6179 | - ) |
| 6180 | - .fetch_all(&self.0.pool) |
| 6181 | - .await |
| 6182 | - } |
| 6183 | - |
| 6184 | - pub async fn read_threads(&self, list_id: &ListId) -> Result<Vec<ThreadSummary>, Error> { |
| 6185 | - let list_name = list_id.0.as_str(); |
| 6186 | - sqlx::query_file_as!( |
| 6187 | - ThreadSummary, |
| 6188 | - "../../queries/mail_read_threads.sql", |
| 6189 | - list_name |
| 6190 | - ) |
| 6191 | - .fetch_all(&self.0.pool) |
| 6192 | - .await |
| 6193 | - } |
| 6194 | - |
| 6195 | - pub async fn list_outbox(&self, max_attempts: u8) -> Result<Vec<OutgoingMessage>, Error> { |
| 6196 | - sqlx::query_file_as!( |
| 6197 | - OutgoingMessage, |
| 6198 | - "../../queries/mail_list_outbox.sql", |
| 6199 | - max_attempts |
| 6200 | - ) |
| 6201 | - .fetch_all(&self.0.pool) |
| 6202 | - .await |
| 6203 | - } |
| 6204 | - |
| 6205 | - pub async fn successful(&self, message_id: i64) -> Result<(), Error> { |
| 6206 | - sqlx::query_file!("../../queries/mail_outbox_successful.sql", message_id) |
| 6207 | - .execute(&self.0.pool) |
| 6208 | - .await?; |
| 6209 | - Ok(()) |
| 6210 | - } |
| 6211 | - |
| 6212 | - pub async fn failed(&self, message_id: i64, err: &DeliveryError) -> Result<(), Error> { |
| 6213 | - let DeliveryError::Generic(message) = err; |
| 6214 | - let err_kind = err.kind(); |
| 6215 | - sqlx::query_file!( |
| 6216 | - "../../queries/mail_outbox_failed.sql", |
| 6217 | - message_id, |
| 6218 | - err_kind, |
| 6219 | - message |
| 6220 | - ) |
| 6221 | - .execute(&self.0.pool) |
| 6222 | - .await?; |
| 6223 | - Ok(()) |
| 6224 | - } |
| 6225 | - } |
| 6226 | diff --git a/crates/database/src/schema.rs b/crates/database/src/schema.rs |
| 6227 | new file mode 100644 |
| 6228 | index 0000000..71b364f |
| 6229 | --- /dev/null |
| 6230 | +++ b/crates/database/src/schema.rs |
| 6231 | @@ -0,0 +1,77 @@ |
| 6232 | + // @generated automatically by Diesel CLI. |
| 6233 | + |
| 6234 | + diesel::table! { |
| 6235 | + logs (id) { |
| 6236 | + id -> Integer, |
| 6237 | + step_id -> Integer, |
| 6238 | + timestamp -> Integer, |
| 6239 | + stream -> Integer, |
| 6240 | + line -> Text, |
| 6241 | + } |
| 6242 | + } |
| 6243 | + |
| 6244 | + diesel::table! { |
| 6245 | + manifests (id) { |
| 6246 | + id -> Integer, |
| 6247 | + collection -> Text, |
| 6248 | + name -> Text, |
| 6249 | + git_hash -> Text, |
| 6250 | + dag_content -> Nullable<Text>, |
| 6251 | + state -> Integer, |
| 6252 | + created_at -> Integer, |
| 6253 | + started_at -> Nullable<Integer>, |
| 6254 | + finished_at -> Nullable<Integer>, |
| 6255 | + } |
| 6256 | + } |
| 6257 | + |
| 6258 | + diesel::table! { |
| 6259 | + samples (id) { |
| 6260 | + id -> Integer, |
| 6261 | + manifest_id -> Integer, |
| 6262 | + timestamp -> Integer, |
| 6263 | + load_1m -> Nullable<Integer>, |
| 6264 | + load_5m -> Nullable<Integer>, |
| 6265 | + load_15m -> Nullable<Integer>, |
| 6266 | + disk_total_bytes -> Nullable<Integer>, |
| 6267 | + disk_free_bytes -> Nullable<Integer>, |
| 6268 | + net_sent_bytes -> Nullable<Integer>, |
| 6269 | + net_received_bytes -> Nullable<Integer>, |
| 6270 | + net_sent_packets -> Nullable<Integer>, |
| 6271 | + net_received_packets -> Nullable<Integer>, |
| 6272 | + mem_total_bytes -> Nullable<Integer>, |
| 6273 | + mem_free_bytes -> Nullable<Integer>, |
| 6274 | + mem_available_bytes -> Nullable<Integer>, |
| 6275 | + } |
| 6276 | + } |
| 6277 | + |
| 6278 | + diesel::table! { |
| 6279 | + steps (id) { |
| 6280 | + id -> Integer, |
| 6281 | + name -> Text, |
| 6282 | + workflow_id -> Integer, |
| 6283 | + shell -> Text, |
| 6284 | + environment_json -> Nullable<Text>, |
| 6285 | + input -> Text, |
| 6286 | + started_at -> Nullable<Integer>, |
| 6287 | + finished_at -> Nullable<Integer>, |
| 6288 | + exit_code -> Nullable<Integer>, |
| 6289 | + } |
| 6290 | + } |
| 6291 | + |
| 6292 | + diesel::table! { |
| 6293 | + workflows (id) { |
| 6294 | + id -> Integer, |
| 6295 | + manifest_id -> Integer, |
| 6296 | + name -> Text, |
| 6297 | + image -> Text, |
| 6298 | + started_at -> Nullable<Integer>, |
| 6299 | + finished_at -> Nullable<Integer>, |
| 6300 | + } |
| 6301 | + } |
| 6302 | + |
| 6303 | + diesel::joinable!(logs -> steps (step_id)); |
| 6304 | + diesel::joinable!(samples -> manifests (manifest_id)); |
| 6305 | + diesel::joinable!(steps -> workflows (workflow_id)); |
| 6306 | + diesel::joinable!(workflows -> manifests (manifest_id)); |
| 6307 | + |
| 6308 | + diesel::allow_tables_to_appear_in_same_query!(logs, manifests, samples, steps, workflows,); |
| 6309 | diff --git a/crates/database/src/stats.rs b/crates/database/src/stats.rs |
| 6310 | deleted file mode 100644 |
| 6311 | index a2dc16a..0000000 |
| 6312 | --- a/crates/database/src/stats.rs |
| 6313 | +++ /dev/null |
| 6314 | @@ -1,74 +0,0 @@ |
| 6315 | - use sqlx::Error; |
| 6316 | - use time::{format_description, OffsetDateTime}; |
| 6317 | - |
| 6318 | - use crate::Wrapper; |
| 6319 | - |
| 6320 | - #[allow(dead_code)] |
| 6321 | - pub enum Aggregation { |
| 6322 | - Day, |
| 6323 | - Week, |
| 6324 | - Month, |
| 6325 | - Year, |
| 6326 | - } |
| 6327 | - |
| 6328 | - pub struct Database<'a>(pub &'a Wrapper); |
| 6329 | - |
| 6330 | - impl Database<'_> { |
| 6331 | - pub async fn contribution_buckets_for_repo( |
| 6332 | - &self, |
| 6333 | - repo_path: &str, |
| 6334 | - git_hash: &str, |
| 6335 | - period: Aggregation, |
| 6336 | - offset: time::Duration, |
| 6337 | - ) -> Result<Vec<(i64, i64, i64)>, Error> { |
| 6338 | - let start = OffsetDateTime::now_utc(); |
| 6339 | - let end = OffsetDateTime::now_utc().saturating_sub(offset); |
| 6340 | - let start_ts = start.unix_timestamp(); |
| 6341 | - let end_ts = end.unix_timestamp(); |
| 6342 | - let seconds = match period { |
| 6343 | - Aggregation::Day => 86400_i64, |
| 6344 | - Aggregation::Week => 604800_i64, |
| 6345 | - Aggregation::Month => 2592000_i64, |
| 6346 | - Aggregation::Year => 31536000_i64, |
| 6347 | - }; |
| 6348 | - let n_buckets = (start_ts - end_ts) / seconds; |
| 6349 | - let mut buckets: Vec<(i64, i64, i64)> = vec![(0, 0, 0); n_buckets as usize]; |
| 6350 | - let strftime = match period { |
| 6351 | - Aggregation::Day => "%d%m", |
| 6352 | - Aggregation::Week => "%w", |
| 6353 | - Aggregation::Month => "%m", |
| 6354 | - Aggregation::Year => "%y", |
| 6355 | - }; |
| 6356 | - let rows = sqlx::query_file!( |
| 6357 | - "../../queries/contributions_bucket.sql", |
| 6358 | - repo_path, |
| 6359 | - git_hash, |
| 6360 | - start, |
| 6361 | - end, |
| 6362 | - strftime |
| 6363 | - ) |
| 6364 | - .fetch_all(&self.0.pool) |
| 6365 | - .await?; |
| 6366 | - for row in rows.iter() { |
| 6367 | - let parsed = |
| 6368 | - OffsetDateTime::parse(row.time.as_str(), &format_description::well_known::Rfc3339) |
| 6369 | - .unwrap(); |
| 6370 | - let diff = ((start - parsed).as_seconds_f64() / seconds as f64).floor(); |
| 6371 | - buckets[(diff - 1.0).abs() as usize] = |
| 6372 | - (row.count, row.added, (row.removed - row.removed * 2)); |
| 6373 | - } |
| 6374 | - // buckets.reverse(); |
| 6375 | - Ok(buckets) |
| 6376 | - } |
| 6377 | - |
| 6378 | - pub async fn count_commits(&self, repo_path: &str, git_hash: &str) -> Result<i32, Error> { |
| 6379 | - let result = sqlx::query_file!( |
| 6380 | - "../../queries/commits_count.sql", |
| 6381 | - repo_path, |
| 6382 | - git_hash, |
| 6383 | - repo_path |
| 6384 | - ); |
| 6385 | - let result = result.fetch_one(&self.0.pool).await?; |
| 6386 | - Ok(result.count.try_into().unwrap()) |
| 6387 | - } |
| 6388 | - } |
| 6389 | diff --git a/crates/timeutil/src/lib.rs b/crates/timeutil/src/lib.rs |
| 6390 | index 164afc4..daf49d1 100644 |
| 6391 | --- a/crates/timeutil/src/lib.rs |
| 6392 | +++ b/crates/timeutil/src/lib.rs |
| 6393 | @@ -1,4 +1,4 @@ |
| 6394 | - use std::time::SystemTime; |
| 6395 | + use std::time::{SystemTime, UNIX_EPOCH}; |
| 6396 | |
| 6397 | // apparently these exist in nightly rust? |
| 6398 | const SECOND: u64 = 1; |
| 6399 | @@ -63,3 +63,10 @@ pub fn timestamp() -> String { |
| 6400 | .format(&time::format_description::well_known::Iso8601::DEFAULT) |
| 6401 | .unwrap() |
| 6402 | } |
| 6403 | + |
| 6404 | + pub fn epoch_secs() -> u64 { |
| 6405 | + std::time::SystemTime::now() |
| 6406 | + .duration_since(UNIX_EPOCH) |
| 6407 | + .unwrap() |
| 6408 | + .as_secs() |
| 6409 | + } |
| 6410 | diff --git a/diesel.toml b/diesel.toml |
| 6411 | new file mode 100644 |
| 6412 | index 0000000..58e0567 |
| 6413 | --- /dev/null |
| 6414 | +++ b/diesel.toml |
| 6415 | @@ -0,0 +1,9 @@ |
| 6416 | + # For documentation on how to configure this file, |
| 6417 | + # see https://diesel.rs/guides/configuring-diesel-cli |
| 6418 | + |
| 6419 | + [print_schema] |
| 6420 | + file = "crates/database/src/schema.rs" |
| 6421 | + custom_type_derives = ["diesel::query_builder::QueryId", "Clone"] |
| 6422 | + |
| 6423 | + [migrations_directory] |
| 6424 | + dir = "crates/database/migrations" |
| 6425 | diff --git a/migrations/20230602111216_init.sql b/migrations/20230602111216_init.sql |
| 6426 | deleted file mode 100644 |
| 6427 | index d3754fe..0000000 |
| 6428 | --- a/migrations/20230602111216_init.sql |
| 6429 | +++ /dev/null |
| 6430 | @@ -1,51 +0,0 @@ |
| 6431 | - CREATE TABLE authors ( |
| 6432 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6433 | - username TEXT NOT NULL, |
| 6434 | - email TEXT NOT NULL, |
| 6435 | - UNIQUE (username, email) |
| 6436 | - ) STRICT; |
| 6437 | - |
| 6438 | - CREATE TABLE languages ( |
| 6439 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6440 | - git_hash TEXT NOT NULL, |
| 6441 | - repo_path TEXT NOT NULL, |
| 6442 | - language TEXT NOT NULL, |
| 6443 | - loc INTEGER NOT NULL, |
| 6444 | - UNIQUE (git_hash, repo_path, language) |
| 6445 | - ) STRICT; |
| 6446 | - |
| 6447 | - CREATE TABLE jobs ( |
| 6448 | - id INTEGER PRIMARY KEY, |
| 6449 | - created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, |
| 6450 | - kind TEXT NOT NULL, |
| 6451 | - repo_path TEXT, |
| 6452 | - runtime INTEGER, |
| 6453 | - success INTEGER |
| 6454 | - ) STRICT; |
| 6455 | - |
| 6456 | - CREATE TABLE job_tracking ( |
| 6457 | - id INTEGER PRIMARY KEY, |
| 6458 | - job_id INTEGER REFERENCES jobs(id) ON DELETE CASCADE NOT NULL, |
| 6459 | - repo_path TEXT NOT NULL, |
| 6460 | - git_hash TEXT NOT NULL, |
| 6461 | - kind TEXT NOT NULL, |
| 6462 | - UNIQUE (repo_path, git_hash, kind) |
| 6463 | - ) STRICT; |
| 6464 | - |
| 6465 | - CREATE TABLE contributions ( |
| 6466 | - id INTEGER PRIMARY KEY, |
| 6467 | - git_hash TEXT NOT NULL, |
| 6468 | - repo_path TEXT NOT NULL, |
| 6469 | - time TEXT NOT NULL, |
| 6470 | - author_id INTEGER REFERENCES authors(id), |
| 6471 | - lines_added INTEGER NOT NULL, |
| 6472 | - lines_removed INTEGER NOT NULL |
| 6473 | - ) STRICT; |
| 6474 | - |
| 6475 | - CREATE TABLE contribution_tally ( |
| 6476 | - id INTEGER PRIMARY KEY, |
| 6477 | - git_hash TEXT NOT NULL, |
| 6478 | - repo_path TEXT NOT NULL, |
| 6479 | - author_id INTEGER REFERENCES authors(id), |
| 6480 | - total INTEGER NOT NULL |
| 6481 | - ) STRICT; |
| 6482 | diff --git a/migrations/20231204194038_init.sql b/migrations/20231204194038_init.sql |
| 6483 | deleted file mode 100644 |
| 6484 | index 79b5e5e..0000000 |
| 6485 | --- a/migrations/20231204194038_init.sql |
| 6486 | +++ /dev/null |
| 6487 | @@ -1,71 +0,0 @@ |
| 6488 | - CREATE TABLE manifests ( |
| 6489 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6490 | - collection TEXT NOT NULL, |
| 6491 | - name TEXT NOT NULL, |
| 6492 | - git_hash TEXT NOT NULL, |
| 6493 | - created_at INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 6494 | - started_at INTEGER CHECK (started_at > 0), |
| 6495 | - finished_at INTEGER CHECK (finished_at > 0) |
| 6496 | - ) STRICT ; |
| 6497 | - |
| 6498 | - CREATE TABLE workflows ( |
| 6499 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6500 | - manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 6501 | - name TEXT NOT NULL, |
| 6502 | - image TEXT NOT NULL, |
| 6503 | - started_at INTEGER CHECK (started_at > 0), |
| 6504 | - finished_at INTEGER CHECK (finished_at > 0) |
| 6505 | - ) STRICT ; |
| 6506 | - |
| 6507 | - CREATE TABLE steps ( |
| 6508 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6509 | - name TEXT NOT NULL, |
| 6510 | - workflow_id INTEGER REFERENCES workflows(id) ON DELETE CASCADE NOT NULL, |
| 6511 | - shell TEXT NOT NULL DEFAULT "/bin/sh", |
| 6512 | - environment_json TEXT, |
| 6513 | - input TEXT NOT NULL, |
| 6514 | - started_at INTEGER CHECK (started_at > 0), |
| 6515 | - finished_at INTEGER CHECK (finished_at > 0), |
| 6516 | - stdout TEXT, |
| 6517 | - stderr TEXT, |
| 6518 | - exit_code INTEGER CHECK (exit_code <= 255) |
| 6519 | - ) STRICT ; |
| 6520 | - |
| 6521 | - CREATE TABLE logs ( |
| 6522 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6523 | - step_id INTEGER REFERENCES steps(id) ON DELETE CASCADE NOT NULL, |
| 6524 | - runtime INTEGER NOT NULL, |
| 6525 | - stream TEXT NOT NULL CHECK (stream IN ('stdout', 'stderr', 'stdin')), |
| 6526 | - line TEXT |
| 6527 | - ) STRICT ; |
| 6528 | - |
| 6529 | - CREATE TABLE steps_env_vars ( |
| 6530 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6531 | - step_id INTEGER REFERENCES steps(id) ON DELETE CASCADE NOT NULL, |
| 6532 | - name TEXT NOT NULL, |
| 6533 | - value TEXT |
| 6534 | - ) STRICT ; |
| 6535 | - |
| 6536 | - CREATE TABLE dags ( |
| 6537 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6538 | - manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 6539 | - dag_content TEXT NOT NULL |
| 6540 | - ) STRICT ; |
| 6541 | - |
| 6542 | - CREATE TABLE samples ( |
| 6543 | - id INTEGER PRIMARY KEY NOT NULL, |
| 6544 | - manifest_id INTEGER REFERENCES manifests(id) ON DELETE CASCADE NOT NULL, |
| 6545 | - timestamp INTEGER NOT NULL DEFAULT (UNIXEPOCH()), |
| 6546 | - load_1m INTEGER, |
| 6547 | - load_5m INTEGER, |
| 6548 | - load_15m INTEGER, |
| 6549 | - disk_total_bytes INTEGER, |
| 6550 | - disk_free_bytes INTEGER, |
| 6551 | - net_sent_bytes INTEGER, |
| 6552 | - net_received_bytes INTEGER, |
| 6553 | - net_sent_packets INTEGER, |
| 6554 | - net_received_packets INTEGER, |
| 6555 | - mem_total_bytes INTEGER, |
| 6556 | - mem_free_bytes INTEGER, |
| 6557 | - mem_available_bytes INTEGER |
| 6558 | - ) STRICT ; |
| 6559 | diff --git a/migrations/20241028092919_mail.sql b/migrations/20241028092919_mail.sql |
| 6560 | deleted file mode 100644 |
| 6561 | index 621471e..0000000 |
| 6562 | --- a/migrations/20241028092919_mail.sql |
| 6563 | +++ /dev/null |
| 6564 | @@ -1,57 +0,0 @@ |
| 6565 | - CREATE TABLE lists ( |
| 6566 | - id INTEGER PRIMARY KEY, |
| 6567 | - name TEXT NOT NULL, |
| 6568 | - address TEXT NOT NULL UNIQUE, |
| 6569 | - description TEXT, |
| 6570 | - enabled INTEGER NOT NULL DEFAULT 0 CHECK (enabled IN (0, 1)) |
| 6571 | - ) STRICT ; |
| 6572 | - |
| 6573 | - CREATE TABLE participants ( |
| 6574 | - id INTEGER PRIMARY KEY, |
| 6575 | - address TEXT NOT NULL UNIQUE, |
| 6576 | - authorized_sender INTEGER NOT NULL DEFAULT 0 CHECK (authorized_sender IN (0, 1)) |
| 6577 | - ) STRICT ; |
| 6578 | - |
| 6579 | - CREATE TABLE subscriptions ( |
| 6580 | - id INTEGER PRIMARY KEY, |
| 6581 | - participant_id INTEGER NOT NULL REFERENCES participants(id), |
| 6582 | - list_id INTEGER NOT NULL REFERENCES lists(id), |
| 6583 | - UNIQUE(participant_id, list_id) ON CONFLICT REPLACE |
| 6584 | - ) STRICT ; |
| 6585 | - |
| 6586 | - CREATE TABLE outbox ( |
| 6587 | - id INTEGER PRIMARY KEY, |
| 6588 | - message_id INTEGER NOT NULL REFERENCES messages(id), |
| 6589 | - recipient INTEGER NOT NULL REFERENCES participants(id), |
| 6590 | - UNIQUE(message_id, recipient) ON CONFLICT REPLACE |
| 6591 | - ) STRICT ; |
| 6592 | - |
| 6593 | - CREATE TABLE messages ( |
| 6594 | - id INTEGER PRIMARY KEY, |
| 6595 | - message_id TEXT NOT NULL UNIQUE, |
| 6596 | - list_id INTEGER NOT NULL REFERENCES lists(id), |
| 6597 | - in_reply_to TEXT, |
| 6598 | - subject TEXT, |
| 6599 | - mail_from INTEGER NOT NULL REFERENCES participants(id), |
| 6600 | - raw_message BLOB NOT NULL, |
| 6601 | - content_body TEXT, |
| 6602 | - reply_count INTEGER NOT NULL DEFAULT 0 |
| 6603 | - ) STRICT ; |
| 6604 | - |
| 6605 | - CREATE TABLE delivery_failures ( |
| 6606 | - id INTEGER PRIMARY KEY, |
| 6607 | - outbox_id INTEGER NOT NULL REFERENCES outbox(id), |
| 6608 | - error_kind TEXT NOT NULL, |
| 6609 | - message TEXT |
| 6610 | - ); |
| 6611 | - |
| 6612 | - CREATE TRIGGER handle_delivery |
| 6613 | - AFTER INSERT ON messages |
| 6614 | - FOR EACH ROW |
| 6615 | - BEGIN |
| 6616 | - INSERT INTO outbox (message_id, recipient) |
| 6617 | - SELECT NEW.id, participants.id FROM participants |
| 6618 | - LEFT JOIN subscriptions ON participants.id = subscriptions.participant_id |
| 6619 | - WHERE |
| 6620 | - subscriptions.list_id = NEW.id AND participants.authorized_sender = 1; |
| 6621 | - END; |