diff --git a/.github/workflows/extension_ci.yml b/.github/workflows/extension_ci.yml index 5e30f00e..4b338ab1 100644 --- a/.github/workflows/extension_ci.yml +++ b/.github/workflows/extension_ci.yml @@ -45,56 +45,6 @@ jobs: - name: Clippy run: cargo clippy - test-core: - runs-on: ubuntu-24.04 - services: - postgres: - image: pgvector/pgvector:0.8.0-pg17 - ports: - - 5432:5432 - env: - POSTGRES_PASSWORD: postgres - options: >- - --health-cmd pg_isready - --health-interval 10s - --health-timeout 5s - --health-retries 5 - vector-serve: - image: ghcr.io/chuckhend/vector-serve:latest - ports: - - 3000:3000 - steps: - - uses: actions/checkout@v4 - - name: Install Rust stable toolchain - uses: dtolnay/rust-toolchain@stable - - uses: Swatinem/rust-cache@v2 - with: - prefix-key: "extension-test" - workspaces: | - vectorize - # Additional directories to cache - cache-directories: | - /home/runner/.pgrx - - name: Install sys dependencies - run: | - sudo apt-get update && sudo apt-get install -y postgresql postgresql-contrib libopenblas-dev libreadline-dev - - name: Test Core - run: | - cd ../server && cargo test - - - name: Test Core - Integration - # skip when on external forks - if: github.repository_owner == 'ChuckHend' - env: - OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} - CO_API_KEY: ${{ secrets.CO_API_KEY }} - PORTKEY_API_KEY: ${{ secrets.PORTKEY_API_KEY }} - PORTKEY_VIRTUAL_KEY_OPENAI: ${{ secrets.PORTKEY_VIRTUAL_KEY_OPENAI }} - VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} - DATABASE_URL: postgresql://postgres:postgres@localhost:5432/postgres - run: | - cd ../server && cargo test -- --ignored - test: name: Run tests runs-on: ubuntu-latest diff --git a/.github/workflows/server_ci.yml b/.github/workflows/server_ci.yml new file mode 100644 index 00000000..cdd123cb --- /dev/null +++ b/.github/workflows/server_ci.yml @@ -0,0 +1,61 @@ +name: Vectorize Server CI + +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + lint: + name: Run linters + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust minimal nightly with clippy and rustfmt + uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Cargo format + run: cargo fmt --all --check + - name: Clippy + run: cargo clippy + + test-server: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Install Rust stable toolchain + uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Install sys dependencies + run: | + sudo apt-get update && sudo apt-get install -y postgresql postgresql-contrib libopenblas-dev libreadline-dev + - name: start containers + env: + DATABASE_URL: postgresql://postgres:postgres@postgres:5432/postgres + run: | + docker compose -f docker-compose.server.yml up postgres -d; + sleep 5; + docker compose -f docker-compose.server.yml up vector-serve server --build -d; + - name: Test Core + run: | + cargo test + - name: Test Core - Integration + # skip when on external forks + if: github.repository_owner == 'ChuckHend' + env: + OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }} + CO_API_KEY: ${{ secrets.CO_API_KEY }} + PORTKEY_API_KEY: ${{ secrets.PORTKEY_API_KEY }} + PORTKEY_VIRTUAL_KEY_OPENAI: ${{ secrets.PORTKEY_VIRTUAL_KEY_OPENAI }} + VOYAGE_API_KEY: ${{ secrets.VOYAGE_API_KEY }} + DATABASE_URL: postgresql://postgres:postgres@0.0.0.0:5432/postgres + run: | + cargo test -- --ignored + - name: debugging info + if: failure() + run: | + docker compose logs + docker ps diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..f9e41237 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,4714 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "actix-codec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" +dependencies = [ + "bitflags", + "bytes", + "futures-core", + "futures-sink", + "memchr", + "pin-project-lite", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "actix-cors" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daa239b93927be1ff123eebada5a3ff23e89f0124ccb8609234e5103d5a5ae6d" +dependencies = [ + "actix-utils", + "actix-web", + "derive_more", + "futures-util", + "log", + "once_cell", + "smallvec", +] + +[[package]] +name = "actix-http" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44dfe5c9e0004c623edc65391dfd51daa201e7e30ebd9c9bedf873048ec32bc2" +dependencies = [ + "actix-codec", + "actix-rt", + "actix-service", + "actix-utils", + "base64", + "bitflags", + "brotli", + "bytes", + "bytestring", + "derive_more", + "encoding_rs", + "flate2", + "foldhash", + "futures-core", + "h2 0.3.26", + "http 0.2.12", + "httparse", + "httpdate", + "itoa", + "language-tags", + "local-channel", + "mime", + "percent-encoding", + "pin-project-lite", + "rand 0.9.1", + "sha1", + "smallvec", + "tokio", + "tokio-util", + "tracing", + "zstd", +] + +[[package]] +name = "actix-macros" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" +dependencies = [ + "quote", + "syn 2.0.102", +] + +[[package]] +name = "actix-router" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" +dependencies = [ + "bytestring", + "cfg-if", + "http 0.2.12", + "regex", + "regex-lite", + "serde", + "tracing", +] + +[[package]] +name = "actix-rt" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" +dependencies = [ + "actix-macros", + "futures-core", + "tokio", +] + +[[package]] +name = "actix-server" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502" +dependencies = [ + "actix-rt", + "actix-service", + "actix-utils", + "futures-core", + "futures-util", + "mio", + "socket2", + "tokio", + "tracing", +] + +[[package]] +name = "actix-service" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f" +dependencies = [ + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "actix-utils" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" +dependencies = [ + "local-waker", + "pin-project-lite", +] + +[[package]] +name = "actix-web" +version = "4.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea" +dependencies = [ + "actix-codec", + "actix-http", + "actix-macros", + "actix-router", + "actix-rt", + "actix-server", + "actix-service", + "actix-utils", + "actix-web-codegen", + "bytes", + "bytestring", + "cfg-if", + "cookie", + "derive_more", + "encoding_rs", + "foldhash", + "futures-core", + "futures-util", + "impl-more", + "itoa", + "language-tags", + "log", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "regex-lite", + "serde", + "serde_json", + "serde_urlencoded", + "smallvec", + "socket2", + "time", + "tracing", + "url", +] + +[[package]] +name = "actix-web-codegen" +version = "4.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" +dependencies = [ + "actix-router", + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "version_check", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" +dependencies = [ + "derive_arbitrary", +] + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "async-stream" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "aws-lc-rs" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fcc8f365936c834db5514fc45aee5b1202d677e6b40e48468aaaa8183ca8c7" +dependencies = [ + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61b1d86e7705efe1be1b569bab41d4fa1e14e220b60a160f78de2db687add079" +dependencies = [ + "bindgen", + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn 2.0.102", + "which", +] + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" +dependencies = [ + "serde", +] + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "brotli" +version = "8.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9991eea70ea4f293524138648e41ee89b0b2b12ddef3b255effa43c8056e0e0d" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bstr" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4" +dependencies = [ + "memchr", + "regex-automata", + "serde", +] + +[[package]] +name = "bumpalo" +version = "3.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee" + +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "bytestring" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" +dependencies = [ + "bytes", +] + +[[package]] +name = "cc" +version = "1.2.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956a5e21988b87f372569b66183b78babf23ebc2e744b733e4350a752c4dafac" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-link", +] + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cookie" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "derive-new" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "derive_arbitrary" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "derive_more" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +dependencies = [ + "serde", +] + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc95de49ad098572c02d3fbf368c9a020bfff5ae78483685b77f51d8a7e9486d" +dependencies = [ + "num_threads", +] + +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fancy-regex" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" +dependencies = [ + "bit-set", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "flate2" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3d7db9596fecd151c5f638c0ee5d5bd487b6e0ea232e5dc96d5250f6f94b1d" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.3.1", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.4", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http 1.3.1", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http 1.3.1", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.10", + "http 1.3.1", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http 1.3.1", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.0", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http 1.3.1", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "impl-more" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2" + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", + "serde", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "jiff" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a194df1107f33c79f4f93d02c80798520551949d59dfad22b6157048a88cca93" +dependencies = [ + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde", +] + +[[package]] +name = "jiff-static" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c6e1db7ed32c6c71b759497fae34bf7933636f75a251b9e736555da426f6442" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "jobserver" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" +dependencies = [ + "getrandom 0.3.3", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "language-tags" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" + +[[package]] +name = "lazy-regex" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60c7310b93682b36b98fa7ea4de998d3463ccbebd94d935d6b48ba5b6ffa7126" +dependencies = [ + "lazy-regex-proc_macros", + "once_cell", + "regex-lite", +] + +[[package]] +name = "lazy-regex-proc_macros" +version = "3.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ba01db5ef81e17eb10a5e0f2109d1b3a3e29bac3070fdbd7d156bf7dbd206a1" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.102", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.172" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" + +[[package]] +name = "libloading" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +dependencies = [ + "cfg-if", + "windows-targets 0.53.1", +] + +[[package]] +name = "libm" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "local-channel" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +dependencies = [ + "futures-core", + "futures-sink", + "local-waker", +] + +[[package]] +name = "local-waker" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "log", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "ollama-rs" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46483ac9e1f9e93da045b5875837ca3c9cf014fd6ab89b4d9736580ddefc4759" +dependencies = [ + "async-stream", + "async-trait", + "log", + "reqwest", + "serde", + "serde_json", + "url", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + +[[package]] +name = "openssl" +version = "0.10.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pgmq" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b776031ffc4e2291941f2657fad6276408d4f16aa4084ac4ca934ce8d2d886d" +dependencies = [ + "chrono", + "log", + "serde", + "serde_json", + "sqlx", + "thiserror 1.0.69", + "tokio", + "url", +] + +[[package]] +name = "pgvector" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc58e2d255979a31caa7cabfa7aac654af0354220719ab7a68520ae7a91e8c0b" +dependencies = [ + "bytes", + "postgres-types", + "sqlx", +] + +[[package]] +name = "pgwire" +version = "0.30.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca6c26b25be998208a13ff2f0c55b567363f34675410e6d6f1c513a150583fd" +dependencies = [ + "async-trait", + "aws-lc-rs", + "bytes", + "chrono", + "derive-new", + "futures", + "hex", + "lazy-regex", + "md5", + "postgres-types", + "rand 0.9.1", + "rust_decimal", + "rustls-pki-types", + "thiserror 2.0.12", + "tokio", + "tokio-rustls", + "tokio-util", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + +[[package]] +name = "portable-atomic-util" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "postgres-protocol" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ff0abab4a9b844b93ef7b81f1efc0a366062aaef2cd702c76256b5dc075c54" +dependencies = [ + "base64", + "byteorder", + "bytes", + "fallible-iterator 0.2.0", + "hmac", + "md-5", + "memchr", + "rand 0.9.1", + "sha2", + "stringprep", +] + +[[package]] +name = "postgres-types" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" +dependencies = [ + "array-init", + "bytes", + "chrono", + "fallible-iterator 0.2.0", + "postgres-protocol", +] + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "prettyplease" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dee91521343f4c5c6a63edd65e54f31f5c92fe8978c40a4282f8372194c6a7d" +dependencies = [ + "proc-macro2", + "syn 2.0.102", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptr_meta" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" +dependencies = [ + "ptr_meta_derive", +] + +[[package]] +name = "ptr_meta_derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quinn" +version = "0.11.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 2.1.1", + "rustls", + "socket2", + "thiserror 2.0.12", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" +dependencies = [ + "bytes", + "getrandom 0.3.3", + "lru-slab", + "rand 0.9.1", + "ring", + "rustc-hash 2.1.1", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.12", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "redox_syscall" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "reqwest" +version = "0.12.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabf4c97d9130e2bf606614eb937e86edac8292eaa6f422f995d7e8de1eb1813" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.10", + "http 1.3.1", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 1.0.0", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted 0.9.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "rkyv" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "rsa" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rust-embed" +version = "8.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.102", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] +name = "rust_decimal" +version = "1.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50" +dependencies = [ + "arrayvec", + "borsh", + "bytes", + "num-traits", + "postgres-types", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.23.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" +dependencies = [ + "aws-lc-rs", + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted 0.9.0", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core 0.6.4", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlparser" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe11944a61da0da3f592e19a45ebe5ab92dc14a779907ff1f08fbb797bfefc7" +dependencies = [ + "log", +] + +[[package]] +name = "sqlx" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6" +dependencies = [ + "base64", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "either", + "event-listener", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.4", + "hashlink", + "indexmap", + "log", + "memchr", + "once_cell", + "percent-encoding", + "rustls", + "serde", + "serde_json", + "sha2", + "smallvec", + "thiserror 2.0.12", + "time", + "tokio", + "tokio-stream", + "tracing", + "url", + "uuid", + "webpki-roots 0.26.11", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.102", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b" +dependencies = [ + "dotenvy", + "either", + "heck", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.102", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "bytes", + "chrono", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.12", + "time", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46" +dependencies = [ + "atoi", + "base64", + "bitflags", + "byteorder", + "chrono", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.12", + "time", + "tracing", + "uuid", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea" +dependencies = [ + "atoi", + "chrono", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "thiserror 2.0.12", + "time", + "tracing", + "url", + "uuid", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6397daf94fa90f058bd0fd88429dd9e5738999cca8d701813c80723add80462" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix 1.0.7", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" +dependencies = [ + "thiserror-impl 2.0.12", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "tiktoken-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25563eeba904d770acf527e8b370fe9a5547bacd20ff84a0b6c3bc41288e5625" +dependencies = [ + "anyhow", + "base64", + "bstr", + "fancy-regex", + "lazy_static", + "regex", + "rustc-hash 1.1.0", +] + +[[package]] +name = "time" +version = "0.3.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" + +[[package]] +name = "time-macros" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-postgres" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c95d533c83082bb6490e0189acaa0bbeef9084e60471b696ca6988cd0541fb0" +dependencies = [ + "async-trait", + "byteorder", + "bytes", + "fallible-iterator 0.2.0", + "futures-channel", + "futures-util", + "log", + "parking_lot", + "percent-encoding", + "phf", + "pin-project-lite", + "postgres-protocol", + "postgres-types", + "rand 0.9.1", + "socket2", + "tokio", + "tokio-util", + "whoami", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http 1.3.1", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1ffbcf9c6f6b99d386e7444eb608ba646ae452a36b39737deb9663b610f662" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "nu-ansi-term", + "sharded-slab", + "smallvec", + "thread_local", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "utoipa" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5afb1a60e207dca502682537fefcfd9921e71d0b83e9576060f09abc6efab23" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen 4.3.1", +] + +[[package]] +name = "utoipa" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435c6f69ef38c9017b4b4eea965dfb91e71e53d869e896db40d1cf2441dd75c0" +dependencies = [ + "indexmap", + "serde", + "serde_json", + "utoipa-gen 5.3.1", +] + +[[package]] +name = "utoipa-gen" +version = "4.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c24e8ab68ff9ee746aad22d39b5535601e6416d1b0feeabf78be986a5c4392" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "regex", + "syn 2.0.102", + "uuid", +] + +[[package]] +name = "utoipa-gen" +version = "5.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77d306bc75294fd52f3e99b13ece67c02c1a2789190a6f31d32f736624326f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "utoipa-swagger-ui" +version = "7.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "943e0ff606c6d57d410fd5663a4d7c074ab2c5f14ab903b9514565e59fa1189e" +dependencies = [ + "actix-web", + "mime_guess", + "regex", + "reqwest", + "rust-embed", + "serde", + "serde_json", + "url", + "utoipa 4.2.3", + "zip", +] + +[[package]] +name = "uuid" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "rand 0.9.1", + "serde", + "uuid-macro-internal", + "wasm-bindgen", +] + +[[package]] +name = "uuid-macro-internal" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b682e8c381995ea03130e381928e0e005b7c9eb483c6c8682f50e07b33c2b7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "vectorize-core" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "bytes", + "chrono", + "env", + "env_logger", + "futures", + "lazy_static", + "log", + "ollama-rs", + "pgmq", + "pgwire", + "postgres-protocol", + "rand 0.9.1", + "regex", + "reqwest", + "serde", + "serde_json", + "sqlparser", + "sqlx", + "thiserror 2.0.12", + "tiktoken-rs", + "tokio", + "tokio-postgres", + "url", + "utoipa 5.3.1", + "uuid", +] + +[[package]] +name = "vectorize-server" +version = "0.1.0" +dependencies = [ + "actix-cors", + "actix-http", + "actix-rt", + "actix-service", + "actix-web", + "anyhow", + "async-trait", + "bytes", + "chrono", + "clap", + "env", + "env_logger", + "fallible-iterator 0.3.0", + "futures", + "lazy_static", + "log", + "ollama-rs", + "pgmq", + "pgvector", + "pgwire", + "postgres-protocol", + "rand 0.9.1", + "regex", + "reqwest", + "serde", + "serde_json", + "sqlparser", + "sqlx", + "thiserror 2.0.12", + "tiktoken-rs", + "tokio", + "tokio-postgres", + "tracing-subscriber", + "url", + "utoipa 4.2.3", + "utoipa-swagger-ui", + "uuid", + "vectorize-core", + "vectorize-worker", +] + +[[package]] +name = "vectorize-worker" +version = "0.1.0" +dependencies = [ + "anyhow", + "log", + "pgmq", + "serde", + "serde_json", + "sqlx", + "tiktoken-rs", + "tokio", + "vectorize-core", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.102", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.0", +] + +[[package]] +name = "webpki-roots" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix 0.38.44", +] + +[[package]] +name = "whoami" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" +dependencies = [ + "redox_syscall", + "wasite", + "web-sys", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "windows-link" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3bfe459f85da17560875b8bf1423d6f113b7a87a5d942e7da0ac71be7c61f8b" + +[[package]] +name = "windows-registry" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bab093bdd303a1240bb99b8aba8ea8a69ee19d34c9e2ef9594e708a4878820" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30357ec391cde730f8fbfcdc29adc47518b06504528df977ab5af02ef23fdee9" +dependencies = [ + "windows_aarch64_gnullvm 0.53.0", + "windows_aarch64_msvc 0.53.0", + "windows_i686_gnu 0.53.0", + "windows_i686_gnullvm 0.53.0", + "windows_i686_msvc 0.53.0", + "windows_x86_64_gnu 0.53.0", + "windows_x86_64_gnullvm 0.53.0", + "windows_x86_64_msvc 0.53.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" + +[[package]] +name = "winnow" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.102", +] + +[[package]] +name = "zip" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" +dependencies = [ + "arbitrary", + "crc32fast", + "crossbeam-utils", + "displaydoc", + "flate2", + "indexmap", + "num_enum", + "thiserror 1.0.69", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.15+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..918ed940 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,39 @@ +[workspace] +members = [ + "server" + ,"core" + ,"worker" +] +resolver = "2" +exclude = [ + "extension" +] + +[workspace.dependencies] +anyhow = "1.0.98" +async-trait = "0.1.88" +bytes = "1.10.1" +chrono = {version = "0.4.41", features = ["serde"] } +clap = { version = "4.0", features = ["derive"] } +env = "1.0.1" +env_logger = "0.11" +fallible-iterator = "0.3.0" +futures = "0.3.31" +lazy_static = "1.5.0" +log = "0.4" +ollama-rs = "=0.2.1" +pgmq = "0.30.1" +rand = "0.9.1" +regex = "1.11.1" +reqwest = { version = "0.12.16", features = ["json"] } +serde = "1.0.219" +serde_json = "1.0" +sqlparser = "0.51" +sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "uuid", "time"] } +thiserror = "2.0.12" +tiktoken-rs = "0.7.0" +tokio = { version = "1.0", features = ["full"] } +url = "2.2" +utoipa = { version = "4", features = ["actix_extras", "chrono", "uuid"] } +utoipa-swagger-ui = { version = "7", features = ["actix-web"] } +uuid = { version = "1.16.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] } \ No newline at end of file diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 00000000..5ebde9eb --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "vectorize-core" +version = "0.1.0" +edition = "2024" +publish = false + +[dependencies] +env_logger = { workspace = true} +anyhow = "1.0.98" +async-trait = "0.1.88" +bytes = "1.10.1" +chrono = {version = "0.4.41", features = ["serde"] } +env = "1.0.1" +futures = "0.3.31" +lazy_static = "1.5.0" +log = "0.4" +ollama-rs = "=0.2.1" +pgmq = "0.30.1" +pgwire = { version = "0.30", features = ["server-api-aws-lc-rs"] } +postgres-protocol = "0.6.8" +rand = "0.9.1" +regex = "1.11.1" +reqwest = { version = "0.12.16", features = ["json"] } +serde = "1.0.219" +serde_json = "1.0" +sqlparser = "0.51" +sqlx = { version = "0.8", features = ["runtime-tokio-rustls", "postgres", "uuid", "time"] } +thiserror = "2.0.12" +tiktoken-rs = "0.7.0" +tokio = { version = "1.0", features = ["full"] } +tokio-postgres = "0.7" +url = "2.2" +utoipa = "5.3.1" +uuid = { version = "1.16.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] } diff --git a/server/src/core/worker/base.rs b/core/src/config.rs similarity index 93% rename from server/src/core/worker/base.rs rename to core/src/config.rs index 461b2d04..5ea18874 100644 --- a/server/src/core/worker/base.rs +++ b/core/src/config.rs @@ -17,6 +17,7 @@ pub fn check_input(input: &str) -> Result<()> { #[derive(Debug, Clone)] pub struct Config { + pub vectorize_proxy_port: u16, pub database_url: String, pub queue_name: String, pub embedding_svc_url: String, @@ -33,6 +34,9 @@ pub struct Config { impl Config { pub fn from_env() -> Config { Config { + vectorize_proxy_port: from_env_default("VECTORIZE_PROXY_PORT", "5433") + .parse() + .unwrap(), database_url: from_env_default( "DATABASE_URL", "postgres://postgres:postgres@localhost:5432/postgres", diff --git a/server/src/db.rs b/core/src/db.rs similarity index 68% rename from server/src/db.rs rename to core/src/db.rs index 1cfc955b..80c8de5c 100644 --- a/server/src/db.rs +++ b/core/src/db.rs @@ -1,8 +1,10 @@ -use crate::errors::ServerError; -use crate::routes::table::VectorizeJob; +use crate::{errors::VectorizeError, types::VectorizeJob}; use sqlx::{FromRow, PgPool}; -pub async fn get_vectorize_job(pool: &PgPool, job_name: &str) -> Result { +pub async fn get_vectorize_job( + pool: &PgPool, + job_name: &str, +) -> Result { // Changed return type let row = sqlx::query( "SELECT job_name, src_table, src_schema, src_column, primary_key, update_time_col, model diff --git a/server/src/core/errors.rs b/core/src/errors.rs similarity index 73% rename from server/src/core/errors.rs rename to core/src/errors.rs index 14b2d8ff..46dc3d26 100644 --- a/server/src/core/errors.rs +++ b/core/src/errors.rs @@ -1,5 +1,6 @@ use anyhow::Error as AnyhowError; use ollama_rs::error::OllamaError; +use pgmq::PgmqError; use sqlx::error::Error as DbError; use std::env::VarError; use thiserror::Error; @@ -18,12 +19,16 @@ pub enum DatabaseError { pub enum VectorizeError { #[error("Database error: {0}")] DatabaseError(#[from] DatabaseError), + #[error("SQL error: {0}")] + SqlError(#[from] DbError), #[error("HTTP error: {0}")] Reqwest(#[from] reqwest::Error), #[error("Serde error: {0}")] SerdeError(#[from] serde_json::Error), #[error("An internal error occurred: {0}")] InternalError(#[from] AnyhowError), + #[error("data not found: {0}")] + NotFound(String), #[error("model not found: {0}")] ModelNotFound(String), #[error("ollama error: {0}")] @@ -31,4 +36,10 @@ pub enum VectorizeError { // env var missing #[error("Environment variable missing: {0}")] EnvError(#[from] VarError), + #[error("job not found: {0}")] + JobNotFound(String), + #[error("embedding generation failed: {0}")] + EmbeddingGenerationFailed(String), + #[error("pgmq error: {0}")] + PgmqError(#[from] PgmqError), } diff --git a/server/src/core/guc.rs b/core/src/guc.rs similarity index 88% rename from server/src/core/guc.rs rename to core/src/guc.rs index 5ed22c0f..2b6dba6f 100644 --- a/server/src/core/guc.rs +++ b/core/src/guc.rs @@ -1,3 +1,7 @@ +use sqlx::PgPool; + +use crate::types::ModelSource; + // for handling of GUCs that can be error prone #[derive(Clone, Debug)] pub enum VectorizeGuc { @@ -5,11 +9,9 @@ pub enum VectorizeGuc { DatabaseName, OpenAIServiceUrl, OpenAIKey, - TemboAIKey, EmbeddingServiceUrl, EmbeddingServiceApiKey, OllamaServiceUrl, - TemboServiceUrl, CohereApiKey, PortkeyApiKey, PortkeyVirtualKey, @@ -26,20 +28,15 @@ pub struct ModelGucConfig { pub virtual_key: Option, } -use sqlx::PgPool; - -use crate::core::types::ModelSource; pub async fn get_guc(guc: VectorizeGuc, pool: &PgPool) -> Option { let guc_name = match guc { VectorizeGuc::Host => "host", VectorizeGuc::DatabaseName => "database_name", VectorizeGuc::OpenAIServiceUrl => "openai_service_url", VectorizeGuc::OpenAIKey => "openai_key", - VectorizeGuc::TemboAIKey => "tembo_jwt", VectorizeGuc::EmbeddingServiceUrl => "embedding_service_url", VectorizeGuc::EmbeddingServiceApiKey => "embedding_service_api_key", VectorizeGuc::OllamaServiceUrl => "ollama_service_url", - VectorizeGuc::TemboServiceUrl => "tembo_service_url", VectorizeGuc::CohereApiKey => "cohere_api_key", VectorizeGuc::PortkeyApiKey => "portkey_api_key", VectorizeGuc::PortkeyVirtualKey => "portkey_virtual_key", @@ -64,11 +61,6 @@ pub async fn get_guc_configs(model_source: &ModelSource, pool: &PgPool) -> Model service_url: get_guc(VectorizeGuc::OpenAIServiceUrl, pool).await, virtual_key: None, }, - ModelSource::Tembo => ModelGucConfig { - api_key: get_guc(VectorizeGuc::TemboAIKey, pool).await, - service_url: get_guc(VectorizeGuc::TemboServiceUrl, pool).await, - virtual_key: None, - }, ModelSource::SentenceTransformers => ModelGucConfig { api_key: get_guc(VectorizeGuc::EmbeddingServiceApiKey, pool).await, service_url: get_guc(VectorizeGuc::EmbeddingServiceUrl, pool).await, diff --git a/server/src/init.rs b/core/src/init.rs similarity index 94% rename from server/src/init.rs rename to core/src/init.rs index 7236de19..fd45d6fe 100644 --- a/server/src/init.rs +++ b/core/src/init.rs @@ -1,14 +1,14 @@ -use crate::core::query; -use crate::core::transformers::providers::get_provider; -use crate::core::types::JobMessage; -use crate::errors::ServerError; -use crate::routes::table::VectorizeJob; +use crate::errors::VectorizeError; +use crate::query; +use crate::transformers::providers::get_provider; +use crate::types::JobMessage; +use crate::types::VectorizeJob; use anyhow::anyhow; use sqlx::PgPool; use std::process::Command; use uuid::Uuid; -pub async fn init_project(pool: &PgPool, conn_string: Option<&str>) -> Result<(), ServerError> { +pub async fn init_project(pool: &PgPool, conn_string: Option<&str>) -> Result<(), VectorizeError> { // Initialize the pgmq extension init_pgmq(pool, conn_string).await?; @@ -30,7 +30,7 @@ pub async fn get_column_datatype( schema: &str, table: &str, column: &str, -) -> Result { +) -> Result { let row: String = sqlx::query_scalar( " SELECT data_type @@ -47,7 +47,7 @@ pub async fn get_column_datatype( .fetch_one(pool) .await .map_err(|e| { - ServerError::InvalidRequest(format!( + VectorizeError::NotFound(format!( "schema, table or column NOT FOUND for {}.{}.{}: {}", schema, table, column, e )) @@ -65,7 +65,7 @@ async fn pgmq_schema_exists(pool: &PgPool) -> Result { Ok(row) } -pub async fn init_pgmq(pool: &PgPool, conn_string: Option<&str>) -> Result<(), ServerError> { +pub async fn init_pgmq(pool: &PgPool, conn_string: Option<&str>) -> Result<(), VectorizeError> { // Check if the pgmq schema already exists if pgmq_schema_exists(pool).await? { log::info!("pgmq schema already exists, skipping initialization."); @@ -93,7 +93,7 @@ pub async fn init_pgmq(pool: &PgPool, conn_string: Option<&str>) -> Result<(), S "failed to install pgmq: {}", String::from_utf8_lossy(&output.stderr) ); - return Err(ServerError::InternalError(anyhow!( + return Err(VectorizeError::InternalError(anyhow!( "Failed to install pgmq".to_string() ))); } @@ -106,7 +106,7 @@ pub async fn init_pgmq(pool: &PgPool, conn_string: Option<&str>) -> Result<(), S pub async fn initialize_job( pool: &PgPool, job_request: &VectorizeJob, -) -> Result { +) -> Result { // create the job record let mut tx = pool.begin().await?; let job_id: Uuid = sqlx::query_scalar(" @@ -196,7 +196,7 @@ pub async fn initialize_job( } // enqueues jobs where records need embeddings computed -pub async fn scan_job(pool: &PgPool, job_request: &VectorizeJob) -> Result<(), ServerError> { +pub async fn scan_job(pool: &PgPool, job_request: &VectorizeJob) -> Result<(), VectorizeError> { let rows_for_update_query = query::new_rows_query_join( &job_request.job_name, &[job_request.src_column.clone()], diff --git a/server/src/core/mod.rs b/core/src/lib.rs similarity index 65% rename from server/src/core/mod.rs rename to core/src/lib.rs index 20e3b7b5..b72417b3 100644 --- a/server/src/core/mod.rs +++ b/core/src/lib.rs @@ -1,6 +1,8 @@ +pub mod config; +pub mod db; pub mod errors; pub mod guc; +pub mod init; pub mod query; pub mod transformers; pub mod types; -pub mod worker; diff --git a/server/src/core/query.rs b/core/src/query.rs similarity index 98% rename from server/src/core/query.rs rename to core/src/query.rs index 60a0b2db..a7da3fce 100644 --- a/server/src/core/query.rs +++ b/core/src/query.rs @@ -1,5 +1,5 @@ -use crate::core::transformers::types::Inputs; -use crate::core::types::{self, JobParams}; +use crate::transformers::types::Inputs; +use crate::types::{self, JobParams}; use anyhow::{Result, anyhow}; use sqlx::error::Error; use sqlx::postgres::PgRow; @@ -358,14 +358,13 @@ mod tests { let job_name = "another_job"; let table_name = "another_table"; - let expected = format!( - " + let expected = " CREATE OR REPLACE TRIGGER vectorize_update_trigger_another_job AFTER UPDATE ON myschema.another_table REFERENCING NEW TABLE AS new_table FOR EACH STATEMENT EXECUTE FUNCTION vectorize.handle_update_another_job();" - ); + .to_string(); let result = create_event_trigger(job_name, "myschema", table_name, "UPDATE"); assert_eq!(expected, result); } @@ -375,14 +374,13 @@ EXECUTE FUNCTION vectorize.handle_update_another_job();" let job_name = "another_job"; let table_name = "another_table"; - let expected = format!( - " + let expected = " CREATE OR REPLACE TRIGGER vectorize_insert_trigger_another_job AFTER INSERT ON myschema.another_table REFERENCING NEW TABLE AS new_table FOR EACH STATEMENT EXECUTE FUNCTION vectorize.handle_update_another_job();" - ); + .to_string(); let result = create_event_trigger(job_name, "myschema", table_name, "INSERT"); assert_eq!(expected, result); } diff --git a/server/src/core/transformers/generic.rs b/core/src/transformers/generic.rs similarity index 97% rename from server/src/core/transformers/generic.rs rename to core/src/transformers/generic.rs index b9e90c27..353679f7 100644 --- a/server/src/core/transformers/generic.rs +++ b/core/src/transformers/generic.rs @@ -4,12 +4,12 @@ use regex::Regex; use std::collections::HashSet; use std::env; -use crate::core::{ +use crate::{ transformers::types::{EmbeddingPayload, EmbeddingRequest, Inputs}, types, }; -use crate::core::transformers::providers::openai::trim_inputs; +use crate::transformers::providers::openai::trim_inputs; lazy_static! { static ref REGEX: Regex = Regex::new(r"\$\{([^}]+)\}").expect("Invalid regex"); diff --git a/server/src/core/transformers/http_handler.rs b/core/src/transformers/http_handler.rs similarity index 89% rename from server/src/core/transformers/http_handler.rs rename to core/src/transformers/http_handler.rs index 7b00856a..4cc11002 100644 --- a/server/src/core/transformers/http_handler.rs +++ b/core/src/transformers/http_handler.rs @@ -1,5 +1,5 @@ -use crate::core::errors::VectorizeError; -use crate::core::transformers::types::{Inputs, PairedEmbeddings}; +use crate::errors::VectorizeError; +use crate::transformers::types::{Inputs, PairedEmbeddings}; pub async fn handle_response serde::Deserialize<'de>>( resp: reqwest::Response, diff --git a/server/src/core/transformers/mod.rs b/core/src/transformers/mod.rs similarity index 100% rename from server/src/core/transformers/mod.rs rename to core/src/transformers/mod.rs diff --git a/server/src/core/transformers/providers/cohere.rs b/core/src/transformers/providers/cohere.rs similarity index 97% rename from server/src/core/transformers/providers/cohere.rs rename to core/src/transformers/providers/cohere.rs index 6a243631..58094916 100644 --- a/server/src/core/transformers/providers/cohere.rs +++ b/core/src/transformers/providers/cohere.rs @@ -2,8 +2,8 @@ use reqwest::Client; use serde::{Deserialize, Serialize}; use super::{EmbeddingProvider, GenericEmbeddingRequest, GenericEmbeddingResponse}; -use crate::core::errors::VectorizeError; -use crate::core::transformers::http_handler::handle_response; +use crate::errors::VectorizeError; +use crate::transformers::http_handler::handle_response; use async_trait::async_trait; use lazy_static::lazy_static; use std::collections::HashMap; diff --git a/server/src/core/transformers/providers/mod.rs b/core/src/transformers/providers/mod.rs similarity index 87% rename from server/src/core/transformers/providers/mod.rs rename to core/src/transformers/providers/mod.rs index 54d049ea..c0de4b8c 100644 --- a/server/src/core/transformers/providers/mod.rs +++ b/core/src/transformers/providers/mod.rs @@ -10,13 +10,13 @@ use async_trait::async_trait; use serde::{Deserialize, Serialize}; use super::types::Inputs; -use crate::core::errors::VectorizeError; -use crate::core::transformers::providers; -use crate::core::types::Model; -use crate::core::types::ModelSource; +use crate::errors::VectorizeError; +use crate::transformers::providers; +use crate::types::Model; +use crate::types::ModelSource; #[async_trait] -pub trait EmbeddingProvider { +pub trait EmbeddingProvider: Send + Sync { #[allow(async_fn_in_trait)] async fn generate_embedding<'a>( &self, @@ -54,7 +54,7 @@ pub fn get_provider( api_key: Option, url: Option, virtual_key: Option, -) -> Result, VectorizeError> { +) -> Result, VectorizeError> { match model_source { ModelSource::OpenAI => Ok(Box::new(providers::openai::OpenAIProvider::new( url, api_key, @@ -74,9 +74,6 @@ pub fn get_provider( providers::vector_serve::VectorServeProvider::new(url, api_key), )), ModelSource::Ollama => Ok(Box::new(providers::ollama::OllamaProvider::new(url))), - ModelSource::Tembo => Err(anyhow::anyhow!( - "Ollama/Tembo transformer not implemented yet" - ))?, } } diff --git a/server/src/core/transformers/providers/ollama.rs b/core/src/transformers/providers/ollama.rs similarity index 98% rename from server/src/core/transformers/providers/ollama.rs rename to core/src/transformers/providers/ollama.rs index ab761525..bd1baef9 100644 --- a/server/src/core/transformers/providers/ollama.rs +++ b/core/src/transformers/providers/ollama.rs @@ -1,7 +1,7 @@ use super::{ ChatMessageRequest, EmbeddingProvider, GenericEmbeddingRequest, GenericEmbeddingResponse, }; -use crate::core::errors::VectorizeError; +use crate::errors::VectorizeError; use async_trait::async_trait; use ollama_rs::{ Ollama, diff --git a/server/src/core/transformers/providers/openai.rs b/core/src/transformers/providers/openai.rs similarity index 97% rename from server/src/core/transformers/providers/openai.rs rename to core/src/transformers/providers/openai.rs index ffb47049..cf54088f 100644 --- a/server/src/core/transformers/providers/openai.rs +++ b/core/src/transformers/providers/openai.rs @@ -5,10 +5,10 @@ use super::{ ChatMessageRequest, ChatResponse, EmbeddingProvider, GenericEmbeddingRequest, GenericEmbeddingResponse, }; -use crate::core::errors::VectorizeError; -use crate::core::transformers::http_handler::handle_response; -use crate::core::transformers::providers; -use crate::core::transformers::types::Inputs; +use crate::errors::VectorizeError; +use crate::transformers::http_handler::handle_response; +use crate::transformers::providers; +use crate::transformers::types::Inputs; use async_trait::async_trait; use std::env; diff --git a/server/src/core/transformers/providers/portkey.rs b/core/src/transformers/providers/portkey.rs similarity index 96% rename from server/src/core/transformers/providers/portkey.rs rename to core/src/transformers/providers/portkey.rs index a77ee6c2..c21044aa 100644 --- a/server/src/core/transformers/providers/portkey.rs +++ b/core/src/transformers/providers/portkey.rs @@ -4,10 +4,10 @@ use super::{ ChatMessageRequest, ChatResponse, EmbeddingProvider, GenericEmbeddingRequest, GenericEmbeddingResponse, }; -use crate::core::errors::VectorizeError; -use crate::core::transformers::http_handler::handle_response; -use crate::core::transformers::providers; -use crate::core::transformers::providers::openai; +use crate::errors::VectorizeError; +use crate::transformers::http_handler::handle_response; +use crate::transformers::providers; +use crate::transformers::providers::openai; use async_trait::async_trait; use std::env; diff --git a/server/src/core/transformers/providers/vector_serve.rs b/core/src/transformers/providers/vector_serve.rs similarity index 96% rename from server/src/core/transformers/providers/vector_serve.rs rename to core/src/transformers/providers/vector_serve.rs index 6e29be70..61aa52f7 100644 --- a/server/src/core/transformers/providers/vector_serve.rs +++ b/core/src/transformers/providers/vector_serve.rs @@ -2,9 +2,9 @@ use reqwest::Client; use serde::{Deserialize, Serialize}; use super::{EmbeddingProvider, GenericEmbeddingRequest, GenericEmbeddingResponse}; -use crate::core::errors::VectorizeError; -use crate::core::transformers::http_handler::handle_response; -use crate::core::transformers::providers::openai; +use crate::errors::VectorizeError; +use crate::transformers::http_handler::handle_response; +use crate::transformers::providers::openai; use async_trait::async_trait; use std::env; diff --git a/server/src/core/transformers/providers/voyage.rs b/core/src/transformers/providers/voyage.rs similarity index 97% rename from server/src/core/transformers/providers/voyage.rs rename to core/src/transformers/providers/voyage.rs index f18a5e84..785a9f21 100644 --- a/server/src/core/transformers/providers/voyage.rs +++ b/core/src/transformers/providers/voyage.rs @@ -2,8 +2,8 @@ use reqwest::Client; use serde::{Deserialize, Serialize}; use super::{EmbeddingProvider, GenericEmbeddingRequest, GenericEmbeddingResponse}; -use crate::core::errors::VectorizeError; -use crate::core::transformers::http_handler::handle_response; +use crate::errors::VectorizeError; +use crate::transformers::http_handler::handle_response; use async_trait::async_trait; use std::env; diff --git a/server/src/core/transformers/types.rs b/core/src/transformers/types.rs similarity index 100% rename from server/src/core/transformers/types.rs rename to core/src/transformers/types.rs diff --git a/server/src/core/types.rs b/core/src/types.rs similarity index 92% rename from server/src/core/types.rs rename to core/src/types.rs index f48cbd4c..2cb240ee 100644 --- a/server/src/core/types.rs +++ b/core/src/types.rs @@ -4,9 +4,25 @@ use std::fmt; use std::fmt::{Display, Formatter}; use std::str::FromStr; use thiserror::Error; +use utoipa::ToSchema; pub const VECTORIZE_SCHEMA: &str = "vectorize"; +#[derive(Serialize, Deserialize, Debug, Clone, ToSchema, FromRow)] +pub struct VectorizeJob { + pub job_name: String, + pub src_table: String, + pub src_schema: String, + pub src_column: String, + pub primary_key: String, + pub update_time_col: String, + #[serde( + deserialize_with = "string_to_model", + serialize_with = "model_to_string" + )] + pub model: Model, +} + #[allow(non_camel_case_types)] #[derive(Clone, Debug, Serialize, Deserialize)] // SimilarityAlg is now deprecated @@ -140,7 +156,7 @@ pub struct VectorizeMeta { pub params: serde_json::Value, } -#[derive(Clone, Debug, Deserialize, Serialize, FromRow)] +#[derive(Clone, Debug, Deserialize, Serialize, FromRow, ToSchema)] pub struct Model { pub source: ModelSource, // the model's namespace + model name @@ -192,7 +208,6 @@ impl Model { ModelSource::OpenAI => self.name.clone(), ModelSource::SentenceTransformers => self.fullname.clone(), ModelSource::Ollama => self.name.clone(), - ModelSource::Tembo => self.name.clone(), ModelSource::Cohere => self.name.clone(), ModelSource::Portkey => self.name.clone(), ModelSource::Voyage => self.name.clone(), @@ -237,17 +252,10 @@ impl Model { .parse::() .map_err(|_| ModelError::InvalidSource(parts[0].to_string()))?; - let name = if source == ModelSource::Tembo { - // removes the leading /tembo from the model name - parts.remove(0); - // all others remain the same - parts.join("/") - } else { - parts - .last() - .expect("expected non-empty model name") - .to_string() - }; + let name = parts + .last() + .expect("expected non-empty model name") + .to_string(); Ok(Self { source, @@ -265,12 +273,11 @@ impl fmt::Display for Model { // model sources are places that serve models // each source can have its own API schema -#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Debug, Deserialize, PartialEq, Serialize, ToSchema)] pub enum ModelSource { OpenAI, SentenceTransformers, Ollama, - Tembo, Cohere, Portkey, Voyage, @@ -284,7 +291,6 @@ impl FromStr for ModelSource { "ollama" => Ok(ModelSource::Ollama), "openai" => Ok(ModelSource::OpenAI), "sentence-transformers" => Ok(ModelSource::SentenceTransformers), - "tembo" => Ok(ModelSource::Tembo), "cohere" => Ok(ModelSource::Cohere), "portkey" => Ok(ModelSource::Portkey), "voyage" => Ok(ModelSource::Voyage), @@ -299,7 +305,6 @@ impl Display for ModelSource { ModelSource::Ollama => write!(f, "ollama"), ModelSource::OpenAI => write!(f, "openai"), ModelSource::SentenceTransformers => write!(f, "sentence-transformers"), - ModelSource::Tembo => write!(f, "tembo"), ModelSource::Cohere => write!(f, "cohere"), ModelSource::Portkey => write!(f, "portkey"), ModelSource::Voyage => write!(f, "voyage"), @@ -313,7 +318,6 @@ impl From for ModelSource { "ollama" => ModelSource::Ollama, "openai" => ModelSource::OpenAI, "sentence-transformers" => ModelSource::SentenceTransformers, - "tembo" => ModelSource::Tembo, "cohere" => ModelSource::Cohere, "portkey" => ModelSource::Portkey, "voyage" => ModelSource::Voyage, @@ -347,14 +351,6 @@ mod model_tests { assert_eq!(model.api_name(), "voyage-3-lite"); } - #[test] - fn test_tembo_parsing() { - let model = Model::new("tembo/meta-llama/Meta-Llama-3-8B-Instruct").unwrap(); - assert_eq!(model.source, ModelSource::Tembo); - assert_eq!(model.fullname, "meta-llama/Meta-Llama-3-8B-Instruct"); - assert_eq!(model.name, "meta-llama/Meta-Llama-3-8B-Instruct"); - } - #[test] fn test_ollama_parsing() { let model = Model::new("ollama/wizardlm2:7b").unwrap(); diff --git a/server/docker-compose.yml b/docker-compose.server.yml similarity index 73% rename from server/docker-compose.yml rename to docker-compose.server.yml index 225343f4..cf56ff26 100644 --- a/server/docker-compose.yml +++ b/docker-compose.server.yml @@ -27,26 +27,14 @@ services: depends_on: - postgres build: - dockerfile: Dockerfile - context: . + dockerfile: server/Dockerfile + context: ./ ports: - - 8080:8080 + - 8080:8080 # http server environment: <<: *default-env - RUST_LOG: info + RUST_LOG: debug command: vectorize-server - worker: - restart: always - logging: *default-logging - depends_on: - - postgres - build: - dockerfile: Dockerfile - context: . - environment: - <<: *default-env - RUST_LOG: info - command: vectorize-worker vector-serve: restart: always logging: *default-logging diff --git a/extension/Cargo.toml b/extension/Cargo.toml index 9d8cd7bc..8e4770df 100644 --- a/extension/Cargo.toml +++ b/extension/Cargo.toml @@ -20,11 +20,14 @@ pg17 = ["pgrx/pg17", "pgrx-tests/pg17"] pg_test = [] [dependencies] +vectorize_core = { path = "../core", package = "vectorize-core" } +vectorize_worker = { path = "../worker", package = "vectorize-worker" } + anyhow = "1.0.72" chrono = {version = "0.4.26", features = ["serde"] } handlebars = "5.1.0" log = "0.4.21" -pgmq = "0.29" +pgmq = "0.30.1" pgrx = "=0.13.1" reqwest = {version = "0.12.16", features = ["json"] } serde = { version = "1.0.173", features = ["derive"] } @@ -39,7 +42,6 @@ text-splitter = "0.22.0" tiktoken-rs = "0.5.7" tokio = {version = "1.29.1", features = ["rt-multi-thread"] } url = "2.4.0" -vectorize_core = { path = "../server", package = "vectorize-server" } [dev-dependencies] pgrx-tests = "=0.13.1" diff --git a/extension/src/api.rs b/extension/src/api.rs index 6926236b..74ba036a 100644 --- a/extension/src/api.rs +++ b/extension/src/api.rs @@ -8,8 +8,8 @@ use crate::transformers::transform; use crate::types; use crate::util::get_vectorize_meta_spi; use text_splitter::TextSplitter; -use vectorize_core::core::query::{create_event_trigger, create_trigger_handler}; -use vectorize_core::core::types::{JobParams, Model}; +use vectorize_core::query::{create_event_trigger, create_trigger_handler}; +use vectorize_core::types::{JobParams, Model}; use anyhow::Result; use pgrx::prelude::*; @@ -293,7 +293,7 @@ fn import_embeddings( let job_params: JobParams = serde_json::from_value(meta.params.clone())?; // Process rows based on table method - let count = if job_params.table_method == vectorize_core::core::types::TableMethod::join { + let count = if job_params.table_method == vectorize_core::types::TableMethod::join { let insert_q = format!( "INSERT INTO vectorize._embeddings_{} ({}, embeddings, updated_at) SELECT src.{}, src.{}, NOW() diff --git a/extension/src/chat/ops.rs b/extension/src/chat/ops.rs index 12a42243..86ddf6aa 100644 --- a/extension/src/chat/ops.rs +++ b/extension/src/chat/ops.rs @@ -5,17 +5,17 @@ use crate::util::get_vectorize_meta_spi; use anyhow::{anyhow, Result}; use handlebars::Handlebars; use pgrx::prelude::*; -use vectorize_core::core::guc::ModelGucConfig; -use vectorize_core::core::transformers::providers::ollama::OllamaProvider; -use vectorize_core::core::transformers::providers::openai::OpenAIProvider; -use vectorize_core::core::transformers::providers::portkey::PortkeyProvider; -use vectorize_core::core::transformers::providers::ChatMessageRequest; -use vectorize_core::core::types::Model; -use vectorize_core::core::types::ModelSource; +use vectorize_core::guc::ModelGucConfig; +use vectorize_core::transformers::providers::ollama::OllamaProvider; +use vectorize_core::transformers::providers::openai::OpenAIProvider; +use vectorize_core::transformers::providers::portkey::PortkeyProvider; +use vectorize_core::transformers::providers::ChatMessageRequest; +use vectorize_core::types::Model; +use vectorize_core::types::ModelSource; use crate::chat::types::{ChatResponse, ContextualSearch, PromptTemplate, RenderedPrompt}; use tiktoken_rs::{get_bpe_from_model, model::get_context_size, CoreBPE}; -use vectorize_core::core::types::{JobParams, VectorizeMeta}; +use vectorize_core::types::{JobParams, VectorizeMeta}; pub fn call_chat( job_name: &str, @@ -41,10 +41,6 @@ pub fn call_chat( ModelSource::OpenAI => { get_bpe_from_model(&chat_model.name).expect("failed to get BPE from model") } - ModelSource::Tembo => { - // Using gpt-3.5-turbo tokenizer as placeholder for Llama3-8B-Instruct - get_bpe_from_model("gpt-3.5-turbo").expect("failed to get BPE from model") - } ModelSource::SentenceTransformers | ModelSource::Cohere => { error!("SentenceTransformers and Cohere not yet supported for chat completions") } @@ -162,7 +158,7 @@ pub fn call_chat_completions( let chat_response: String = runtime.block_on(async { match model.source { - ModelSource::OpenAI | ModelSource::Tembo => { + ModelSource::OpenAI => { let provider = OpenAIProvider::new( guc_configs.service_url.clone(), guc_configs.api_key.clone(), diff --git a/extension/src/executor.rs b/extension/src/executor.rs index 5abf3399..2031c002 100644 --- a/extension/src/executor.rs +++ b/extension/src/executor.rs @@ -8,10 +8,10 @@ use sqlx::error::Error; use sqlx::postgres::PgRow; use sqlx::{Pool, Postgres, Row}; use tiktoken_rs::cl100k_base; -use vectorize_core::core::errors::DatabaseError; -use vectorize_core::core::query::{check_input, create_batches, new_rows_query_join}; -use vectorize_core::core::transformers::types::Inputs; -use vectorize_core::core::types::{JobMessage, JobParams, TableMethod}; +use vectorize_core::errors::DatabaseError; +use vectorize_core::query::{check_input, create_batches, new_rows_query_join}; +use vectorize_core::transformers::types::Inputs; +use vectorize_core::types::{JobMessage, JobParams, TableMethod}; #[pg_extern] pub fn batch_texts( diff --git a/extension/src/guc.rs b/extension/src/guc.rs index 9a2e4981..863f8ed9 100644 --- a/extension/src/guc.rs +++ b/extension/src/guc.rs @@ -3,8 +3,8 @@ use core::ffi::CStr; use pgrx::*; use crate::transformers::generic::env_interpolate_string; -use vectorize_core::core::guc::{ModelGucConfig, VectorizeGuc}; -use vectorize_core::core::types::ModelSource; +use vectorize_core::guc::{ModelGucConfig, VectorizeGuc}; +use vectorize_core::types::ModelSource; pub static VECTORIZE_HOST: GucSetting> = GucSetting::>::new(None); pub static VECTORIZE_DATABASE_NAME: GucSetting> = @@ -227,8 +227,6 @@ pub fn get_guc(guc: VectorizeGuc) -> Option { VectorizeGuc::OpenAIKey => OPENAI_KEY.get(), VectorizeGuc::EmbeddingServiceUrl => EMBEDDING_SERVICE_HOST.get(), VectorizeGuc::OllamaServiceUrl => OLLAMA_SERVICE_HOST.get(), - VectorizeGuc::TemboServiceUrl => TEMBO_SERVICE_HOST.get(), - VectorizeGuc::TemboAIKey => TEMBO_API_KEY.get(), VectorizeGuc::OpenAIServiceUrl => OPENAI_BASE_URL.get(), VectorizeGuc::EmbeddingServiceApiKey => EMBEDDING_SERVICE_API_KEY.get(), VectorizeGuc::CohereApiKey => COHERE_API_KEY.get(), @@ -268,11 +266,6 @@ pub fn get_guc_configs(model_source: &ModelSource) -> ModelGucConfig { service_url: get_guc(VectorizeGuc::OpenAIServiceUrl), virtual_key: None, }, - ModelSource::Tembo => ModelGucConfig { - api_key: get_guc(VectorizeGuc::TemboAIKey), - service_url: get_guc(VectorizeGuc::TemboServiceUrl), - virtual_key: None, - }, ModelSource::SentenceTransformers => ModelGucConfig { api_key: get_guc(VectorizeGuc::EmbeddingServiceApiKey), service_url: get_guc(VectorizeGuc::EmbeddingServiceUrl), diff --git a/extension/src/init.rs b/extension/src/init.rs index f60c2e8e..117de45f 100644 --- a/extension/src/init.rs +++ b/extension/src/init.rs @@ -2,10 +2,10 @@ use crate::guc; use pgrx::prelude::*; use anyhow::{anyhow, Context, Result}; -use vectorize_core::core::guc::VectorizeGuc; -use vectorize_core::core::query::{self, check_input}; -use vectorize_core::core::types::IndexDist; -use vectorize_core::core::types::{JobParams, TableMethod, VECTORIZE_SCHEMA}; +use vectorize_core::guc::VectorizeGuc; +use vectorize_core::query::{self, check_input}; +use vectorize_core::types::IndexDist; +use vectorize_core::types::{JobParams, TableMethod, VECTORIZE_SCHEMA}; pub static VECTORIZE_QUEUE: &str = "vectorize_jobs"; pub fn init_pgmq() -> Result<()> { diff --git a/extension/src/job.rs b/extension/src/job.rs index 28754635..d0aecb50 100644 --- a/extension/src/job.rs +++ b/extension/src/job.rs @@ -5,9 +5,9 @@ use crate::guc::BATCH_SIZE; use crate::init::VECTORIZE_QUEUE; use pgrx::prelude::*; use tiktoken_rs::cl100k_base; -use vectorize_core::core::query::{create_batches, new_rows_query_join}; -use vectorize_core::core::transformers::types::Inputs; -use vectorize_core::core::types::{JobMessage, JobParams, TableMethod}; +use vectorize_core::query::{create_batches, new_rows_query_join}; +use vectorize_core::transformers::types::Inputs; +use vectorize_core::types::{JobMessage, JobParams, TableMethod}; // creates batches of embedding jobs // typically used on table init diff --git a/extension/src/search.rs b/extension/src/search.rs index 1d5d25f2..2fc5282b 100644 --- a/extension/src/search.rs +++ b/extension/src/search.rs @@ -11,12 +11,12 @@ use pgrx::prelude::*; use pgrx::JsonB; use serde_json::Value; use std::collections::HashMap; -use vectorize_core::core::guc::VectorizeGuc; -use vectorize_core::core::query; -use vectorize_core::core::query::{create_event_trigger, create_trigger_handler}; -use vectorize_core::core::transformers::providers::get_provider; -use vectorize_core::core::transformers::providers::ollama::check_model_host; -use vectorize_core::core::types::{self, Model, ModelSource, TableMethod, VectorizeMeta}; +use vectorize_core::guc::VectorizeGuc; +use vectorize_core::query; +use vectorize_core::query::{create_event_trigger, create_trigger_handler}; +use vectorize_core::transformers::providers::get_provider; +use vectorize_core::transformers::providers::ollama::check_model_host; +use vectorize_core::types::{self, Model, ModelSource, TableMethod, VectorizeMeta}; #[allow(clippy::too_many_arguments)] pub fn init_table( @@ -66,9 +66,6 @@ pub fn init_table( )?; None } - ModelSource::Tembo => { - error!("Tembo not implemented for search yet"); - } ModelSource::Ollama => { let url = match guc::get_guc(VectorizeGuc::OllamaServiceUrl) { Some(k) => k, diff --git a/extension/src/transformers/generic.rs b/extension/src/transformers/generic.rs index e11c3f81..2ed0b464 100644 --- a/extension/src/transformers/generic.rs +++ b/extension/src/transformers/generic.rs @@ -1,6 +1,6 @@ use anyhow::Result; -use vectorize_core::core::transformers::generic::{find_placeholders, interpolate}; +use vectorize_core::transformers::generic::{find_placeholders, interpolate}; /// Interpolates environment variables into a string /// if env var is missing, the placeholder is left as a raw string diff --git a/extension/src/transformers/http_handler.rs b/extension/src/transformers/http_handler.rs index 720977ed..0f531f50 100644 --- a/extension/src/transformers/http_handler.rs +++ b/extension/src/transformers/http_handler.rs @@ -3,10 +3,10 @@ use anyhow::{Context, Result}; use pgrx::prelude::*; -use vectorize_core::core::guc::ModelGucConfig; -use vectorize_core::core::transformers::providers::get_provider; -use vectorize_core::core::transformers::types::TransformerMetadata; -use vectorize_core::core::types::Model; +use vectorize_core::guc::ModelGucConfig; +use vectorize_core::transformers::providers::get_provider; +use vectorize_core::transformers::types::TransformerMetadata; +use vectorize_core::types::Model; #[pg_extern] pub fn mod_info(model_name: &str, api_key: default!(Option, "NULL")) -> pgrx::JsonB { diff --git a/extension/src/transformers/mod.rs b/extension/src/transformers/mod.rs index 7a719c32..5e362d52 100644 --- a/extension/src/transformers/mod.rs +++ b/extension/src/transformers/mod.rs @@ -5,10 +5,10 @@ pub mod openai; use crate::guc; use pgrx::prelude::*; -use vectorize_core::core::guc::ModelGucConfig; -use vectorize_core::core::transformers::providers::{self, prepare_generic_embedding_request}; -use vectorize_core::core::transformers::types::Inputs; -use vectorize_core::core::types::Model; +use vectorize_core::guc::ModelGucConfig; +use vectorize_core::transformers::providers::{self, prepare_generic_embedding_request}; +use vectorize_core::transformers::types::Inputs; +use vectorize_core::types::Model; pub fn transform(input: &str, transformer: &Model, api_key: Option) -> Vec> { let runtime = tokio::runtime::Builder::new_current_thread() diff --git a/extension/src/transformers/openai.rs b/extension/src/transformers/openai.rs index a18d3a35..026e6f15 100644 --- a/extension/src/transformers/openai.rs +++ b/extension/src/transformers/openai.rs @@ -1,6 +1,6 @@ use anyhow::Result; use pgrx::prelude::*; -use vectorize_core::core::transformers::http_handler::handle_response; +use vectorize_core::transformers::http_handler::handle_response; use crate::guc::EMBEDDING_REQ_TIMEOUT_SEC; diff --git a/extension/src/types.rs b/extension/src/types.rs index 1bd1b50f..4b16380c 100644 --- a/extension/src/types.rs +++ b/extension/src/types.rs @@ -1,5 +1,5 @@ use pgrx::*; -use vectorize_core::core::types::{ +use vectorize_core::types::{ IndexDist as CoreIndexDist, SimilarityAlg as CoreSimilarityAlg, TableMethod as CoreTableMethod, }; diff --git a/extension/src/util.rs b/extension/src/util.rs index 58a1ad63..c059f2a6 100644 --- a/extension/src/util.rs +++ b/extension/src/util.rs @@ -5,10 +5,10 @@ use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; use sqlx::{Pool, Postgres}; use std::env; use url::{ParseError, Url}; -use vectorize_core::core::guc::VectorizeGuc; +use vectorize_core::guc::VectorizeGuc; use crate::guc; -use vectorize_core::core::types::{self, Model}; +use vectorize_core::types::{self, Model}; #[derive(Clone, Debug)] pub struct Config { diff --git a/extension/src/workers/mod.rs b/extension/src/workers/mod.rs index c0d09910..ccc22c7c 100644 --- a/extension/src/workers/mod.rs +++ b/extension/src/workers/mod.rs @@ -6,14 +6,14 @@ use pgmq::{Message, PGMQueueExt}; use pgrx::*; use sqlx::{Pool, Postgres}; use tiktoken_rs::cl100k_base; -use vectorize_core::core::errors::DatabaseError; -use vectorize_core::core::guc; -use vectorize_core::core::transformers::http_handler; -use vectorize_core::core::transformers::providers; -use vectorize_core::core::transformers::types::Inputs; -use vectorize_core::core::types; -use vectorize_core::core::types::{JobMessage, JobParams, VectorizeMeta}; -use vectorize_core::core::worker::ops; +use vectorize_core::errors::DatabaseError; +use vectorize_core::guc; +use vectorize_core::transformers::http_handler; +use vectorize_core::transformers::providers; +use vectorize_core::transformers::types::Inputs; +use vectorize_core::types; +use vectorize_core::types::{JobMessage, JobParams, VectorizeMeta}; +use vectorize_worker::ops; pub async fn run_worker( queue: PGMQueueExt, @@ -152,7 +152,7 @@ pub async fn execute_job(dbclient: &Pool, msg: Message) -> let paired_embeddings = http_handler::merge_input_output(inputs, embeddings.embeddings); match job_params.clone().table_method { - vectorize_core::core::types::TableMethod::append => { + vectorize_core::types::TableMethod::append => { ops::update_embeddings( dbclient, &job_params.schema, @@ -164,7 +164,7 @@ pub async fn execute_job(dbclient: &Pool, msg: Message) -> ) .await?; } - vectorize_core::core::types::TableMethod::join => { + vectorize_core::types::TableMethod::join => { ops::upsert_embedding_table( dbclient, &job_meta.name, diff --git a/server/Cargo.toml b/server/Cargo.toml index 0c22fabf..a3965feb 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -8,11 +8,11 @@ publish = false name = "vectorize_server" path = "src/lib.rs" -[[bin]] -name = "vectorize-worker" -path = "src/bin/worker.rs" [dependencies] +vectorize_core = { package = "vectorize-core", path = "../core" } +vectorize_worker = { package = "vectorize-worker", path = "../worker" } + actix-cors = "0.7.1" actix-http = "3.11.0" actix-rt = "2.10.0" @@ -20,23 +20,35 @@ actix-service = "2.0.3" actix-web = "4.11.0" anyhow = "1.0.98" async-trait = "0.1.88" +bytes = "1.10.1" chrono = {version = "0.4.41", features = ["serde"] } +clap = { version = "4.0", features = ["derive"] } env = "1.0.1" -env_logger = "0.11.8" +env_logger = "0.11" +fallible-iterator = "0.3.0" +futures = "0.3.31" lazy_static = "1.5.0" -log = "0.4.27" +log = "0.4" ollama-rs = "=0.2.1" pgmq = "0.30.1" +pgwire = { version = "0.30", features = ["server-api-aws-lc-rs"] } +postgres-protocol = "0.6.8" rand = "0.9.1" regex = "1.11.1" reqwest = { version = "0.12.16", features = ["json"] } serde = "1.0.219" -serde_json = "1.0.140" -sqlx = { version = "0.8", features = [ "runtime-tokio-native-tls", "postgres", "chrono", "json", "uuid"]} +serde_json = "1.0" +sqlparser = "0.51" +sqlx = { workspace = true} thiserror = "2.0.12" tiktoken-rs = "0.7.0" -tokio = { version = "1.45.0", features = ["full"] } -url = "2.5.4" +tokio = { version = "1.0", features = ["full"] } +tokio-postgres = "0.7" +tracing-subscriber = "0.3" +url = "2.2" utoipa = { version = "4", features = ["actix_extras", "chrono", "uuid"] } utoipa-swagger-ui = { version = "7", features = ["actix-web"] } uuid = { version = "1.16.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] } + +[dev-dependencies] +pgvector = { version = "0.4.1", features = ["postgres", "sqlx"] } diff --git a/server/Dockerfile b/server/Dockerfile index 0a4eaaba..9de79e1c 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -6,12 +6,13 @@ RUN apt-get update && \ WORKDIR /build -COPY .sqlx .sqlx/ -COPY src src/ +COPY core core/ +COPY worker worker/ +COPY server server/ + COPY Cargo.toml Cargo.lock ./ ENV SQLX_OFFLINE=1 -RUN cargo build --bin vectorize-worker --release RUN cargo build --bin vectorize-server --release FROM rust:1.87.0-slim-bookworm @@ -20,5 +21,4 @@ RUN apt-get update && \ apt-get install -y postgresql-client && apt-get clean && \ rm -rf /var/lib/apt/lists/* /var/cache/apt/archives/* -COPY --from=builder /build/target/release/vectorize-worker /usr/local/bin/vectorize-worker COPY --from=builder /build/target/release/vectorize-server /usr/local/bin/vectorize-server diff --git a/server/Makefile b/server/Makefile deleted file mode 100644 index 88d86033..00000000 --- a/server/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -RUST_LOG:=info - -include .env - -run-server: - RUST_LOG=$(RUST_LOG) DATABASE_URL=$(DATABASE_URL) cargo run --bin vectorize-server - -run-worker: - RUST_LOG=$(RUST_LOG) cargo run --bin vectorize-worker diff --git a/server/README.md b/server/README.md deleted file mode 100644 index d1c73592..00000000 --- a/server/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Embedding and Vector Search on any Postgres - -Quick start -- just run the contains locally: - -```bash -docker compose up -d -``` - -Create a table and insert some data: - -```bash -psql postgres://postgres:postgres@0.0.0.0:5432/postgres -c "CREATE TABLE my_table (id SERIAL PRIMARY KEY, content TEXT, updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP);" - -psql postgres://postgres:postgres@0.0.0.0:5432/postgres -c "INSERT INTO my_table (content) VALUES ('pizza'), ('pencil'), ('airplane');" -``` - -Generating embeddings: - -```bash -curl -X POST http://0.0.0.0:8080/api/v1/table -d '{ - "job_name": "my_job", - "src_table": "my_table", - "src_schema": "public", - "src_column": "content", - "primary_key": "id", - "update_time_col": "updated_at", - "model": "sentence-transformers/all-MiniLM-L6-v2" - }' \ - -H "Content-Type: application/json" -``` - -Search for similar content: - -```bash -curl -X GET http://0.0.0.0:8080/api/v1/search -d '{ - "job_name": "my_job", - "query": "food" - }' -H "Content-Type: application/json" | jq . -``` - -```json -[ - { - "content": "pizza", - "id": 1, - "similarity_score": 0.637525878100046, - "updated_at": "2025-05-31T01:13:09.349983+00:00" - }, - { - "content": "airplane", - "id": 3, - "similarity_score": 0.31890476700379766, - "updated_at": "2025-05-31T01:13:09.349983+00:00" - }, - { - "content": "pencil", - "id": 2, - "similarity_score": 0.25519378452338115, - "updated_at": "2025-05-31T01:13:09.349983+00:00" - } -] -``` diff --git a/server/src/bin/worker.rs b/server/src/bin/worker.rs index d26d8b01..9187cf46 100644 --- a/server/src/bin/worker.rs +++ b/server/src/bin/worker.rs @@ -1,6 +1,6 @@ -use vectorize_server::core::worker::base::Config; -use vectorize_server::executor::poll_job; -use vectorize_server::init; +use vectorize_core::config::Config; +use vectorize_core::init; +use vectorize_worker::executor::poll_job; #[tokio::main] async fn main() { diff --git a/server/src/config.rs b/server/src/config.rs deleted file mode 100644 index 4f67b9da..00000000 --- a/server/src/config.rs +++ /dev/null @@ -1,20 +0,0 @@ -#[derive(Clone, Debug)] -pub struct Config { - pub database_url: String, -} - -impl Default for Config { - fn default() -> Self { - Self { - database_url: from_env_default( - "DATABASE_URL", - "postgresql://postgres:postgres@localhost:5432/postgres", - ), - } - } -} - -/// source a variable from environment - use default if not exists -pub fn from_env_default(key: &str, default: &str) -> String { - env::var(key).unwrap_or_else(|_| default.to_owned()) -} diff --git a/server/src/core/worker/mod.rs b/server/src/core/worker/mod.rs deleted file mode 100644 index 17dc461e..00000000 --- a/server/src/core/worker/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod base; -pub mod ops; diff --git a/server/src/errors.rs b/server/src/errors.rs index 9cd8c7d5..81653acc 100644 --- a/server/src/errors.rs +++ b/server/src/errors.rs @@ -1,4 +1,4 @@ -use crate::core::errors; +use vectorize_core::errors; use actix_web::{HttpResponse, ResponseError, http::StatusCode, web::JsonConfig}; use anyhow::Error as AnyhowError; diff --git a/server/src/lib.rs b/server/src/lib.rs index 77f07825..92cd0cb3 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,8 +1,3 @@ -pub mod config; -pub mod core; -pub mod db; pub mod errors; -pub mod executor; -pub mod init; pub mod routes; pub mod server; diff --git a/server/src/main.rs b/server/src/main.rs index 8c1bf793..5ab0f6b9 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -1,10 +1,11 @@ use actix_cors::Cors; use actix_web::{App, HttpServer, middleware, web}; -use std::time::Duration; - -use vectorize_server::init; +use log::error; -use vectorize_server::core::worker::base::Config; +use std::time::Duration; +use vectorize_core::config::Config; +use vectorize_core::init; +use vectorize_worker::{WorkerHealthMonitor, start_vectorize_worker_with_monitoring}; #[actix_web::main] async fn main() { @@ -21,6 +22,22 @@ async fn main() { init::init_project(&pool, Some(&cfg.database_url)) .await .expect("Failed to initialize project"); + + // Start the vectorize worker with health monitoring + let worker_pool = pool.clone(); + let worker_cfg = cfg.clone(); + let worker_health_monitor = WorkerHealthMonitor::new(); + let worker_health_for_routes = worker_health_monitor.get_arc_clone(); + + tokio::spawn(async move { + if let Err(e) = + start_vectorize_worker_with_monitoring(worker_cfg, worker_pool, worker_health_monitor) + .await + { + error!("Failed to start vectorize worker: {}", e); + } + }); + let _ = HttpServer::new(move || { let cors = Cors::permissive(); @@ -29,7 +46,9 @@ async fn main() { .wrap(middleware::Logger::default()) .app_data(web::Data::new(cfg.clone())) .app_data(web::Data::new(pool.clone())) + .app_data(web::Data::new(worker_health_for_routes.clone())) .configure(vectorize_server::server::route_config) + .configure(vectorize_server::routes::health::configure_health_routes) }) .workers(server_workers) .keep_alive(Duration::from_secs(75)) diff --git a/server/src/routes/health.rs b/server/src/routes/health.rs new file mode 100644 index 00000000..2fb0cf1e --- /dev/null +++ b/server/src/routes/health.rs @@ -0,0 +1,91 @@ +use actix_web::{HttpResponse, Result, web}; +use serde_json::json; +use std::sync::Arc; +use std::time::SystemTime; +use tokio::sync::RwLock; + +use vectorize_worker::WorkerHealth; + +pub async fn health_check( + worker_health: web::Data>>, +) -> Result { + let health = worker_health.read().await; + let is_healthy = match &health.status { + vectorize_worker::WorkerStatus::Healthy => true, + vectorize_worker::WorkerStatus::Starting => { + health + .last_heartbeat + .elapsed() + .unwrap_or_default() + .as_secs() + < 120 + } + _ => false, + }; + + let response = json!({ + "status": if is_healthy { "healthy" } else { "unhealthy" }, + "worker": { + "status": format!("{:?}", health.status), + "last_heartbeat": health.last_heartbeat + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs(), + "jobs_processed": health.jobs_processed, + "uptime_seconds": health.uptime.as_secs(), + "restart_count": health.restart_count, + "last_error": health.last_error + }, + "timestamp": SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs() + }); + + if is_healthy { + Ok(HttpResponse::Ok().json(response)) + } else { + Ok(HttpResponse::ServiceUnavailable().json(response)) + } +} + +pub async fn liveness_check() -> Result { + Ok(HttpResponse::Ok().json(json!({ + "status": "alive", + "timestamp": SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs() + }))) +} + +pub async fn readiness_check( + worker_health: web::Data>>, +) -> Result { + let health = worker_health.read().await; + let is_ready = matches!(health.status, vectorize_worker::WorkerStatus::Healthy); + + let response = json!({ + "status": if is_ready { "ready" } else { "not_ready" }, + "worker_status": format!("{:?}", health.status), + "timestamp": SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH) + .unwrap_or_default() + .as_secs() + }); + + if is_ready { + Ok(HttpResponse::Ok().json(response)) + } else { + Ok(HttpResponse::ServiceUnavailable().json(response)) + } +} + +pub fn configure_health_routes(cfg: &mut web::ServiceConfig) { + cfg.service( + web::scope("/health") + .route("", web::get().to(health_check)) + .route("/live", web::get().to(liveness_check)) + .route("/ready", web::get().to(readiness_check)), + ); +} diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs index b33505e7..a881fcae 100644 --- a/server/src/routes/mod.rs +++ b/server/src/routes/mod.rs @@ -1,2 +1,3 @@ +pub mod health; pub mod search; pub mod table; diff --git a/server/src/routes/search.rs b/server/src/routes/search.rs index 15e7f27e..05bdbbe2 100644 --- a/server/src/routes/search.rs +++ b/server/src/routes/search.rs @@ -1,11 +1,12 @@ -use crate::core::query; -use crate::core::transformers::providers::prepare_generic_embedding_request; -use crate::{core::transformers::types::Inputs, errors::ServerError}; +use crate::errors::ServerError; use actix_web::{HttpResponse, get, web}; use serde::{Deserialize, Serialize}; use sqlx::{PgPool, Row, prelude::FromRow}; use utoipa::ToSchema; use uuid::Uuid; +use vectorize_core::query; +use vectorize_core::transformers::providers::prepare_generic_embedding_request; +use vectorize_core::transformers::types::Inputs; #[derive(Serialize, Deserialize, Debug, Clone, ToSchema, FromRow)] pub struct SearchRequest { @@ -20,23 +21,27 @@ pub struct SearchResponse { #[utoipa::path( context_path = "/api/v1", + params( + ("job_name" = String, Query, description = "Name of the vectorize job"), + ("query" = String, Query, description = "Search query string") + ), responses( ( - status = 200, description = "Search", - body = SearchResponse, + status = 200, description = "Search results", + body = Vec, ), ), )] #[get("/search")] pub async fn search( pool: web::Data, - payload: web::Json, + payload: web::Query, ) -> Result { let payload = payload.into_inner(); - let vectorizejob = crate::db::get_vectorize_job(&pool, &payload.job_name).await?; + let vectorizejob = vectorize_core::db::get_vectorize_job(&pool, &payload.job_name).await?; - let provider = crate::core::transformers::providers::get_provider( + let provider = vectorize_core::transformers::providers::get_provider( &vectorizejob.model.source, None, None, @@ -61,7 +66,6 @@ pub async fn search( 3, None, ); - log::error!("Generated query: {}", q); let results = sqlx::query(&q) .bind(&embeddings.embeddings[0]) .fetch_all(&**pool) diff --git a/server/src/routes/table.rs b/server/src/routes/table.rs index e6684781..a24b87ce 100644 --- a/server/src/routes/table.rs +++ b/server/src/routes/table.rs @@ -1,28 +1,12 @@ use crate::errors::ServerError; -use crate::init; -use crate::init::get_column_datatype; use actix_web::{HttpResponse, post, web}; use serde::{Deserialize, Serialize}; -use sqlx::{PgPool, prelude::FromRow}; +use sqlx::PgPool; use utoipa::ToSchema; use uuid::Uuid; +use vectorize_core::init::{self, get_column_datatype}; -use crate::core::types::{Model, model_to_string, string_to_model}; - -#[derive(Serialize, Deserialize, Debug, Clone, ToSchema, FromRow)] -pub struct VectorizeJob { - pub job_name: String, - pub src_table: String, - pub src_schema: String, - pub src_column: String, - pub primary_key: String, - pub update_time_col: String, - #[serde( - deserialize_with = "string_to_model", - serialize_with = "model_to_string" - )] - pub model: Model, -} +use vectorize_core::types::VectorizeJob; #[derive(Serialize, Deserialize, Debug, Clone, ToSchema)] pub struct JobResponse { diff --git a/server/tests/tests.rs b/server/tests/tests.rs index 3caa784d..505e9127 100644 --- a/server/tests/tests.rs +++ b/server/tests/tests.rs @@ -1,30 +1,19 @@ mod util; -use actix_web::{http::StatusCode, http::header, test}; -use env_logger; use serde_json::json; use util::common; use vectorize_server::routes::table::JobResponse; -// these tests require: -// 1. Postgres to be running -// 2. job-worker binary to be running -// easiest way is to run these with docker-compose.yml +// these tests require the following main server, vector-serve, and Postgres to be running +// easiest way is to use the docker-compose file in the root of the project #[ignore] -#[actix_web::test] -async fn test_table() { +#[tokio::test] +async fn test_lifecycle() { env_logger::init(); - let app = common::get_test_app().await; - - // Create test table with required columns - let cfg = vectorize_server::config::Config::default(); - let pool = sqlx::postgres::PgPoolOptions::new() - .max_connections(5) - .connect(&cfg.database_url) - .await - .expect("unable to connect to postgres"); + // Initialize the project (database setup, etc.) without creating test app + common::init_test_environment().await; let table = common::create_test_table().await; let job_name = format!("test_job_{}", table); @@ -37,21 +26,183 @@ async fn test_table() { "src_column": "content", "primary_key": "id", "update_time_col": "updated_at", - "model": "openai/text-embedding-3-small" + "model": "sentence-transformers/all-MiniLM-L6-v2" }); - let req = test::TestRequest::post() - .uri("/api/v1/table") - .insert_header((header::CONTENT_TYPE, "application/json")) - .set_json(&payload) - .to_request(); - - let resp = test::call_service(&app, req).await; + // Use reqwest to make HTTP request to running server + let client = reqwest::Client::new(); + let resp = client + .post("http://localhost:8080/api/v1/table") + .header("Content-Type", "application/json") + .json(&payload) + .send() + .await + .expect("Failed to send request"); - assert_eq!(resp.status(), StatusCode::OK, "{:?}", resp); + assert_eq!( + resp.status(), + reqwest::StatusCode::OK, + "Response status: {:?}", + resp.status() + ); - // deserialize the response body - let body = test::read_body(resp).await; - let response: JobResponse = serde_json::from_slice(&body).unwrap(); + let response: JobResponse = resp.json().await.expect("Failed to parse response"); assert!(!response.id.is_nil(), "Job ID should not be nil"); + + // sleep for 2 seconds + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + + // test searching the job + // test HTTP search endpoint with query parameters + let search_url = format!( + "http://0.0.0.0:8080/api/v1/search?job_name={}&query=food", + job_name + ); + let resp = client + .get(&search_url) + .send() + .await + .expect("Failed to send search request"); + + assert_eq!( + resp.status(), + reqwest::StatusCode::OK, + "Search response status: {:?}", + resp.status() + ); + + let search_results: Vec = + resp.json().await.expect("Failed to parse search response"); + + // Should return 3 results + assert_eq!(search_results.len(), 3); + + // First result should be pizza (highest similarity) + assert_eq!(search_results[0]["content"].as_str().unwrap(), "pizza"); + assert!(search_results[0]["similarity_score"].as_f64().unwrap() > 0.6); +} + +#[ignore] +#[tokio::test] +async fn test_health_monitoring() { + // Initialize the test environment without creating test app + common::init_test_environment().await; + + // Use reqwest to make HTTP requests to running server + let client = reqwest::Client::new(); + + // Test liveness endpoint + let resp = client + .get("http://localhost:8080/health/live") + .send() + .await + .expect("Failed to send liveness request"); + + assert_eq!( + resp.status(), + reqwest::StatusCode::OK, + "Liveness check should always return OK" + ); + + let liveness_response: serde_json::Value = resp + .json() + .await + .expect("Failed to parse liveness response"); + + assert_eq!(liveness_response["status"], "alive"); + assert!(liveness_response["timestamp"].is_number()); + + // Test main health endpoint + let resp = client + .get("http://localhost:8080/health") + .send() + .await + .expect("Failed to send health request"); + + // Health endpoint might return 200 (healthy) or 503 (unhealthy) depending on worker state + assert!( + resp.status() == reqwest::StatusCode::OK + || resp.status() == reqwest::StatusCode::SERVICE_UNAVAILABLE, + "Health check should return 200 or 503, got: {:?}", + resp.status() + ); + + let health_response: serde_json::Value = + resp.json().await.expect("Failed to parse health response"); + + // Verify response structure + assert!(health_response["status"].is_string()); + assert!(health_response["worker"].is_object()); + assert!(health_response["worker"]["status"].is_string()); + assert!(health_response["worker"]["last_heartbeat"].is_number()); + assert!(health_response["worker"]["jobs_processed"].is_number()); + assert!(health_response["worker"]["uptime_seconds"].is_number()); + assert!(health_response["worker"]["restart_count"].is_number()); + assert!(health_response["timestamp"].is_number()); + + println!( + "Health response: {}", + serde_json::to_string_pretty(&health_response).unwrap() + ); + + // Test readiness endpoint + let resp = client + .get("http://localhost:8080/health/ready") + .send() + .await + .expect("Failed to send readiness request"); + + // Readiness endpoint might return 200 (ready) or 503 (not ready) depending on worker state + assert!( + resp.status() == reqwest::StatusCode::OK + || resp.status() == reqwest::StatusCode::SERVICE_UNAVAILABLE, + "Readiness check should return 200 or 503, got: {:?}", + resp.status() + ); + + let readiness_response: serde_json::Value = resp + .json() + .await + .expect("Failed to parse readiness response"); + + assert!(readiness_response["status"].is_string()); + assert!(readiness_response["worker_status"].is_string()); + assert!(readiness_response["timestamp"].is_number()); + + // Wait a moment and check that worker metrics change over time + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + + let resp2 = client + .get("http://localhost:8080/health") + .send() + .await + .expect("Failed to send second health request"); + + let health_response2: serde_json::Value = resp2 + .json() + .await + .expect("Failed to parse second health response"); + + // The uptime should have increased + let uptime1 = health_response["worker"]["uptime_seconds"] + .as_u64() + .unwrap(); + let uptime2 = health_response2["worker"]["uptime_seconds"] + .as_u64() + .unwrap(); + assert!(uptime2 >= uptime1, "Uptime should increase over time"); + + // The heartbeat timestamp should have updated + let heartbeat1 = health_response["worker"]["last_heartbeat"] + .as_u64() + .unwrap(); + let heartbeat2 = health_response2["worker"]["last_heartbeat"] + .as_u64() + .unwrap(); + assert!( + heartbeat2 >= heartbeat1, + "Heartbeat should update over time" + ); + + println!("Health monitoring test completed successfully"); } diff --git a/server/tests/util.rs b/server/tests/util.rs index 4a58a67c..56f3e071 100644 --- a/server/tests/util.rs +++ b/server/tests/util.rs @@ -4,11 +4,11 @@ pub mod common { use actix_web::test; use actix_web::{App, Error, dev::ServiceResponse, web}; use rand::prelude::*; - use vectorize_server::init; + use vectorize_core::init; #[cfg(test)] pub async fn get_test_app() -> impl Service { - let cfg = vectorize_server::config::Config::default(); + let cfg = vectorize_core::config::Config::from_env(); let pool = sqlx::postgres::PgPoolOptions::new() .max_connections(5) .connect(&cfg.database_url) @@ -25,9 +25,24 @@ pub mod common { .await } + // Initialize test environment without creating Actix test service + // For use with reqwest-based tests that hit a running server + #[cfg(test)] + pub async fn init_test_environment() { + let cfg = vectorize_core::config::Config::from_env(); + let pool = sqlx::postgres::PgPoolOptions::new() + .max_connections(5) + .connect(&cfg.database_url) + .await + .expect("unable to connect to postgres"); + init::init_project(&pool, Some(&cfg.database_url)) + .await + .expect("Failed to initialize project"); + } + // creates a table in the vectorize_test schema pub async fn create_test_table() -> String { - let cfg = vectorize_server::config::Config::default(); + let cfg = vectorize_core::config::Config::from_env(); let pool = sqlx::postgres::PgPoolOptions::new() .max_connections(2) .connect(&cfg.database_url) @@ -54,16 +69,18 @@ pub mod common { .await .expect("unable to create test table"); - sqlx::query( - format!( - "insert into vectorize_test.{} (content, updated_at) values ('the quick brown fox jumps over the lazy dog', now());", - table + for record in ["pizza", "pencil", "airplane"] { + sqlx::query( + format!( + "insert into vectorize_test.{} (content, updated_at) values ('{}', now());", + table, record + ) + .as_str(), ) - .as_str(), - ) - .execute(&pool) - .await - .expect("unable to insert test data"); + .execute(&pool) + .await + .expect("unable to insert test data"); + } table } diff --git a/worker/Cargo.toml b/worker/Cargo.toml new file mode 100644 index 00000000..117ae4b3 --- /dev/null +++ b/worker/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "vectorize-worker" +version = "0.1.0" +edition = "2024" + +[dependencies] +vectorize_core = { package = "vectorize-core", path = "../core" } +serde = { workspace = true} +serde_json = { workspace = true } +tokio = { workspace = true } +log = { workspace = true } +sqlx = { workspace = true } +pgmq = { workspace = true } +anyhow = { workspace = true } +tiktoken-rs = { workspace = true } diff --git a/server/src/executor.rs b/worker/src/executor.rs similarity index 90% rename from server/src/executor.rs rename to worker/src/executor.rs index 0fee6ba9..2d8a4516 100644 --- a/server/src/executor.rs +++ b/worker/src/executor.rs @@ -1,22 +1,22 @@ -use crate::core::types::JobMessage; use pgmq::Message; use sqlx::PgPool; +use vectorize_core::errors::VectorizeError; +use vectorize_core::types::JobMessage; -use crate::core::transformers::{http_handler, providers, types::Inputs}; -use crate::core::worker::base::Config; -use crate::core::worker::ops; -use crate::db; -use crate::errors::ServerError; -use crate::init; +use crate::ops; use anyhow::Result; use pgmq::PGMQueueExt; use tiktoken_rs::cl100k_base; +use vectorize_core::config::Config; +use vectorize_core::db; +use vectorize_core::init; +use vectorize_core::transformers::{http_handler, providers, types::Inputs}; pub async fn poll_job( conn: &PgPool, queue: &PGMQueueExt, config: &Config, -) -> Result, ServerError> { +) -> Result, VectorizeError> { let msg: Message = match queue.read::(&config.queue_name, 300_i32).await { Ok(Some(msg)) => msg, @@ -56,13 +56,13 @@ pub async fn poll_job( ); } - queue.archive(&config.queue_name, msg_id).await?; + queue.delete(&config.queue_name, msg_id).await?; Ok(Some(())) } /// processes a single job from the queue -async fn execute_job(pool: &PgPool, msg: Message) -> Result<(), ServerError> { +async fn execute_job(pool: &PgPool, msg: Message) -> Result<(), VectorizeError> { let bpe = cl100k_base().unwrap(); let job_name = msg.message.job_name.clone(); diff --git a/worker/src/health.rs b/worker/src/health.rs new file mode 100644 index 00000000..f50aec9c --- /dev/null +++ b/worker/src/health.rs @@ -0,0 +1,112 @@ +use serde::{Deserialize, Serialize}; +use std::sync::Arc; +use std::time::{Duration, SystemTime}; +use tokio::sync::RwLock; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum WorkerStatus { + Starting, + Healthy, + Error(String), + Dead, +} + +#[derive(Debug, Clone, Serialize)] +pub struct WorkerHealth { + pub status: WorkerStatus, + pub last_heartbeat: SystemTime, + pub jobs_processed: u64, + pub last_error: Option, + pub uptime: Duration, + pub restart_count: u32, +} + +impl Default for WorkerHealth { + fn default() -> Self { + Self { + status: WorkerStatus::Starting, + last_heartbeat: SystemTime::now(), + jobs_processed: 0, + last_error: None, + uptime: Duration::from_secs(0), + restart_count: 0, + } + } +} + +#[derive(Debug, Clone)] +pub struct WorkerHealthMonitor { + health: Arc>, + start_time: SystemTime, +} + +impl Default for WorkerHealthMonitor { + fn default() -> Self { + Self::new() + } +} + +impl WorkerHealthMonitor { + pub fn new() -> Self { + Self { + health: Arc::new(RwLock::new(WorkerHealth::default())), + start_time: SystemTime::now(), + } + } + + pub async fn heartbeat(&self) { + let mut health = self.health.write().await; + health.last_heartbeat = SystemTime::now(); + health.uptime = self.start_time.elapsed().unwrap_or_default(); + } + + pub async fn set_status(&self, status: WorkerStatus) { + let mut health = self.health.write().await; + health.status = status; + health.last_heartbeat = SystemTime::now(); + health.uptime = self.start_time.elapsed().unwrap_or_default(); + } + + pub async fn job_processed(&self) { + let mut health = self.health.write().await; + health.jobs_processed += 1; + health.last_heartbeat = SystemTime::now(); + health.uptime = self.start_time.elapsed().unwrap_or_default(); + } + + pub async fn set_error(&self, error: String) { + let mut health = self.health.write().await; + health.status = WorkerStatus::Error(error.clone()); + health.last_error = Some(error); + health.last_heartbeat = SystemTime::now(); + health.uptime = self.start_time.elapsed().unwrap_or_default(); + } + + pub async fn increment_restart(&self) { + let mut health = self.health.write().await; + health.restart_count += 1; + health.status = WorkerStatus::Starting; + health.last_heartbeat = SystemTime::now(); + health.uptime = self.start_time.elapsed().unwrap_or_default(); + } + + pub async fn get_health(&self) -> WorkerHealth { + let health = self.health.read().await; + health.clone() + } + + pub async fn is_healthy(&self) -> bool { + let health = self.health.read().await; + let time_since_heartbeat = health.last_heartbeat.elapsed().unwrap_or_default(); + + match &health.status { + WorkerStatus::Healthy => time_since_heartbeat < Duration::from_secs(60), + WorkerStatus::Starting => time_since_heartbeat < Duration::from_secs(120), + _ => false, + } + } + + pub fn get_arc_clone(&self) -> Arc> { + Arc::clone(&self.health) + } +} diff --git a/worker/src/lib.rs b/worker/src/lib.rs new file mode 100644 index 00000000..e5f0fde9 --- /dev/null +++ b/worker/src/lib.rs @@ -0,0 +1,104 @@ +pub mod executor; +pub mod health; +pub mod ops; + +pub use health::*; + +use crate::executor::poll_job; +use log::{error, info, warn}; +use sqlx::PgPool; +use std::time::Duration; +use vectorize_core::config::Config; + +pub async fn start_vectorize_worker_with_monitoring( + cfg: Config, + pool: PgPool, + health_monitor: WorkerHealthMonitor, +) -> Result<(), Box> { + let mut restart_count = 0; + let max_restarts = 5; + let mut restart_delay = Duration::from_secs(1); + let max_restart_delay = Duration::from_secs(30); + + loop { + health_monitor.set_status(WorkerStatus::Starting).await; + + match start_vectorize_worker_inner(cfg.clone(), pool.clone(), health_monitor.clone()).await + { + Ok(_) => { + info!("Vectorize worker completed normally"); + break; + } + Err(e) => { + restart_count += 1; + let error_msg = format!("Worker failed: {}", e); + error!("{}", error_msg); + health_monitor.set_error(error_msg).await; + health_monitor.increment_restart().await; + + if restart_count >= max_restarts { + error!("Max restart attempts ({}) reached, giving up", max_restarts); + health_monitor.set_status(WorkerStatus::Dead).await; + return Err(format!( + "Worker failed permanently after {} restarts", + max_restarts + ) + .into()); + } + + warn!( + "Restarting worker in {:?} (attempt {}/{})", + restart_delay, restart_count, max_restarts + ); + tokio::time::sleep(restart_delay).await; + restart_delay = std::cmp::min(restart_delay * 2, max_restart_delay); + } + } + } + + Ok(()) +} + +async fn start_vectorize_worker_inner( + cfg: Config, + pool: PgPool, + health_monitor: WorkerHealthMonitor, +) -> Result<(), Box> { + info!("Starting vectorize worker"); + health_monitor.set_status(WorkerStatus::Healthy).await; + + let queue = pgmq::PGMQueueExt::new_with_pool(pool.clone()).await; + + loop { + health_monitor.heartbeat().await; + + match poll_job(&pool, &queue, &cfg).await { + Ok(Some(_)) => { + info!("processed job!"); + health_monitor.job_processed().await; + } + Ok(None) => { + info!( + "No messages in queue, waiting for {} seconds", + cfg.poll_interval + ); + tokio::time::sleep(tokio::time::Duration::from_secs(cfg.poll_interval)).await; + } + Err(e) => { + let error_msg = format!("Error processing job: {:?}", e); + error!("{}", error_msg); + health_monitor.set_error(error_msg).await; + tokio::time::sleep(tokio::time::Duration::from_secs(cfg.poll_interval)).await; + } + } + } +} + +// Legacy function for backward compatibility +pub async fn start_vectorize_worker( + cfg: Config, + pool: PgPool, +) -> Result<(), Box> { + let health_monitor = WorkerHealthMonitor::new(); + start_vectorize_worker_with_monitoring(cfg, pool, health_monitor).await +} diff --git a/server/src/core/worker/ops.rs b/worker/src/ops.rs similarity index 98% rename from server/src/core/worker/ops.rs rename to worker/src/ops.rs index 388603a1..b6572d2c 100644 --- a/server/src/core/worker/ops.rs +++ b/worker/src/ops.rs @@ -1,8 +1,8 @@ -use crate::core::{errors::VectorizeError, transformers::types::PairedEmbeddings}; use anyhow::Result; use serde_json::to_string; use sqlx::{Pool, Postgres}; use std::fmt::Write; +use vectorize_core::{errors::VectorizeError, transformers::types::PairedEmbeddings}; pub async fn upsert_embedding_table( conn: &Pool,