diff --git a/Cargo.lock b/Cargo.lock index e60a7c5..12e94d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,7 +14,7 @@ version = "0.6.0-rc.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b657e772794c6b04730ea897b66a058ccd866c16d1967da05eeeecec39043fe" dependencies = [ - "crypto-common 0.2.0", + "crypto-common 0.2.1", "inout", ] @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arcstr" @@ -94,14 +94,14 @@ checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d" [[package]] name = "async-compression" -version = "0.4.39" +version = "0.4.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68650b7df54f0293fd061972a0fb05aaf4fc0879d3b3d21a638a182c5c543b9f" +checksum = "d0f9ee0f6e02ffd7ad5816e9464499fba7b3effd01123b515c41d1697c43dad1" dependencies = [ "compression-codecs", "compression-core", "pin-project-lite", - "tokio 1.49.0", + "tokio 1.50.0", ] [[package]] @@ -163,9 +163,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "aws-config" -version = "1.8.14" +version = "1.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a8fc176d53d6fe85017f230405e3255cedb4a02221cb55ed6d76dccbbb099b2" +checksum = "11493b0bad143270fb8ad284a096dd529ba91924c5409adeac856cc1bf047dbc" dependencies = [ "aws-credential-types", "aws-runtime", @@ -183,9 +183,9 @@ dependencies = [ "fastrand", "hex", "http 1.4.0", - "ring", + "sha1", "time", - "tokio 1.49.0", + "tokio 1.50.0", "tracing", "url 2.5.8", "zeroize", @@ -193,9 +193,9 @@ dependencies = [ [[package]] name = "aws-credential-types" -version = "1.2.12" +version = "1.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e26bbf46abc608f2dc61fd6cb3b7b0665497cc259a21520151ed98f8b37d2c79" +checksum = "8f20799b373a1be121fe3005fba0c2090af9411573878f224df44b42727fcaf7" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -205,9 +205,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.15.4" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7b6141e96a8c160799cc2d5adecd5cbbe5054cb8c7c4af53da0f83bb7ad256" +checksum = "94bffc006df10ac2a68c83692d734a465f8ee6c5b384d8545a636f81d858f4bf" dependencies = [ "aws-lc-sys", "zeroize", @@ -215,9 +215,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.37.1" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" +checksum = "4321e568ed89bb5a7d291a7f37997c2c0df89809d7b6d12062c81ddb54aa782e" dependencies = [ "cc", "cmake", @@ -227,9 +227,9 @@ dependencies = [ [[package]] name = "aws-runtime" -version = "1.7.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0f92058d22a46adf53ec57a6a96f34447daf02bff52e8fb956c66bcd5c6ac12" +checksum = "5fc0651c57e384202e47153c1260b84a9936e19803d747615edf199dc3b98d17" dependencies = [ "aws-credential-types", "aws-sigv4", @@ -255,9 +255,9 @@ dependencies = [ [[package]] name = "aws-sdk-s3" -version = "1.123.0" +version = "1.125.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c018f22146966fdd493a664f62ee2483dff256b42a08c125ab6a084bde7b77fe" +checksum = "223f5c95650d9557925a91f4c2db3def189e8f659452134a29e5cd2d37d708ed" dependencies = [ "aws-credential-types", "aws-runtime", @@ -290,9 +290,9 @@ dependencies = [ [[package]] name = "aws-sdk-sso" -version = "1.94.0" +version = "1.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "699da1961a289b23842d88fe2984c6ff68735fdf9bdcbc69ceaeb2491c9bf434" +checksum = "f64a6eded248c6b453966e915d32aeddb48ea63ad17932682774eb026fbef5b1" dependencies = [ "aws-credential-types", "aws-runtime", @@ -314,9 +314,9 @@ dependencies = [ [[package]] name = "aws-sdk-ssooidc" -version = "1.96.0" +version = "1.98.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3e3a4cb3b124833eafea9afd1a6cc5f8ddf3efefffc6651ef76a03cbc6b4981" +checksum = "db96d720d3c622fcbe08bae1c4b04a72ce6257d8b0584cb5418da00ae20a344f" dependencies = [ "aws-credential-types", "aws-runtime", @@ -338,9 +338,9 @@ dependencies = [ [[package]] name = "aws-sdk-sts" -version = "1.98.0" +version = "1.100.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c4f19655ab0856375e169865c91264de965bd74c407c7f1e403184b1049409" +checksum = "fafbdda43b93f57f699c5dfe8328db590b967b8a820a13ccdd6687355dfcc7ca" dependencies = [ "aws-credential-types", "aws-runtime", @@ -363,9 +363,9 @@ dependencies = [ [[package]] name = "aws-sigv4" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f6ae9b71597dc5fd115d52849d7a5556ad9265885ad3492ea8d73b93bbc46e" +checksum = "b0b660013a6683ab23797778e21f1f854744fdf05f68204b4cca4c8c04b5d1f4" dependencies = [ "aws-credential-types", "aws-smithy-eventstream", @@ -391,20 +391,20 @@ dependencies = [ [[package]] name = "aws-smithy-async" -version = "1.2.12" +version = "1.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cba48474f1d6807384d06fec085b909f5807e16653c5af5c45dfe89539f0b70" +checksum = "2ffcaf626bdda484571968400c326a244598634dc75fd451325a54ad1a59acfc" dependencies = [ "futures-util", "pin-project-lite", - "tokio 1.49.0", + "tokio 1.50.0", ] [[package]] name = "aws-smithy-checksums" -version = "0.64.4" +version = "0.64.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a764fa7222922f6c0af8eea478b0ef1ba5ce1222af97e01f33ca5e957bd7f3b9" +checksum = "6750f3dd509b0694a4377f0293ed2f9630d710b1cebe281fa8bac8f099f88bc6" dependencies = [ "aws-smithy-http", "aws-smithy-types", @@ -423,9 +423,9 @@ dependencies = [ [[package]] name = "aws-smithy-eventstream" -version = "0.60.19" +version = "0.60.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c0b3e587fbaa5d7f7e870544508af8ce82ea47cd30376e69e1e37c4ac746f79" +checksum = "faf09d74e5e32f76b8762da505a3cd59303e367a664ca67295387baa8c1d7548" dependencies = [ "aws-smithy-types", "bytes 1.11.1", @@ -434,9 +434,9 @@ dependencies = [ [[package]] name = "aws-smithy-http" -version = "0.63.4" +version = "0.63.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4a8a5fe3e4ac7ee871237c340bbce13e982d37543b65700f4419e039f5d78e" +checksum = "ba1ab2dc1c2c3749ead27180d333c42f11be8b0e934058fb4b2258ee8dbe5231" dependencies = [ "aws-smithy-eventstream", "aws-smithy-runtime-api", @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "aws-smithy-http-client" -version = "1.1.10" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0709f0083aa19b704132684bc26d3c868e06bd428ccc4373b0b55c3e8748a58b" +checksum = "6a2f165a7feee6f263028b899d0a181987f4fa7179a6411a32a439fba7c5f769" dependencies = [ "aws-smithy-async", "aws-smithy-runtime-api", @@ -475,10 +475,10 @@ dependencies = [ "hyper-util", "pin-project-lite", "rustls 0.21.12", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-native-certs", "rustls-pki-types", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-rustls 0.26.4", "tower", "tracing", @@ -486,27 +486,27 @@ dependencies = [ [[package]] name = "aws-smithy-json" -version = "0.62.4" +version = "0.62.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b3a779093e18cad88bbae08dc4261e1d95018c4c5b9356a52bcae7c0b6e9bb" +checksum = "9648b0bb82a2eedd844052c6ad2a1a822d1f8e3adee5fbf668366717e428856a" dependencies = [ "aws-smithy-types", ] [[package]] name = "aws-smithy-observability" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d3f39d5bb871aaf461d59144557f16d5927a5248a983a40654d9cf3b9ba183b" +checksum = "a06c2315d173edbf1920da8ba3a7189695827002e4c0fc961973ab1c54abca9c" dependencies = [ "aws-smithy-runtime-api", ] [[package]] name = "aws-smithy-query" -version = "0.60.14" +version = "0.60.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f76a580e3d8f8961e5d48763214025a2af65c2fa4cd1fb7f270a0e107a71b0" +checksum = "1a56d79744fb3edb5d722ef79d86081e121d3b9422cb209eb03aea6aa4f21ebd" dependencies = [ "aws-smithy-types", "urlencoding", @@ -514,9 +514,9 @@ dependencies = [ [[package]] name = "aws-smithy-runtime" -version = "1.10.1" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd3dfc18c1ce097cf81fced7192731e63809829c6cbf933c1ec47452d08e1aa" +checksum = "028999056d2d2fd58a697232f9eec4a643cf73a71cf327690a7edad1d2af2110" dependencies = [ "aws-smithy-async", "aws-smithy-http", @@ -533,15 +533,15 @@ dependencies = [ "http-body-util", "pin-project-lite", "pin-utils", - "tokio 1.49.0", + "tokio 1.50.0", "tracing", ] [[package]] name = "aws-smithy-runtime-api" -version = "1.11.4" +version = "1.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c55e0837e9b8526f49e0b9bfa9ee18ddee70e853f5bc09c5d11ebceddcb0fec" +checksum = "876ab3c9c29791ba4ba02b780a3049e21ec63dabda09268b175272c3733a79e6" dependencies = [ "aws-smithy-async", "aws-smithy-types", @@ -549,16 +549,16 @@ dependencies = [ "http 0.2.12", "http 1.4.0", "pin-project-lite", - "tokio 1.49.0", + "tokio 1.50.0", "tracing", "zeroize", ] [[package]] name = "aws-smithy-types" -version = "1.4.4" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576b0d6991c9c32bc14fc340582ef148311f924d41815f641a308b5d11e8e7cd" +checksum = "d2b1117b3b2bbe166d11199b540ceed0d0f7676e36e7b962b5a437a9971eac75" dependencies = [ "base64-simd", "bytes 1.11.1", @@ -576,24 +576,24 @@ dependencies = [ "ryu", "serde", "time", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-util", ] [[package]] name = "aws-smithy-xml" -version = "0.60.14" +version = "0.60.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53543b4b86ed43f051644f704a98c7291b3618b67adf057ee77a366fa52fcaa" +checksum = "0ce02add1aa3677d022f8adf81dcbe3046a95f17a1b1e8979c145cd21d3d22b3" dependencies = [ "xmlparser", ] [[package]] name = "aws-types" -version = "1.3.12" +version = "1.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c50f3cdf47caa8d01f2be4a6663ea02418e892f9bbfd82c7b9a3a37eaccdd3a" +checksum = "47c8323699dd9b3c8d5b3c13051ae9cdef58fd179957c882f8374dd8725962d9" dependencies = [ "aws-credential-types", "aws-smithy-async", @@ -639,9 +639,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" [[package]] name = "bitvec" @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96eb4cdd6cf1b31d671e9efe75c5d1ec614776856cefbe109ca373554a6d514f" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ "hybrid-array", ] @@ -698,9 +698,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" [[package]] name = "byteorder" @@ -736,9 +736,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.55" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -772,9 +772,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "js-sys", @@ -786,12 +786,12 @@ dependencies = [ [[package]] name = "cipher" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64727038c8c5e2bb503a15b9f5b9df50a1da9a33e83e1f93067d914f2c6604a5" +checksum = "e34d8227fe1ba289043aeb13792056ff80fd6de1a9f49137a5f499de8e8c78ea" dependencies = [ - "block-buffer 0.11.0", - "crypto-common 0.2.0", + "block-buffer 0.12.0", + "crypto-common 0.2.1", "inout", ] @@ -813,6 +813,12 @@ dependencies = [ "cc", ] +[[package]] +name = "cmov" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0758edba32d61d1fd9f4d69491b47604b91ee2f7e6b33de7e54ca4ebe55dc3" + [[package]] name = "combine" version = "4.6.7" @@ -823,15 +829,15 @@ dependencies = [ "futures-core", "memchr", "pin-project-lite", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-util", ] [[package]] name = "compression-codecs" -version = "0.4.36" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00828ba6fd27b45a448e57dbfe84f1029d4c9f26b368157e9a448a5f49a2ec2a" +checksum = "eb7b51a7d9c967fc26773061ba86150f19c50c0d65c887cb1fbe295fd16619b7" dependencies = [ "compression-core", "flate2", @@ -1094,24 +1100,33 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "211f05e03c7d03754740fd9e585de910a095d6b99f8bcfffdef8319fa02a8331" +checksum = "77727bb15fa921304124b128af125e7e3b968275d1b108b379190264f4423710" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "hybrid-array", "rand_core 0.10.0", ] [[package]] name = "ctr" -version = "0.10.0-rc.3" +version = "0.10.0-rc.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65ea71550d18331d179854662ab330bb54306b9b56020d0466aae2a58f4e17c1" +checksum = "fee683dd898fbd052617b4514bc31f98bc32081a83b69ec46adef3b1ef4ae36f" dependencies = [ "cipher", ] +[[package]] +name = "ctutils" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1005a6d4446f5120ef475ad3d2af2b30c49c2c9c6904258e3bb30219bebed5e4" +dependencies = [ + "cmov", +] + [[package]] name = "darling" version = "0.21.3" @@ -1165,9 +1180,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", ] @@ -1453,9 +1468,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1468,9 +1483,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1478,15 +1493,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -1495,15 +1510,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", @@ -1512,21 +1527,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1536,7 +1551,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -1572,20 +1586,20 @@ dependencies = [ "cfg-if 1.0.4", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if 1.0.4", "libc", - "r-efi", + "r-efi 6.0.0", "rand_core 0.10.0", "wasip2", "wasip3", @@ -1593,9 +1607,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.6.0-rc.6" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb9be1ab8718f9d16384cb3626a5a7d7eac4d3fd1b2564e97592f40523dc0228" +checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5" dependencies = [ "polyval", ] @@ -1625,7 +1639,7 @@ dependencies = [ "http 0.2.12", "indexmap", "slab", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-util", "tracing", ] @@ -1644,7 +1658,7 @@ dependencies = [ "http 1.4.0", "indexmap", "slab", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-util", "tracing", ] @@ -1707,7 +1721,7 @@ dependencies = [ "ring", "thiserror 2.0.18", "tinyvec", - "tokio 1.49.0", + "tokio 1.50.0", "tracing", "url 2.5.8", ] @@ -1729,7 +1743,7 @@ dependencies = [ "resolv-conf", "smallvec 1.15.1", "thiserror 2.0.18", - "tokio 1.49.0", + "tokio 1.50.0", "tracing", ] @@ -1836,7 +1850,7 @@ dependencies = [ "itoa", "pin-project-lite", "socket2 0.5.10", - "tokio 1.49.0", + "tokio 1.50.0", "tower-service", "tracing", "want", @@ -1860,7 +1874,7 @@ dependencies = [ "pin-project-lite", "pin-utils", "smallvec 1.15.1", - "tokio 1.49.0", + "tokio 1.50.0", "want", ] @@ -1875,7 +1889,7 @@ dependencies = [ "hyper 0.14.32", "log", "rustls 0.21.12", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-rustls 0.24.1", ] @@ -1888,10 +1902,10 @@ dependencies = [ "http 1.4.0", "hyper 1.8.1", "hyper-util", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-native-certs", "rustls-pki-types", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-rustls 0.26.4", "tower-service", "webpki-roots", @@ -1914,9 +1928,9 @@ dependencies = [ "libc", "percent-encoding 2.3.2", "pin-project-lite", - "socket2 0.6.2", + "socket2 0.6.3", "system-configuration", - "tokio 1.49.0", + "tokio 1.50.0", "tower-service", "tracing", "windows-registry", @@ -2115,9 +2129,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "iri-string" @@ -2169,9 +2183,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -2201,26 +2215,27 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.181" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459427e2af2b9c839b132acb702a1c654d95e10f8c326bfc2ad11310e458b1c5" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", - "redox_syscall 0.7.1", + "plain", + "redox_syscall 0.7.3", ] [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -2442,9 +2457,9 @@ dependencies = [ [[package]] name = "moka" -version = "0.12.13" +version = "0.12.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac832c50ced444ef6be0767a008b02c106a909ba79d1d830501e94b96f6b7e" +checksum = "85f8024e1c8e71c778968af91d43700ce1d11b219d127d79fb2934153b82b42b" dependencies = [ "crossbeam-channel", "crossbeam-epoch 0.9.18", @@ -2482,7 +2497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "803dd859e8afa084c255a8effd8000ff86f7c8076a50cd6d8c99e8f3496f75c2" dependencies = [ "base64", - "bitflags 2.10.0", + "bitflags 2.11.0", "bson", "derive-where", "derive_more", @@ -2501,19 +2516,19 @@ dependencies = [ "percent-encoding 2.3.2", "rand 0.9.2", "rustc_version_runtime", - "rustls 0.23.36", + "rustls 0.23.37", "rustversion", "serde", "serde_bytes", "serde_with", "sha1", "sha2", - "socket2 0.6.2", + "socket2 0.6.3", "stringprep", "strsim", "take_mut", "thiserror 2.0.18", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-rustls 0.26.4", "tokio-util", "typed-builder", @@ -2638,7 +2653,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -2666,7 +2681,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cfg-if 1.0.4", "foreign-types", "libc", @@ -2812,9 +2827,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -2838,11 +2853,17 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "plain" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" + [[package]] name = "polyval" -version = "0.7.0-rc.9" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e83fbff7a079b2d37c70aa6bd5eedb9e5d09ceb9b4ecd31e9ea212d00e9b0bc" +checksum = "7dfc63250416fea14f5749b90725916a6c903f599d51cb635aa7a52bfd03eede" dependencies = [ "cpubits", "cpufeatures 0.3.0", @@ -2868,7 +2889,7 @@ dependencies = [ "cron", "dotenvy", "flate2", - "futures 0.3.31", + "futures 0.3.32", "futures-util", "generic-array", "hex", @@ -2887,7 +2908,7 @@ dependencies = [ "tempfile", "thiserror 2.0.18", "time", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-postgres", "tokio-stream", "tokio-tar", @@ -2990,10 +3011,10 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.36", - "socket2 0.6.2", + "rustls 0.23.37", + "socket2 0.6.3", "thiserror 2.0.18", - "tokio 1.49.0", + "tokio 1.50.0", "tracing", "web-time", ] @@ -3011,7 +3032,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "slab", "thiserror 2.0.18", @@ -3029,16 +3050,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.2", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -3049,6 +3070,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "radium" version = "0.7.0" @@ -3122,9 +3149,9 @@ checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" [[package]] name = "redis" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e969d1d702793536d5fda739a82b88ad7cbe7d04f8386ee8cd16ad3eff4854a5" +checksum = "b36964393906eb775b89b25b05b7b95685b8dd14062f1663a31ff93e75c452e5" dependencies = [ "arcstr", "bytes 1.11.1", @@ -3137,8 +3164,8 @@ dependencies = [ "pin-project-lite", "ryu", "sha1_smol", - "socket2 0.6.2", - "tokio 1.49.0", + "socket2 0.6.3", + "tokio 1.50.0", "tokio-util", "url 2.5.8", "xxhash-rust", @@ -3165,16 +3192,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] name = "redox_syscall" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" +checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", ] [[package]] @@ -3196,9 +3223,9 @@ checksum = "cab834c73d247e67f4fae452806d17d3c7501756d98c8808d7c9c7aa7d18f973" [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" @@ -3220,13 +3247,13 @@ dependencies = [ "percent-encoding 2.3.2", "pin-project-lite", "quinn", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-rustls 0.26.4", "tower", "tower-http", @@ -3264,14 +3291,14 @@ dependencies = [ "percent-encoding 2.3.2", "pin-project-lite", "quinn", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "rustls-platform-verifier", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-rustls 0.26.4", "tokio-util", "tower", @@ -3351,11 +3378,11 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", @@ -3376,9 +3403,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "aws-lc-rs", "log", @@ -3423,7 +3450,7 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-native-certs", "rustls-platform-verifier-android", "rustls-webpki 0.103.9", @@ -3529,11 +3556,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.5.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3542,9 +3569,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -3659,9 +3686,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" dependencies = [ "serde_core", "serde_with_macros", @@ -3669,9 +3696,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" dependencies = [ "darling", "proc-macro2", @@ -3787,12 +3814,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -3842,9 +3869,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.115" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e614ed320ac28113fa64972c4262d5dbc89deacdfd00c34a3e4cea073243c12" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -3877,7 +3904,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -3923,12 +3950,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.25.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", - "getrandom 0.4.1", + "getrandom 0.4.2", "once_cell", "rustix", "windows-sys 0.61.2", @@ -4076,16 +4103,16 @@ dependencies = [ [[package]] name = "tokio" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes 1.11.1", "libc", "mio 1.1.1", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] @@ -4164,9 +4191,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", @@ -4193,8 +4220,8 @@ dependencies = [ "postgres-protocol", "postgres-types", "rand 0.9.2", - "socket2 0.6.2", - "tokio 1.49.0", + "socket2 0.6.3", + "tokio 1.50.0", "tokio-util", "whoami", ] @@ -4225,7 +4252,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ "rustls 0.21.12", - "tokio 1.49.0", + "tokio 1.50.0", ] [[package]] @@ -4234,8 +4261,8 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.36", - "tokio 1.49.0", + "rustls 0.23.37", + "tokio 1.50.0", ] [[package]] @@ -4246,7 +4273,7 @@ checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", - "tokio 1.49.0", + "tokio 1.50.0", ] [[package]] @@ -4269,7 +4296,7 @@ dependencies = [ "futures-core", "libc", "redox_syscall 0.3.5", - "tokio 1.49.0", + "tokio 1.50.0", "tokio-stream", "xattr", ] @@ -4361,7 +4388,7 @@ dependencies = [ "futures-io", "futures-sink", "pin-project-lite", - "tokio 1.49.0", + "tokio 1.50.0", ] [[package]] @@ -4376,7 +4403,7 @@ dependencies = [ "toml_datetime", "toml_parser", "toml_writer", - "winnow 0.7.14", + "winnow 0.7.15", ] [[package]] @@ -4390,11 +4417,11 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.0.8+spec-1.1.0" +version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ - "winnow 0.7.14", + "winnow 0.7.15", ] [[package]] @@ -4413,7 +4440,7 @@ dependencies = [ "futures-util", "pin-project-lite", "sync_wrapper", - "tokio 1.49.0", + "tokio 1.50.0", "tower-layer", "tower-service", ] @@ -4424,7 +4451,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes 1.11.1", "futures-util", "http 1.4.0", @@ -4569,9 +4596,9 @@ checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" [[package]] name = "unicode-ident" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" @@ -4602,12 +4629,12 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" -version = "0.6.0-rc.10" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058482a494bb3c9c39447d8b40a3a0f38ebb3dccaf02c5a2d681e69035f8da11" +checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96" dependencies = [ - "crypto-common 0.2.0", - "subtle", + "crypto-common 0.2.1", + "ctutils", ] [[package]] @@ -4654,11 +4681,11 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.20.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.2", "js-sys", "serde_core", "wasm-bindgen", @@ -4751,9 +4778,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if 1.0.4", "once_cell", @@ -4764,9 +4791,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if 1.0.4", "futures-util", @@ -4778,9 +4805,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4788,9 +4815,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", @@ -4801,9 +4828,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] @@ -4849,7 +4876,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "hashbrown 0.15.5", "indexmap", "semver 1.0.27", @@ -4857,9 +4884,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -5324,9 +5351,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" [[package]] name = "winreg" @@ -5396,7 +5423,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.10.0", + "bitflags 2.11.0", "indexmap", "log", "serde", @@ -5498,18 +5525,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", diff --git a/docker-compose.yml b/docker-compose.yml index 82b5455..acbdf21 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -12,13 +12,13 @@ services: - cargo-registry:/usr/local/cargo/registry - cargo-git:/usr/local/cargo/git # - cargo-target:/app/target - - sqlite-data:/sqlite-data/workspace/data - - ./scripts/sqlite/test-db:/sqlite-data-2/workspace/data +# - sqlite-data:/sqlite-data/workspace/data +# - ./scripts/sqlite/test-db:/sqlite-data-2/workspace/data environment: APP_ENV: development LOG: debug TZ: "Europe/Paris" - EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiZjg4Y2E0MDMtNDgwOS00NGM4LTlkZjItY2VkNWYwYzhkNTM2IiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" + EDGE_KEY: "eyJzZXJ2ZXJVcmwiOiJodHRwOi8vbG9jYWxob3N0Ojg4ODciLCJhZ2VudElkIjoiNjI1MDQzY2YtN2MwMC00M2M4LWJjYzktZDM1MTk5ODk2ZGNkIiwibWFzdGVyS2V5QjY0IjoiQlhWM1hvbEM2NTZTVjdkTmdjV1BHUWxrKytycExJNmxHRGk3Q1BCNWllbz0ifQ==" #POOLING: 1 #DATABASES_CONFIG_FILE: "config.toml" extra_hosts: @@ -26,19 +26,19 @@ services: networks: - portabase -# db-postgres: -# container_name: db-postgres -# image: postgres:17-alpine -# ports: -# - "5436:5432" -# volumes: -# - postgres-data:/var/lib/postgresql/data -# environment: -# - POSTGRES_DB=devdb -# - POSTGRES_USER=devuser -# - POSTGRES_PASSWORD=changeme -# networks: -# - portabase + db-postgres: + container_name: db-postgres + image: postgres:17-alpine + ports: + - "5436:5432" + volumes: + - postgres-data:/var/lib/postgresql/data + environment: + - POSTGRES_DB=devdb + - POSTGRES_USER=devuser + - POSTGRES_PASSWORD=changeme + networks: + - portabase # # db-mariadb: # container_name: db-mariadb @@ -93,15 +93,15 @@ services: # networks: # - portabase - sqlite: - container_name: db-sqlite - image: keinos/sqlite3 - volumes: - - sqlite-data:/workspace/data - working_dir: /workspace - command: tail -f /dev/null - stdin_open: true - tty: true +# sqlite: +# container_name: db-sqlite +# image: keinos/sqlite3 +# volumes: +# - sqlite-data:/workspace/data +# working_dir: /workspace +# command: tail -f /dev/null +# stdin_open: true +# tty: true volumes: @@ -109,11 +109,11 @@ volumes: cargo-git: # cargo-target: -# postgres-data: + postgres-data: # mariadb-data: # mongodb-data: # mongodb-data-auth: - sqlite-data: +# sqlite-data: networks: portabase: diff --git a/scripts/postgres/seed-1gb.sql b/scripts/postgres/seed-1gb.sql index be0883d..9bf1c47 100644 --- a/scripts/postgres/seed-1gb.sql +++ b/scripts/postgres/seed-1gb.sql @@ -60,7 +60,7 @@ SELECT ) FROM users u JOIN generate_series(1, 30) AS p(post_no) - ON u.id <= 300000; + ON u.id <= 500000; -- ============================================================ -- OPTIONAL: FORCE DISK MATERIALIZATION diff --git a/src/services/api/endpoints/agent/mod.rs b/src/services/api/endpoints/agent/mod.rs index d6293ca..161e4e6 100644 --- a/src/services/api/endpoints/agent/mod.rs +++ b/src/services/api/endpoints/agent/mod.rs @@ -1,2 +1,3 @@ pub mod status; -pub mod backup; \ No newline at end of file +pub mod backup; +pub mod restore; \ No newline at end of file diff --git a/src/services/api/endpoints/agent/restore/mod.rs b/src/services/api/endpoints/agent/restore/mod.rs new file mode 100644 index 0000000..82d53f7 --- /dev/null +++ b/src/services/api/endpoints/agent/restore/mod.rs @@ -0,0 +1,33 @@ +use crate::services::api::models::agent::restore::ResultRestoreResponse; +use crate::services::api::{ApiClient, ApiError}; +use anyhow::Result; +use reqwest::Method; +use serde::Serialize; + +#[derive(Serialize)] +pub struct ResultRestoreRequest { + #[serde(rename = "generatedId")] + pub generated_id: String, + pub status: String, +} + +impl ApiClient { + pub async fn restore_result( + &self, + agent_id: impl Into, + generated_id: impl Into, + status: impl Into, + ) -> Result, ApiError> { + let body = ResultRestoreRequest { + generated_id: generated_id.into(), + status: status.into(), + }; + + let agent_id = agent_id.into(); + + let path = format!("/agent/{}/restore", agent_id); + + self.request_with_body(Method::POST, path.as_str(), &body) + .await + } +} diff --git a/src/services/api/models/agent/mod.rs b/src/services/api/models/agent/mod.rs index d6293ca..161e4e6 100644 --- a/src/services/api/models/agent/mod.rs +++ b/src/services/api/models/agent/mod.rs @@ -1,2 +1,3 @@ pub mod status; -pub mod backup; \ No newline at end of file +pub mod backup; +pub mod restore; \ No newline at end of file diff --git a/src/services/api/models/agent/restore.rs b/src/services/api/models/agent/restore.rs new file mode 100644 index 0000000..288d4c8 --- /dev/null +++ b/src/services/api/models/agent/restore.rs @@ -0,0 +1,7 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +pub struct ResultRestoreResponse { + pub message: String, + pub status: bool, +} \ No newline at end of file diff --git a/src/services/backup.rs b/src/services/backup.rs deleted file mode 100644 index 8a501e4..0000000 --- a/src/services/backup.rs +++ /dev/null @@ -1,415 +0,0 @@ -#![allow(dead_code)] - -use crate::core::context::Context as CoreContext; -use crate::domain::factory::DatabaseFactory; -use crate::services::api::models::agent::status::DatabaseStorage; -use crate::services::config::{DatabaseConfig, DatabasesConfig, DbType}; -use crate::services::storage; -use crate::utils::common::BackupMethod; -use crate::utils::compress::compress_to_tar_gz_large; -use anyhow::Result; -use futures::future::join_all; -use std::path::{Path, PathBuf}; -use std::sync::Arc; -use tempfile::TempDir; -use tracing::{error, info}; -use crate::utils::locks::FileLock; - -#[derive(Debug, Clone)] -pub struct BackupResult { - pub generated_id: String, - pub db_type: DbType, - pub status: String, - pub backup_file: Option, - pub code: Option, -} - -#[derive(Debug)] -pub struct UploadResult { - pub storage_id: String, - pub success: bool, - pub error: Option, - pub remote_file_path: Option, - pub total_size: Option, -} - -pub struct BackupService { - ctx: Arc, -} - -impl BackupService { - pub fn new(ctx: Arc) -> Self { - Self { ctx } - } - - pub async fn dispatch( - &self, - generated_id: &String, - config: &DatabasesConfig, - method: BackupMethod, - storages: &Vec, - encrypt: bool, - ) { - if let Some(cfg) = config - .databases - .iter() - .find(|c| c.generated_id == generated_id.as_str()) - { - let db_cfg = cfg.clone(); - let ctx = self.ctx.clone(); - let storages_clone = storages.clone(); - let generated_id_clone = generated_id.clone(); - - tokio::spawn(async move { - match TempDir::new() { - Ok(temp_dir) => { - match FileLock::is_locked(&generated_id_clone).await { - Ok(true) => { - error!("Backup already running for {}", &generated_id_clone); - return; - } - Ok(false) => { - match ctx - .api - .backup_create( - method.clone().to_string(), - ctx.edge_key.agent_id.clone(), - &generated_id_clone, - ) - .await - { - Ok(backup_created_result) => { - info!("Backup created successfully"); - let tmp_path = temp_dir.path().to_path_buf(); - info!("Created temp directory {}", tmp_path.display()); - match BackupService::run(db_cfg, &tmp_path).await { - Ok(mut result) => { - let backup_id = backup_created_result.unwrap().backup.id; - - if result.status == "failed" { - error!("Backup failed early for {}", result.generated_id); - let service = BackupService { ctx: ctx.clone() }; - let _ = service - .send_result(result, vec![], &backup_id) - .await; - return; - } - - - if let Some(backup_file) = result.backup_file.take() { - match compress_to_tar_gz_large(&backup_file).await { - Ok(compression_result) => { - result.backup_file = - Some(compression_result.compressed_path); - let service = BackupService { ctx: ctx.clone() }; - match service - .upload( - result.clone(), - method, - storages_clone.clone(), - encrypt, - &backup_id, - ) - .await - { - Ok(upload_result) => { - match service - .send_result( - result, - upload_result, - &backup_id, - ) - .await - { - Ok(_) => { - return; - } - Err(e) => { - error!( - "Failed to send backup result: {}", - e - ); - } - } - } - Err(e) => { - error!( - "Failed to upload backup files: {}", - e - ); - } - } - } - Err(e) => { - error!( - "Failed to compress backup file : {}", - e - ); - } - } - } else { - error!("No backup file generated"); - } - } - Err(e) => error!("BackupService run failed: {}", e), - } - // TempDir is automatically deleted when dropped here - } - Err(e) => error!("Backup creation failed: {}", e), - } - } - Err(e) => error!("An error occurred while checking lock : {}", e), - } - } - Err(e) => error!("Failed to create temp dir: {}", e), - } - }); - } - } - - pub async fn run(cfg: DatabaseConfig, tmp_path: &Path) -> Result { - let db_instance = DatabaseFactory::create_for_backup(cfg.clone()).await; - let generated_id = cfg.generated_id.clone(); - let db_type = cfg.db_type.clone(); - - - let reachable = match db_instance.ping().await { - Ok(v) => v, - Err(e) => { - error!("Ping failed: {}", e); - return Err(e.into()); - } - }; - - - info!("Reachable: {}", reachable); - if !reachable { - return Ok(BackupResult { - generated_id, - db_type, - status: "failed".into(), - backup_file: None, - code: None, - }); - } - - match db_instance.backup(tmp_path).await { - Ok(file) => Ok(BackupResult { - generated_id, - db_type, - status: "success".into(), - backup_file: Some(file), - code: None, - }), - Err(e) => match e.to_string().as_str() { - "backup_already_in_progress" => Ok(BackupResult { - generated_id, - db_type, - status: "failed".into(), - backup_file: None, - code: Some(e.to_string()), - }), - _ => Ok(BackupResult { - generated_id, - db_type, - status: "failed".into(), - backup_file: None, - code: None, - }), - }, - } - } - - pub async fn upload( - &self, - result: BackupResult, - method: BackupMethod, - storages: Vec, - encrypt: bool, - backup_id: &String, - ) -> Result> { - if result.code.as_deref() == Some("backup_already_in_progress") { - info!("Skipping send: backup already in progress"); - anyhow::bail!("backup_already_in_progres"); - } - - let upload_futures = storages.into_iter().map(|storage| { - info!( - "Uploading storage -> {:?} for {:?}", - storage.provider, storage.id - ); - let provider = storage::get_provider(&storage); - let result_clone = result.clone(); - let ctx_clone = self.ctx.clone(); - let storages_clone = storage.clone(); - let storage_id = storages_clone.id; - let generated_id = result_clone.generated_id.clone(); - - async move { - match self - .ctx - .api - .backup_upload_init( - self.ctx.edge_key.agent_id.clone(), - generated_id.clone(), - storage_id.clone(), - backup_id, - ) - .await - { - Ok(upload_init_result) => { - info!("Uploading init result: {:#?}", upload_init_result); - let backup_storage_id = upload_init_result.unwrap().backup_storage.id.clone(); - match provider { - Some(provider) => { - let upload_result = provider - .upload( - ctx_clone, - result_clone, - method, - &storage, - Some(encrypt), - ) - .await; - - let status = if upload_result.success { - "success" - } else { - "failed" - }; - - if status != "success" { - return upload_result; - } - - info!("Storage {} uploaded to remote path {:?}", storage_id, upload_result.remote_file_path); - - let (remote_path, total_size) = match ( - &upload_result.remote_file_path, - upload_result.total_size, - ) { - (Some(path), Some(size)) => (path.clone(), size), - _ => { - return UploadResult { - storage_id: storage_id.clone(), - success: false, - error: Some("remote_file_path or total_size missing".to_string()), - remote_file_path: None, - total_size: None, - } - } - }; - - match self.ctx.api.backup_upload_status( - self.ctx.edge_key.agent_id.clone(), - generated_id.clone(), - backup_storage_id, - status, - remote_path, - total_size, - backup_id, - ).await { - Ok(_) => { - upload_result - } - Err(err) => { - error!( - "backup_upload_status failed (generated_id={}, storage_id={}): {}", - generated_id, storage_id, err - ); - UploadResult { - storage_id: storage_id.clone(), - success: false, - error: Some(err.to_string()), - remote_file_path: None, - total_size: None, - } - } - } - } - None => { - error!("Skipping storage due to missing provider"); - UploadResult { - storage_id: storage_id.clone(), - success: false, - error: Some( - "Skipping storage due to missing provider".to_string(), - ), - remote_file_path: None, - total_size: None, - } - } - } - } - Err(e) => { - error!( - "Unable to create the storage backup on remote server : {}", - e - ); - UploadResult { - storage_id: storage_id.clone(), - success: false, - error: Some( - "Unable to create the storage backup on remote server".to_string(), - ), - remote_file_path: None, - total_size: None, - } - } - } - } - }); - - let results: Vec = join_all(upload_futures).await; - info!("Upload results: {:#?}", results); - - Ok(results) - } - - pub async fn send_result( - &self, - result: BackupResult, - upload_results: Vec, - backup_id: &String, - ) -> Result<()> { - let status = if upload_results.iter().any(|r| r.success) { - "success" - } else { - "failed" - }; - - let file_size = if status == "failed" { - None - } else { - let mut sum = 0u64; - let mut count = 0u64; - - for size in upload_results.iter().filter_map(|r| r.total_size) { - sum += size; - count += 1; - } - - if count == 0 { - None - } else { - Some(sum / count) - } - }; - - match self - .ctx - .api - .backup_update(self.ctx.edge_key.agent_id.clone(), backup_id, status, file_size, &result.generated_id) - .await - { - Ok(_result) => Ok(()), - Err(e) => { - error!( - "backup_update failed (generated_id={}, backup_id={}): {}", - &result.generated_id, &backup_id, e - ); - Err(e.into()) - } - } - } -} diff --git a/src/services/backup/compressor.rs b/src/services/backup/compressor.rs new file mode 100644 index 0000000..d7ca3e3 --- /dev/null +++ b/src/services/backup/compressor.rs @@ -0,0 +1,20 @@ +use super::service::BackupService; +use crate::utils::compress::compress_to_tar_gz_large; +use std::path::PathBuf; +use anyhow::Result; + +impl BackupService { + + pub async fn compress_backup( + &self, + backup_file: Option, + ) -> Result { + + let file = backup_file + .ok_or_else(|| anyhow::anyhow!("No backup file generated"))?; + + let compression = compress_to_tar_gz_large(&file).await?; + + Ok(compression.compressed_path) + } +} \ No newline at end of file diff --git a/src/services/backup/dispatcher.rs b/src/services/backup/dispatcher.rs new file mode 100644 index 0000000..b6aa2bc --- /dev/null +++ b/src/services/backup/dispatcher.rs @@ -0,0 +1,44 @@ +use super::service::BackupService; +use crate::services::config::DatabasesConfig; +use crate::services::api::models::agent::status::DatabaseStorage; +use crate::utils::common::BackupMethod; +use tracing::error; + +impl BackupService { + + pub async fn dispatch( + &self, + generated_id: &String, + config: &DatabasesConfig, + method: BackupMethod, + storages: &Vec, + encrypt: bool, + ) { + + let Some(cfg) = config + .databases + .iter() + .find(|c| c.generated_id == generated_id.as_str()) + else { + error!("Database config not found for {}", generated_id); + return; + }; + + let service = Self { + ctx: self.ctx.clone(), + }; + + let db_cfg = cfg.clone(); + let storages = storages.clone(); + let generated_id = generated_id.clone(); + + tokio::spawn(async move { + if let Err(e) = service + .execute_backup(generated_id, db_cfg, method, storages, encrypt) + .await + { + error!("Backup execution failed: {}", e); + } + }); + } +} \ No newline at end of file diff --git a/src/services/backup/executor.rs b/src/services/backup/executor.rs new file mode 100644 index 0000000..203b21f --- /dev/null +++ b/src/services/backup/executor.rs @@ -0,0 +1,49 @@ +use super::service::BackupService; +use crate::services::config::DatabaseConfig; +use crate::services::api::models::agent::status::DatabaseStorage; +use crate::utils::common::BackupMethod; +use crate::utils::locks::FileLock; + +use tempfile::TempDir; +use anyhow::Result; + +impl BackupService { + + pub async fn execute_backup( + &self, + generated_id: String, + db_cfg: DatabaseConfig, + method: BackupMethod, + storages: Vec, + encrypt: bool, + ) -> Result<()> { + + if FileLock::is_locked(&generated_id).await? { + anyhow::bail!("backup already running"); + } + + let backup = self.create_backup_record(&generated_id, &method).await?; + let backup_id = backup.backup.id; + + let temp_dir = TempDir::new()?; + let tmp_path = temp_dir.path(); + + let mut result = Self::run(db_cfg, tmp_path).await?; + + if result.status == "failed" { + self.send_result(result, vec![], &backup_id).await?; + return Ok(()); + } + + let compressed = self.compress_backup(result.backup_file.take()).await?; + result.backup_file = Some(compressed); + + let uploads = self + .upload(result.clone(), method, storages, encrypt, &backup_id) + .await?; + + self.send_result(result, uploads, &backup_id).await?; + + Ok(()) + } +} \ No newline at end of file diff --git a/src/services/backup/helpers.rs b/src/services/backup/helpers.rs new file mode 100644 index 0000000..a5a0130 --- /dev/null +++ b/src/services/backup/helpers.rs @@ -0,0 +1,26 @@ +use super::service::BackupService; +use crate::utils::common::BackupMethod; +use anyhow::{Result, anyhow}; +use crate::services::api::models::agent::backup::BackupResponse; + +impl BackupService { + + pub async fn create_backup_record( + &self, + generated_id: &str, + method: &BackupMethod, + ) -> Result { + + let response = self + .ctx + .api + .backup_create( + method.to_string(), + self.ctx.edge_key.agent_id.clone(), + generated_id, + ) + .await?; + + response.ok_or_else(|| anyhow!("backup_create returned empty response")) + } +} \ No newline at end of file diff --git a/src/services/backup/mod.rs b/src/services/backup/mod.rs new file mode 100644 index 0000000..2e1b5f0 --- /dev/null +++ b/src/services/backup/mod.rs @@ -0,0 +1,11 @@ +pub mod service; +pub mod dispatcher; +pub mod executor; +pub mod compressor; +pub mod uploader; +pub mod result; +pub mod models; +pub mod helpers; +pub mod runner; + +pub use service::BackupService; \ No newline at end of file diff --git a/src/services/backup/models.rs b/src/services/backup/models.rs new file mode 100644 index 0000000..f9db440 --- /dev/null +++ b/src/services/backup/models.rs @@ -0,0 +1,22 @@ +#![allow(dead_code)] + +use std::path::PathBuf; +use crate::services::config::DbType; + +#[derive(Debug, Clone)] +pub struct BackupResult { + pub generated_id: String, + pub db_type: DbType, + pub status: String, + pub backup_file: Option, + pub code: Option, +} + +#[derive(Debug)] +pub struct UploadResult { + pub storage_id: String, + pub success: bool, + pub error: Option, + pub remote_file_path: Option, + pub total_size: Option, +} \ No newline at end of file diff --git a/src/services/backup/result.rs b/src/services/backup/result.rs new file mode 100644 index 0000000..2de5588 --- /dev/null +++ b/src/services/backup/result.rs @@ -0,0 +1,45 @@ +use super::models::{BackupResult, UploadResult}; +use super::service::BackupService; +use crate::services::api::ApiError; +use crate::services::api::models::agent::backup::BackupResponse; +use anyhow::Result; +use tracing::error; + +impl BackupService { + pub async fn send_result( + &self, + result: BackupResult, + upload_results: Vec, + backup_id: &String, + ) -> Result, ApiError> { + let status = if upload_results.iter().any(|r| r.success) { + "success" + } else { + "failed" + }; + + let file_size = upload_results + .iter() + .filter_map(|r| r.total_size) + .reduce(|a, b| a + b) + .map(|sum| sum / upload_results.len() as u64); + + self.ctx + .api + .backup_update( + self.ctx.edge_key.agent_id.clone(), + backup_id, + status, + file_size, + &result.generated_id, + ) + .await + .map_err(|e| { + error!( + "backup_update failed (generated_id={}, backup_id={}): {}", + result.generated_id, backup_id, e + ); + e.into() + }) + } +} diff --git a/src/services/backup/runner.rs b/src/services/backup/runner.rs new file mode 100644 index 0000000..5a46b24 --- /dev/null +++ b/src/services/backup/runner.rs @@ -0,0 +1,70 @@ +use super::models::BackupResult; +use super::service::BackupService; + +use crate::domain::factory::DatabaseFactory; +use crate::services::config::DatabaseConfig; + +use anyhow::Result; +use std::path::Path; +use tracing::{error, info}; + +impl BackupService { + + pub async fn run( + cfg: DatabaseConfig, + tmp_path: &Path, + ) -> Result { + + let db = DatabaseFactory::create_for_backup(cfg.clone()).await; + + let generated_id = cfg.generated_id.clone(); + let db_type = cfg.db_type.clone(); + + let reachable = match db.ping().await { + Ok(v) => v, + Err(e) => { + error!("Ping failed: {}", e); + return Err(e.into()); + } + }; + + info!("Reachable: {}", reachable); + + if !reachable { + return Ok(BackupResult { + generated_id, + db_type, + status: "failed".into(), + backup_file: None, + code: None, + }); + } + + match db.backup(tmp_path).await { + + Ok(file) => Ok(BackupResult { + generated_id, + db_type, + status: "success".into(), + backup_file: Some(file), + code: None, + }), + + Err(e) if e.to_string() == "backup_already_in_progress" => Ok(BackupResult { + generated_id, + db_type, + status: "failed".into(), + backup_file: None, + code: Some("backup_already_in_progress".into()), + }), + + Err(_) => Ok(BackupResult { + generated_id, + db_type, + status: "failed".into(), + backup_file: None, + code: None, + }), + } + } +} \ No newline at end of file diff --git a/src/services/backup/service.rs b/src/services/backup/service.rs new file mode 100644 index 0000000..043e88d --- /dev/null +++ b/src/services/backup/service.rs @@ -0,0 +1,12 @@ +use std::sync::Arc; +use crate::core::context::Context as CoreContext; + +pub struct BackupService { + pub ctx: Arc, +} + +impl BackupService { + pub fn new(ctx: Arc) -> Self { + Self { ctx } + } +} \ No newline at end of file diff --git a/src/services/backup/uploader.rs b/src/services/backup/uploader.rs new file mode 100644 index 0000000..8136f27 --- /dev/null +++ b/src/services/backup/uploader.rs @@ -0,0 +1,181 @@ +use super::service::BackupService; +use super::models::{BackupResult, UploadResult}; + +use crate::services::storage; +use crate::services::api::models::agent::status::DatabaseStorage; +use crate::utils::common::BackupMethod; + +use futures::future::join_all; +use anyhow::{Result, bail}; +use tracing::{info, error}; + +impl BackupService { + + pub async fn upload( + &self, + result: BackupResult, + method: BackupMethod, + storages: Vec, + encrypt: bool, + backup_id: &String, + ) -> Result> { + + if result.code.as_deref() == Some("backup_already_in_progress") { + info!("Skipping send: backup already in progress"); + bail!("backup_already_in_progress"); + } + + let ctx = self.ctx.clone(); + + let futures = storages.into_iter().map(|storage| { + + let ctx_clone = ctx.clone(); + let result_clone = result.clone(); + let provider = storage::get_provider(&storage); + + let storage_id = storage.id.clone(); + let generated_id = result_clone.generated_id.clone(); + + async move { + + info!("Uploading storage -> {:?} for {:?}", storage.provider, storage_id); + + /* + INIT STEP + */ + let init = match ctx_clone.api + .backup_upload_init( + ctx_clone.edge_key.agent_id.clone(), + generated_id.clone(), + storage_id.clone(), + backup_id, + ) + .await + { + Ok(v) => v, + Err(e) => { + error!("backup_upload_init failed: {}", e); + + return UploadResult { + storage_id, + success: false, + error: Some("backup_upload_init failed".into()), + remote_file_path: None, + total_size: None, + }; + } + }; + + let backup_storage_id = match init { + Some(v) => v.backup_storage.id, + None => { + return UploadResult { + storage_id, + success: false, + error: Some("backup_upload_init returned empty response".into()), + remote_file_path: None, + total_size: None, + }; + } + }; + + /* + PROVIDER CHECK + */ + let Some(provider) = provider else { + error!("Skipping storage due to missing provider"); + + return UploadResult { + storage_id, + success: false, + error: Some("missing provider".into()), + remote_file_path: None, + total_size: None, + }; + }; + + /* + STORAGE UPLOAD + */ + let upload_result = provider + .upload( + ctx_clone.clone(), + result_clone, + method, + &storage, + Some(encrypt), + ) + .await; + + let status = if upload_result.success { "success" } else { "failed" }; + + if status != "success" { + return upload_result; + } + + info!( + "Storage {} uploaded to remote path {:?}", + storage_id, + upload_result.remote_file_path + ); + + /* + METADATA VALIDATION + */ + let (remote_path, total_size) = match ( + &upload_result.remote_file_path, + upload_result.total_size, + ) { + (Some(path), Some(size)) => (path.clone(), size), + _ => { + return UploadResult { + storage_id, + success: false, + error: Some("remote_file_path or total_size missing".into()), + remote_file_path: None, + total_size: None, + }; + } + }; + + /* + STATUS UPDATE + */ + match ctx_clone.api.backup_upload_status( + ctx_clone.edge_key.agent_id.clone(), + generated_id, + backup_storage_id, + status, + remote_path, + total_size, + backup_id, + ).await { + + Ok(_) => upload_result, + + Err(err) => { + error!( + "backup_upload_status failed (storage_id={}): {}", + storage_id, + err + ); + + UploadResult { + storage_id, + success: false, + error: Some(err.to_string()), + remote_file_path: None, + total_size: None, + } + } + } + } + }); + + let results: Vec = join_all(futures).await; + + info!("Upload results: {:#?}", results); + + Ok(results) + } +} \ No newline at end of file diff --git a/src/services/restore.rs b/src/services/restore.rs deleted file mode 100644 index 6b05643..0000000 --- a/src/services/restore.rs +++ /dev/null @@ -1,246 +0,0 @@ -#![allow(dead_code)] -#![warn(unused_assignments)] -use crate::core::context::Context; -use crate::domain::factory::DatabaseFactory; -use crate::services::api::models::agent::status::DatabaseStatus; -use crate::services::config::{DatabaseConfig, DatabasesConfig}; -use crate::utils::compress::decompress_large_tar_gz; -use crate::utils::file::decrypt_file_stream_gcm; -use anyhow::Result; -use reqwest::{Client, Url}; -use serde::Serialize; -use std::path::{Path, PathBuf}; -use std::sync::Arc; -use tempfile::TempDir; -use tracing::{error, info}; - -#[derive(Debug, Serialize)] -pub struct RestoreResult { - #[serde(rename = "generatedId")] - pub generated_id: String, - pub status: String, -} - -pub struct RestoreService { - ctx: Arc, -} - -impl RestoreService { - pub fn new(ctx: Arc) -> Self { - Self { ctx } - } - - pub async fn dispatch(&self, db: &DatabaseStatus, config: &DatabasesConfig) { - if let Some(cfg) = config - .databases - .iter() - .find(|c| c.generated_id == db.generated_id) - { - let db_cfg = cfg.clone(); - let ctx_clone = self.ctx.clone(); - let file_to_restore = db.data.restore.file.clone(); - if file_to_restore.is_none() { - error!("restore file not found"); - return; - } - tokio::spawn(async move { - match TempDir::new() { - Ok(temp_dir) => { - let tmp_path = temp_dir.path().to_path_buf(); - info!("Created temp directory {}", tmp_path.display()); - match RestoreService::run( - &ctx_clone, - db_cfg, - &tmp_path, - &file_to_restore.unwrap(), - ) - .await - { - Ok(result) => { - let service = RestoreService { ctx: ctx_clone }; - service.send_result(result).await; - } - Err(e) => error!("Restoration error {}", e), - } - // TempDir is automatically deleted when dropped - } - Err(e) => error!("Failed to create temp dir: {}", e), - } - }); - } - } - - pub async fn run( - ctx: &Arc, - cfg: DatabaseConfig, - tmp_path: &Path, - file_url: &str, - ) -> Result { - let generated_id = cfg.generated_id.clone(); - - info!("File url: {}", file_url); - - let client = Client::new(); - let response = client.get(file_url).send().await?; - - if !response.status().is_success() { - error!("Backup download failed with status {}", response.status()); - return Ok(RestoreResult { - generated_id, - status: "failed".into(), - }); - } - - let filename_from_header = response - .headers() - .get(reqwest::header::CONTENT_DISPOSITION) - .and_then(|v| v.to_str().ok()) - .and_then(|s| s.split("filename=").nth(1)) - .map(|f| f.trim_matches('"').to_string()); - - let filename_from_url = Url::parse(file_url).ok().and_then(|u| { - u.path_segments()? - .last() - .filter(|s| !s.is_empty()) - .map(|s| s.to_string()) - }); - - let filename = filename_from_header - .or(filename_from_url) - .unwrap_or_else(|| "downloaded_file".to_string()); - - info!("File name: {}", filename); - - let bytes = response.bytes().await?; - - let is_legacy_file = if filename.ends_with(".sql") { - true - } else if filename.ends_with(".dump") { - true - } else { - false - }; - let downloaded_file = tmp_path.join(&filename); - tokio::fs::write(&downloaded_file, &bytes).await?; - info!("Backup downloaded to {}", downloaded_file.display()); - - let backup_file_path: PathBuf = if !is_legacy_file { - let encrypted = if filename.ends_with(".tar.gz") { - false - } else if filename.ends_with(".tar.gz.enc") { - true - } else { - return Ok(RestoreResult { - generated_id, - status: "failed".into(), - }); - }; - - info!("Encrypted: {}", encrypted); - - let mut compressed_archive = downloaded_file.clone(); - - if encrypted { - let new_name = downloaded_file - .file_name() - .and_then(|n| n.to_str()) - .and_then(|n| n.strip_suffix(".enc")) - .ok_or_else(|| anyhow::anyhow!("Invalid encrypted filename"))?; - - let new_compressed_archive = tmp_path.join(new_name); - - decrypt_file_stream_gcm( - downloaded_file, - new_compressed_archive.clone(), - ctx.edge_key.master_key_b64.clone(), - ) - .await - .map_err(|e| { - error!("Failed to decrypt file: {}", e); - e - })?; - - compressed_archive = new_compressed_archive; - } - - let decompressed_files = - decompress_large_tar_gz(compressed_archive.as_path(), tmp_path).await?; - - if decompressed_files.is_empty() { - return Ok(RestoreResult { - generated_id, - status: "failed".into(), - }); - } - - if decompressed_files.len() == 1 { - decompressed_files[0].clone() - } else { - compressed_archive - } - } else { - downloaded_file.clone() - }; - - let db_instance = DatabaseFactory::create_for_restore(cfg.clone(), &backup_file_path).await; - let reachable = db_instance.ping().await.unwrap_or(false); - info!("Reachable: {}", reachable); - if !reachable { - return Ok(RestoreResult { - generated_id, - status: "failed".into(), - }); - } - - match db_instance.restore(&backup_file_path).await { - Ok(_) => Ok(RestoreResult { - generated_id, - status: "success".into(), - }), - Err(e) => { - error!("Restore failed: {:?}", e); - Ok(RestoreResult { - generated_id, - status: "failed".into(), - }) - } - } - } - - // TODO : update with ctx api manager - pub async fn send_result(&self, result: RestoreResult) { - info!( - "[RestoreService] DB: {} | Status: {}", - result.generated_id, result.status, - ); - - let client = reqwest::Client::new(); - let url = format!( - "{}/api/agent/{}/restore", - self.ctx.edge_key.server_url, self.ctx.edge_key.agent_id - ); - - let body = RestoreResult { - generated_id: result.generated_id, - status: result.status, - }; - - match client.post(&url).json(&body).send().await { - Ok(resp) => { - let status = resp.status(); - if status.is_success() { - info!("Restoration result sent successfully"); - } else { - let text = resp.text().await.unwrap_or_default(); - error!( - "Restoration result failed, status: {}, body: {}", - status, text - ); - } - } - Err(e) => { - error!("Failed to send restoration result: {}", e); - } - } - } -} diff --git a/src/services/restore/archive.rs b/src/services/restore/archive.rs new file mode 100644 index 0000000..6cb457c --- /dev/null +++ b/src/services/restore/archive.rs @@ -0,0 +1,61 @@ +use super::service::RestoreService; + +use crate::utils::compress::decompress_large_tar_gz; +use crate::utils::file::decrypt_file_stream_gcm; + +use anyhow::Result; +use std::path::{Path, PathBuf}; + +impl RestoreService { + + pub async fn prepare_archive( + &self, + downloaded_file: PathBuf, + tmp_path: &Path, + ) -> Result { + + let filename = downloaded_file + .file_name() + .unwrap() + .to_string_lossy() + .to_string(); + + let is_legacy = filename.ends_with(".sql") || filename.ends_with(".dump"); + + if is_legacy { + return Ok(downloaded_file); + } + + let encrypted = filename.ends_with(".tar.gz.enc"); + + let mut archive = downloaded_file.clone(); + + if encrypted { + + let new_name = filename.strip_suffix(".enc").unwrap(); + + let decrypted = tmp_path.join(new_name); + + decrypt_file_stream_gcm( + downloaded_file, + decrypted.clone(), + self.ctx.edge_key.master_key_b64.clone(), + ) + .await?; + + archive = decrypted; + } + + let files = decompress_large_tar_gz(archive.as_path(), tmp_path).await?; + + if files.is_empty() { + anyhow::bail!("archive empty"); + } + + if files.len() == 1 { + Ok(files[0].clone()) + } else { + Ok(archive) + } + } +} \ No newline at end of file diff --git a/src/services/restore/dispatcher.rs b/src/services/restore/dispatcher.rs new file mode 100644 index 0000000..12a0fd5 --- /dev/null +++ b/src/services/restore/dispatcher.rs @@ -0,0 +1,42 @@ +use super::service::RestoreService; +use crate::services::config::DatabasesConfig; +use crate::services::api::models::agent::status::DatabaseStatus; + +use tracing::error; + +impl RestoreService { + + pub async fn dispatch(&self, db: &DatabaseStatus, config: &DatabasesConfig) { + + let Some(cfg) = config + .databases + .iter() + .find(|c| c.generated_id == db.generated_id) + else { + error!("Database config not found"); + return; + }; + + let Some(file_to_restore) = db.data.restore.file.clone() else { + error!("restore file not found"); + return; + }; + + let service = Self { + ctx: self.ctx.clone(), + }; + + let db_cfg = cfg.clone(); + + tokio::spawn(async move { + + if let Err(e) = service + .execute_restore(db_cfg, file_to_restore) + .await + { + error!("Restore failed: {}", e); + } + + }); + } +} \ No newline at end of file diff --git a/src/services/restore/downloader.rs b/src/services/restore/downloader.rs new file mode 100644 index 0000000..6646b8c --- /dev/null +++ b/src/services/restore/downloader.rs @@ -0,0 +1,53 @@ +use super::service::RestoreService; + +use reqwest::{Client, Url}; +use anyhow::Result; +use std::path::{Path, PathBuf}; +use tracing::info; + +impl RestoreService { + + pub async fn download_backup( + &self, + file_url: &str, + tmp_path: &Path, + ) -> Result { + + let client = Client::new(); + + let response = client.get(file_url).send().await?; + + if !response.status().is_success() { + anyhow::bail!("download failed"); + } + + let filename_from_header = response + .headers() + .get(reqwest::header::CONTENT_DISPOSITION) + .and_then(|v| v.to_str().ok()) + .and_then(|s| s.split("filename=").nth(1)) + .map(|f| f.trim_matches('"').to_string()); + + + let filename_from_url = Url::parse(file_url).ok().and_then(|u| { + u.path_segments()? + .last() + .filter(|s| !s.is_empty()) + .map(|s| s.to_string()) + }); + + let filename = filename_from_header + .or(filename_from_url) + .unwrap_or_else(|| "downloaded_file".to_string()); + + let path = tmp_path.join(&filename); + + let bytes = response.bytes().await?; + + tokio::fs::write(&path, &bytes).await?; + + info!("Backup downloaded to {}", path.display()); + + Ok(path) + } +} \ No newline at end of file diff --git a/src/services/restore/executor.rs b/src/services/restore/executor.rs new file mode 100644 index 0000000..4cabb5b --- /dev/null +++ b/src/services/restore/executor.rs @@ -0,0 +1,30 @@ +use super::service::RestoreService; +use crate::services::config::DatabaseConfig; +use tempfile::TempDir; +use anyhow::Result; +use tracing::info; + +impl RestoreService { + + pub async fn execute_restore( + &self, + cfg: DatabaseConfig, + file_url: String, + ) -> Result<()> { + + let temp_dir = TempDir::new()?; + let tmp_path = temp_dir.path(); + + info!("Created temp directory {}", tmp_path.display()); + + let downloaded = self.download_backup(&file_url, tmp_path).await?; + + let backup_file = self.prepare_archive(downloaded, tmp_path).await?; + + let result = self.run_restore(cfg, backup_file).await?; + + self.send_result(result).await; + + Ok(()) + } +} \ No newline at end of file diff --git a/src/services/restore/mod.rs b/src/services/restore/mod.rs new file mode 100644 index 0000000..4ca2ebe --- /dev/null +++ b/src/services/restore/mod.rs @@ -0,0 +1,10 @@ +pub mod service; +pub mod dispatcher; +pub mod executor; +pub mod downloader; +pub mod archive; +pub mod runner; +pub mod result; +pub mod models; + +pub use service::RestoreService; \ No newline at end of file diff --git a/src/services/restore/models.rs b/src/services/restore/models.rs new file mode 100644 index 0000000..e987903 --- /dev/null +++ b/src/services/restore/models.rs @@ -0,0 +1,8 @@ +use serde::Serialize; + +#[derive(Debug, Serialize)] +pub struct RestoreResult { + #[serde(rename = "generatedId")] + pub generated_id: String, + pub status: String, +} \ No newline at end of file diff --git a/src/services/restore/result.rs b/src/services/restore/result.rs new file mode 100644 index 0000000..d7325bf --- /dev/null +++ b/src/services/restore/result.rs @@ -0,0 +1,30 @@ +use super::service::RestoreService; +use super::models::RestoreResult; + +use tracing::{info, error}; + +impl RestoreService { + pub async fn send_result(&self, result: RestoreResult) { + + info!( + "[RestoreService] DB: {} | Status: {}", + result.generated_id, result.status + ); + + match self.ctx + .api + .restore_result( + self.ctx.edge_key.agent_id.clone(), + &result.generated_id, + &result.status, + ) + .await { + Ok(_) => { + info!("Restoration result sent successfully"); + } + Err(e) => { + error!("Failed to send restoration result: {}", e); + } + } + } +} \ No newline at end of file diff --git a/src/services/restore/runner.rs b/src/services/restore/runner.rs new file mode 100644 index 0000000..eaefb02 --- /dev/null +++ b/src/services/restore/runner.rs @@ -0,0 +1,51 @@ +use super::service::RestoreService; +use super::models::RestoreResult; + +use crate::domain::factory::DatabaseFactory; +use crate::services::config::DatabaseConfig; + +use anyhow::Result; +use std::path::PathBuf; +use tracing::{info, error}; + +impl RestoreService { + + pub async fn run_restore( + &self, + cfg: DatabaseConfig, + backup_file: PathBuf, + ) -> Result { + + let generated_id = cfg.generated_id.clone(); + + let db = DatabaseFactory::create_for_restore(cfg.clone(), &backup_file).await; + + let reachable = db.ping().await.unwrap_or(false); + + info!("Reachable: {}", reachable); + + if !reachable { + return Ok(RestoreResult { + generated_id, + status: "failed".into(), + }); + } + + match db.restore(&backup_file).await { + + Ok(_) => Ok(RestoreResult { + generated_id, + status: "success".into(), + }), + + Err(e) => { + error!("Restore failed: {:?}", e); + + Ok(RestoreResult { + generated_id, + status: "failed".into(), + }) + } + } + } +} \ No newline at end of file diff --git a/src/services/restore/service.rs b/src/services/restore/service.rs new file mode 100644 index 0000000..5b6be8d --- /dev/null +++ b/src/services/restore/service.rs @@ -0,0 +1,12 @@ +use std::sync::Arc; +use crate::core::context::Context; + +pub struct RestoreService { + pub ctx: Arc, +} + +impl RestoreService { + pub fn new(ctx: Arc) -> Self { + Self { ctx } + } +} \ No newline at end of file diff --git a/src/services/storage/mod.rs b/src/services/storage/mod.rs index 695d22b..e44d142 100644 --- a/src/services/storage/mod.rs +++ b/src/services/storage/mod.rs @@ -1,7 +1,6 @@ pub mod providers; use crate::core::context::Context; -use crate::services::backup::{BackupResult, UploadResult}; use crate::utils::common::BackupMethod; use async_trait::async_trait; use providers::local; @@ -10,6 +9,7 @@ use providers::google_drive; use std::sync::Arc; use tracing::{error, info}; use crate::services::api::models::agent::status::DatabaseStorage; +use crate::services::backup::models::{BackupResult, UploadResult}; #[async_trait] pub trait StorageProvider: Send + Sync { diff --git a/src/services/storage/providers/google_drive/mod.rs b/src/services/storage/providers/google_drive/mod.rs index 277eb4b..c5182d5 100644 --- a/src/services/storage/providers/google_drive/mod.rs +++ b/src/services/storage/providers/google_drive/mod.rs @@ -3,7 +3,6 @@ mod models; use crate::core::context::Context; use crate::services::api::models::agent::status::DatabaseStorage; -use crate::services::backup::{BackupResult, UploadResult}; use crate::services::storage::StorageProvider; use crate::utils::common::BackupMethod; use crate::utils::file::{full_file_name, full_file_path}; @@ -12,6 +11,7 @@ use async_trait::async_trait; use std::sync::Arc; use tokio::fs; use tracing::{error, info}; +use crate::services::backup::models::{BackupResult, UploadResult}; use crate::services::storage::providers::google_drive::helpers::{upload_stream_to_google_drive}; use crate::services::storage::providers::google_drive::models::GoogleDriveProviderConfig; diff --git a/src/services/storage/providers/local.rs b/src/services/storage/providers/local.rs index f4a0777..80eae97 100644 --- a/src/services/storage/providers/local.rs +++ b/src/services/storage/providers/local.rs @@ -1,6 +1,5 @@ use crate::core::context::Context; use crate::services::api::models::agent::status::DatabaseStorage; -use crate::services::backup::{BackupResult, UploadResult}; use crate::services::storage::StorageProvider; use crate::utils::common::BackupMethod; use crate::utils::file::{full_file_name, full_file_path}; @@ -11,6 +10,7 @@ use reqwest::header::{HeaderMap, HeaderValue}; use std::sync::Arc; use tokio::fs; use tracing::error; +use crate::services::backup::models::{BackupResult, UploadResult}; pub struct LocalProvider; diff --git a/src/services/storage/providers/s3/mod.rs b/src/services/storage/providers/s3/mod.rs index bc1430d..7479d48 100644 --- a/src/services/storage/providers/s3/mod.rs +++ b/src/services/storage/providers/s3/mod.rs @@ -2,7 +2,6 @@ mod models; use crate::core::context::Context; use crate::services::api::models::agent::status::DatabaseStorage; -use crate::services::backup::{BackupResult, UploadResult}; use crate::services::storage::StorageProvider; use crate::services::storage::providers::s3::models::S3ProviderConfig; use crate::utils::common::BackupMethod; @@ -19,6 +18,7 @@ use std::pin::Pin; use std::sync::Arc; use tokio::fs; use tracing::{error, info}; +use crate::services::backup::models::{BackupResult, UploadResult}; pub struct S3Provider {}