├── .cargo └── config.toml ├── .env ├── .github ├── live01.png ├── live02.png ├── live03.png └── workflows │ ├── gatling.yml │ └── release.yml ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── README.md ├── db └── v0001__create_people.sql ├── docker-compose-axum-local.yml ├── docker-compose-axum-prod.yml ├── docker-compose-dev.yml ├── docker-compose-touche-local.yml ├── docker-compose-touche-prod.yml ├── nginx.conf ├── rinha-axum ├── .sqlx │ ├── query-5734c5bec575d6962bf295754ea21ae83f96758ba99faf90d4d1bdc55ce91b55.json │ └── query-be7a47438fe43899e0a8cda76075c532153d4657d5fa0b044acecf55a2320f70.json ├── Cargo.toml ├── Dockerfile └── src │ ├── main.rs │ └── persistence.rs ├── rinha-core ├── Cargo.toml └── src │ └── lib.rs └── rinha-touche ├── Cargo.toml ├── Dockerfile └── src ├── main.rs └── persistence.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | rustflags = ["--cfg" , "uuid_unstable"] 3 | 4 | [registries.crates-io] 5 | protocol = "sparse" 6 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | DATABASE_URL=postgres://rinha:rinha@localhost:5432/rinha 2 | -------------------------------------------------------------------------------- /.github/live01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reu/rinha-backend-rust/eddc832df9c92d43508c7939f7c73d0070d93283/.github/live01.png -------------------------------------------------------------------------------- /.github/live02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reu/rinha-backend-rust/eddc832df9c92d43508c7939f7c73d0070d93283/.github/live02.png -------------------------------------------------------------------------------- /.github/live03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reu/rinha-backend-rust/eddc832df9c92d43508c7939f7c73d0070d93283/.github/live03.png -------------------------------------------------------------------------------- /.github/workflows/gatling.yml: -------------------------------------------------------------------------------- 1 | name: gatling 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | 7 | jobs: 8 | test: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | contents: write 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | lib: 16 | - { dockerfile: rinha-axum/Dockerfile, compose: docker-compose-axum-local.yml } 17 | - { dockerfile: rinha-touche/Dockerfile, compose: docker-compose-touche-local.yml } 18 | steps: 19 | - uses: actions/checkout@v3 20 | - run: docker build -f ${{ matrix.lib.dockerfile }} . 21 | - run: docker-compose -f ${{ matrix.lib.compose }} up -d 22 | - name: Load test 23 | run: | 24 | git clone --single-branch --quiet https://github.com/zanfranceschi/rinha-de-backend-2023-q3 25 | cd rinha-de-backend-2023-q3 26 | wget https://repo1.maven.org/maven2/io/gatling/highcharts/gatling-charts-highcharts-bundle/3.9.5/gatling-charts-highcharts-bundle-3.9.5-bundle.zip 27 | unzip gatling-charts-highcharts-bundle-3.9.5-bundle.zip 28 | cd gatling-charts-highcharts-bundle-3.9.5 29 | ./bin/gatling.sh -rm local -s RinhaBackendSimulation -rd "DESCRICAO" -rf $WORKSPACE/user-files/results -sf $WORKSPACE/user-files/simulations -rsf $WORKSPACE/user-files/resources 30 | echo GATLING_OUTPUT_FOLDER=$(ls $WORKSPACE/user-files/results | sort | head -n 1) >> $GITHUB_ENV 31 | env: 32 | WORKSPACE: ${{ github.workspace }}/rinha-de-backend-2023-q3/stress-test 33 | - run: echo ${{ env.GATLING_OUTPUT_FOLDER }} 34 | - name: Deploy 35 | uses: peaceiris/actions-gh-pages@v3 36 | with: 37 | github_token: ${{ secrets.GITHUB_TOKEN }} 38 | publish_dir: ${{ github.workspace }}/rinha-de-backend-2023-q3/stress-test/user-files/results/${{ env.GATLING_OUTPUT_FOLDER }} 39 | destination_dir: ${{ env.GATLING_OUTPUT_FOLDER }} 40 | - run: echo "Deployed at [https://reu.github.io/rinha-backend-rust/${{ env.GATLING_OUTPUT_FOLDER }}](https://reu.github.io/rinha-backend-rust/${{ env.GATLING_OUTPUT_FOLDER }})" >> "${GITHUB_STEP_SUMMARY}" 41 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | tags: 5 | - "v*" 6 | jobs: 7 | release: 8 | name: Publish to Dockerhub 9 | runs-on: ubuntu-latest 10 | strategy: 11 | fail-fast: false 12 | matrix: 13 | lib: 14 | - { dockerfile: rinha-axum/Dockerfile, image: rinha-backend-axum } 15 | - { dockerfile: rinha-touche/Dockerfile, image: rinha-backend-touche } 16 | steps: 17 | - uses: actions/checkout@v2 18 | 19 | - name: Get release version 20 | id: get_version 21 | uses: battila7/get-version-action@v2 22 | 23 | - run: docker login -u ${{ secrets.DOCKERHUB_USER }} -p ${{ secrets.DOCKERHUB_PASS }} 24 | 25 | - run: docker build -f ${{ matrix.lib.dockerfile }} -t rinha . 26 | - run: docker tag rinha rnavarro/${{ matrix.lib.image }}:latest 27 | - run: docker tag rinha rnavarro/${{ matrix.lib.image }}:${{ steps.get_version.outputs.major }} 28 | - run: docker tag rinha rnavarro/${{ matrix.lib.image }}:${{ steps.get_version.outputs.major }}.${{ steps.get_version.outputs.minor }} 29 | - run: docker tag rinha rnavarro/${{ matrix.lib.image }}:${{ steps.get_version.outputs.version-without-v }} 30 | 31 | - run: docker push rnavarro/${{ matrix.lib.image }}:latest 32 | - run: docker push rnavarro/${{ matrix.lib.image }}:${{ steps.get_version.outputs.major }} 33 | - run: docker push rnavarro/${{ matrix.lib.image }}:${{ steps.get_version.outputs.major }}.${{ steps.get_version.outputs.minor }} 34 | - run: docker push rnavarro/${{ matrix.lib.image }}:${{ steps.get_version.outputs.version-without-v }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "addr2line" 7 | version = "0.20.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" 10 | dependencies = [ 11 | "gimli", 12 | ] 13 | 14 | [[package]] 15 | name = "adler" 16 | version = "1.0.2" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 19 | 20 | [[package]] 21 | name = "ahash" 22 | version = "0.8.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" 25 | dependencies = [ 26 | "cfg-if", 27 | "getrandom", 28 | "once_cell", 29 | "version_check", 30 | ] 31 | 32 | [[package]] 33 | name = "allocator-api2" 34 | version = "0.2.16" 35 | source = "registry+https://github.com/rust-lang/crates.io-index" 36 | checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" 37 | 38 | [[package]] 39 | name = "array-init" 40 | version = "2.1.0" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" 43 | 44 | [[package]] 45 | name = "async-trait" 46 | version = "0.1.72" 47 | source = "registry+https://github.com/rust-lang/crates.io-index" 48 | checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09" 49 | dependencies = [ 50 | "proc-macro2", 51 | "quote", 52 | "syn 2.0.28", 53 | ] 54 | 55 | [[package]] 56 | name = "atoi" 57 | version = "2.0.0" 58 | source = "registry+https://github.com/rust-lang/crates.io-index" 59 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 60 | dependencies = [ 61 | "num-traits", 62 | ] 63 | 64 | [[package]] 65 | name = "atomic" 66 | version = "0.5.3" 67 | source = "registry+https://github.com/rust-lang/crates.io-index" 68 | checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" 69 | 70 | [[package]] 71 | name = "autocfg" 72 | version = "1.1.0" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 75 | 76 | [[package]] 77 | name = "axum" 78 | version = "0.6.20" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" 81 | dependencies = [ 82 | "async-trait", 83 | "axum-core", 84 | "bitflags 1.3.2", 85 | "bytes", 86 | "futures-util", 87 | "http", 88 | "http-body", 89 | "hyper", 90 | "itoa", 91 | "matchit", 92 | "memchr", 93 | "mime", 94 | "percent-encoding", 95 | "pin-project-lite", 96 | "rustversion", 97 | "serde", 98 | "serde_json", 99 | "serde_path_to_error", 100 | "serde_urlencoded", 101 | "sync_wrapper", 102 | "tokio", 103 | "tower", 104 | "tower-layer", 105 | "tower-service", 106 | ] 107 | 108 | [[package]] 109 | name = "axum-core" 110 | version = "0.3.4" 111 | source = "registry+https://github.com/rust-lang/crates.io-index" 112 | checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" 113 | dependencies = [ 114 | "async-trait", 115 | "bytes", 116 | "futures-util", 117 | "http", 118 | "http-body", 119 | "mime", 120 | "rustversion", 121 | "tower-layer", 122 | "tower-service", 123 | ] 124 | 125 | [[package]] 126 | name = "backtrace" 127 | version = "0.3.68" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" 130 | dependencies = [ 131 | "addr2line", 132 | "cc", 133 | "cfg-if", 134 | "libc", 135 | "miniz_oxide", 136 | "object", 137 | "rustc-demangle", 138 | ] 139 | 140 | [[package]] 141 | name = "base64" 142 | version = "0.13.1" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" 145 | 146 | [[package]] 147 | name = "base64" 148 | version = "0.21.2" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" 151 | 152 | [[package]] 153 | name = "base64ct" 154 | version = "1.6.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 157 | 158 | [[package]] 159 | name = "bitflags" 160 | version = "1.3.2" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 163 | 164 | [[package]] 165 | name = "bitflags" 166 | version = "2.4.0" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" 169 | dependencies = [ 170 | "serde", 171 | ] 172 | 173 | [[package]] 174 | name = "block-buffer" 175 | version = "0.10.4" 176 | source = "registry+https://github.com/rust-lang/crates.io-index" 177 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 178 | dependencies = [ 179 | "generic-array", 180 | ] 181 | 182 | [[package]] 183 | name = "bumpalo" 184 | version = "3.13.0" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" 187 | 188 | [[package]] 189 | name = "byteorder" 190 | version = "1.4.3" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 193 | 194 | [[package]] 195 | name = "bytes" 196 | version = "1.4.0" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 199 | 200 | [[package]] 201 | name = "cc" 202 | version = "1.0.82" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "305fe645edc1442a0fa8b6726ba61d422798d37a52e12eaecf4b022ebbb88f01" 205 | dependencies = [ 206 | "libc", 207 | ] 208 | 209 | [[package]] 210 | name = "cfg-if" 211 | version = "1.0.0" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 214 | 215 | [[package]] 216 | name = "const-oid" 217 | version = "0.9.5" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" 220 | 221 | [[package]] 222 | name = "cpufeatures" 223 | version = "0.2.9" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" 226 | dependencies = [ 227 | "libc", 228 | ] 229 | 230 | [[package]] 231 | name = "crc" 232 | version = "3.0.1" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" 235 | dependencies = [ 236 | "crc-catalog", 237 | ] 238 | 239 | [[package]] 240 | name = "crc-catalog" 241 | version = "2.2.0" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" 244 | 245 | [[package]] 246 | name = "crossbeam-queue" 247 | version = "0.3.8" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" 250 | dependencies = [ 251 | "cfg-if", 252 | "crossbeam-utils", 253 | ] 254 | 255 | [[package]] 256 | name = "crossbeam-utils" 257 | version = "0.8.16" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" 260 | dependencies = [ 261 | "cfg-if", 262 | ] 263 | 264 | [[package]] 265 | name = "crypto-common" 266 | version = "0.1.6" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 269 | dependencies = [ 270 | "generic-array", 271 | "typenum", 272 | ] 273 | 274 | [[package]] 275 | name = "dashmap" 276 | version = "5.5.0" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | checksum = "6943ae99c34386c84a470c499d3414f66502a41340aa895406e0d2e4a207b91d" 279 | dependencies = [ 280 | "cfg-if", 281 | "hashbrown", 282 | "lock_api", 283 | "once_cell", 284 | "parking_lot_core", 285 | ] 286 | 287 | [[package]] 288 | name = "der" 289 | version = "0.7.8" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" 292 | dependencies = [ 293 | "const-oid", 294 | "pem-rfc7468", 295 | "zeroize", 296 | ] 297 | 298 | [[package]] 299 | name = "deranged" 300 | version = "0.3.7" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "7684a49fb1af197853ef7b2ee694bc1f5b4179556f1e5710e1760c5db6f5e929" 303 | dependencies = [ 304 | "serde", 305 | ] 306 | 307 | [[package]] 308 | name = "digest" 309 | version = "0.10.7" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 312 | dependencies = [ 313 | "block-buffer", 314 | "const-oid", 315 | "crypto-common", 316 | "subtle", 317 | ] 318 | 319 | [[package]] 320 | name = "dotenvy" 321 | version = "0.15.7" 322 | source = "registry+https://github.com/rust-lang/crates.io-index" 323 | checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" 324 | 325 | [[package]] 326 | name = "either" 327 | version = "1.9.0" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" 330 | dependencies = [ 331 | "serde", 332 | ] 333 | 334 | [[package]] 335 | name = "equivalent" 336 | version = "1.0.1" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 339 | 340 | [[package]] 341 | name = "errno" 342 | version = "0.3.2" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" 345 | dependencies = [ 346 | "errno-dragonfly", 347 | "libc", 348 | "windows-sys", 349 | ] 350 | 351 | [[package]] 352 | name = "errno-dragonfly" 353 | version = "0.1.2" 354 | source = "registry+https://github.com/rust-lang/crates.io-index" 355 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 356 | dependencies = [ 357 | "cc", 358 | "libc", 359 | ] 360 | 361 | [[package]] 362 | name = "etcetera" 363 | version = "0.8.0" 364 | source = "registry+https://github.com/rust-lang/crates.io-index" 365 | checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 366 | dependencies = [ 367 | "cfg-if", 368 | "home", 369 | "windows-sys", 370 | ] 371 | 372 | [[package]] 373 | name = "event-listener" 374 | version = "2.5.3" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" 377 | 378 | [[package]] 379 | name = "fallible-iterator" 380 | version = "0.2.0" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" 383 | 384 | [[package]] 385 | name = "fastrand" 386 | version = "2.0.0" 387 | source = "registry+https://github.com/rust-lang/crates.io-index" 388 | checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764" 389 | 390 | [[package]] 391 | name = "flume" 392 | version = "0.10.14" 393 | source = "registry+https://github.com/rust-lang/crates.io-index" 394 | checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" 395 | dependencies = [ 396 | "futures-core", 397 | "futures-sink", 398 | "pin-project", 399 | "spin 0.9.8", 400 | ] 401 | 402 | [[package]] 403 | name = "fnv" 404 | version = "1.0.7" 405 | source = "registry+https://github.com/rust-lang/crates.io-index" 406 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 407 | 408 | [[package]] 409 | name = "form_urlencoded" 410 | version = "1.2.0" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" 413 | dependencies = [ 414 | "percent-encoding", 415 | ] 416 | 417 | [[package]] 418 | name = "futures-channel" 419 | version = "0.3.28" 420 | source = "registry+https://github.com/rust-lang/crates.io-index" 421 | checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" 422 | dependencies = [ 423 | "futures-core", 424 | "futures-sink", 425 | ] 426 | 427 | [[package]] 428 | name = "futures-core" 429 | version = "0.3.28" 430 | source = "registry+https://github.com/rust-lang/crates.io-index" 431 | checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 432 | 433 | [[package]] 434 | name = "futures-executor" 435 | version = "0.3.28" 436 | source = "registry+https://github.com/rust-lang/crates.io-index" 437 | checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" 438 | dependencies = [ 439 | "futures-core", 440 | "futures-task", 441 | "futures-util", 442 | ] 443 | 444 | [[package]] 445 | name = "futures-intrusive" 446 | version = "0.5.0" 447 | source = "registry+https://github.com/rust-lang/crates.io-index" 448 | checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" 449 | dependencies = [ 450 | "futures-core", 451 | "lock_api", 452 | "parking_lot", 453 | ] 454 | 455 | [[package]] 456 | name = "futures-io" 457 | version = "0.3.28" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" 460 | 461 | [[package]] 462 | name = "futures-macro" 463 | version = "0.3.28" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" 466 | dependencies = [ 467 | "proc-macro2", 468 | "quote", 469 | "syn 2.0.28", 470 | ] 471 | 472 | [[package]] 473 | name = "futures-sink" 474 | version = "0.3.28" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" 477 | 478 | [[package]] 479 | name = "futures-task" 480 | version = "0.3.28" 481 | source = "registry+https://github.com/rust-lang/crates.io-index" 482 | checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" 483 | 484 | [[package]] 485 | name = "futures-util" 486 | version = "0.3.28" 487 | source = "registry+https://github.com/rust-lang/crates.io-index" 488 | checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" 489 | dependencies = [ 490 | "futures-core", 491 | "futures-io", 492 | "futures-macro", 493 | "futures-sink", 494 | "futures-task", 495 | "memchr", 496 | "pin-project-lite", 497 | "pin-utils", 498 | "slab", 499 | ] 500 | 501 | [[package]] 502 | name = "generic-array" 503 | version = "0.14.7" 504 | source = "registry+https://github.com/rust-lang/crates.io-index" 505 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 506 | dependencies = [ 507 | "typenum", 508 | "version_check", 509 | ] 510 | 511 | [[package]] 512 | name = "getrandom" 513 | version = "0.2.10" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" 516 | dependencies = [ 517 | "cfg-if", 518 | "libc", 519 | "wasi", 520 | ] 521 | 522 | [[package]] 523 | name = "gimli" 524 | version = "0.27.3" 525 | source = "registry+https://github.com/rust-lang/crates.io-index" 526 | checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" 527 | 528 | [[package]] 529 | name = "hashbrown" 530 | version = "0.14.0" 531 | source = "registry+https://github.com/rust-lang/crates.io-index" 532 | checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" 533 | dependencies = [ 534 | "ahash", 535 | "allocator-api2", 536 | ] 537 | 538 | [[package]] 539 | name = "hashlink" 540 | version = "0.8.3" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "312f66718a2d7789ffef4f4b7b213138ed9f1eb3aa1d0d82fc99f88fb3ffd26f" 543 | dependencies = [ 544 | "hashbrown", 545 | ] 546 | 547 | [[package]] 548 | name = "headers" 549 | version = "0.3.8" 550 | source = "registry+https://github.com/rust-lang/crates.io-index" 551 | checksum = "f3e372db8e5c0d213e0cd0b9be18be2aca3d44cf2fe30a9d46a65581cd454584" 552 | dependencies = [ 553 | "base64 0.13.1", 554 | "bitflags 1.3.2", 555 | "bytes", 556 | "headers-core", 557 | "http", 558 | "httpdate", 559 | "mime", 560 | "sha1", 561 | ] 562 | 563 | [[package]] 564 | name = "headers-core" 565 | version = "0.2.0" 566 | source = "registry+https://github.com/rust-lang/crates.io-index" 567 | checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" 568 | dependencies = [ 569 | "http", 570 | ] 571 | 572 | [[package]] 573 | name = "heck" 574 | version = "0.4.1" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" 577 | dependencies = [ 578 | "unicode-segmentation", 579 | ] 580 | 581 | [[package]] 582 | name = "hermit-abi" 583 | version = "0.3.2" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" 586 | 587 | [[package]] 588 | name = "hex" 589 | version = "0.4.3" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 592 | 593 | [[package]] 594 | name = "hkdf" 595 | version = "0.12.3" 596 | source = "registry+https://github.com/rust-lang/crates.io-index" 597 | checksum = "791a029f6b9fc27657f6f188ec6e5e43f6911f6f878e0dc5501396e09809d437" 598 | dependencies = [ 599 | "hmac", 600 | ] 601 | 602 | [[package]] 603 | name = "hmac" 604 | version = "0.12.1" 605 | source = "registry+https://github.com/rust-lang/crates.io-index" 606 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 607 | dependencies = [ 608 | "digest", 609 | ] 610 | 611 | [[package]] 612 | name = "home" 613 | version = "0.5.5" 614 | source = "registry+https://github.com/rust-lang/crates.io-index" 615 | checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" 616 | dependencies = [ 617 | "windows-sys", 618 | ] 619 | 620 | [[package]] 621 | name = "http" 622 | version = "0.2.9" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" 625 | dependencies = [ 626 | "bytes", 627 | "fnv", 628 | "itoa", 629 | ] 630 | 631 | [[package]] 632 | name = "http-body" 633 | version = "0.4.5" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" 636 | dependencies = [ 637 | "bytes", 638 | "http", 639 | "pin-project-lite", 640 | ] 641 | 642 | [[package]] 643 | name = "httparse" 644 | version = "1.8.0" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 647 | 648 | [[package]] 649 | name = "httpdate" 650 | version = "1.0.2" 651 | source = "registry+https://github.com/rust-lang/crates.io-index" 652 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 653 | 654 | [[package]] 655 | name = "hyper" 656 | version = "0.14.27" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" 659 | dependencies = [ 660 | "bytes", 661 | "futures-channel", 662 | "futures-core", 663 | "futures-util", 664 | "http", 665 | "http-body", 666 | "httparse", 667 | "httpdate", 668 | "itoa", 669 | "pin-project-lite", 670 | "socket2 0.4.9", 671 | "tokio", 672 | "tower-service", 673 | "tracing", 674 | "want", 675 | ] 676 | 677 | [[package]] 678 | name = "idna" 679 | version = "0.4.0" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" 682 | dependencies = [ 683 | "unicode-bidi", 684 | "unicode-normalization", 685 | ] 686 | 687 | [[package]] 688 | name = "indexmap" 689 | version = "2.0.0" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" 692 | dependencies = [ 693 | "equivalent", 694 | "hashbrown", 695 | ] 696 | 697 | [[package]] 698 | name = "itertools" 699 | version = "0.10.5" 700 | source = "registry+https://github.com/rust-lang/crates.io-index" 701 | checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" 702 | dependencies = [ 703 | "either", 704 | ] 705 | 706 | [[package]] 707 | name = "itoa" 708 | version = "1.0.9" 709 | source = "registry+https://github.com/rust-lang/crates.io-index" 710 | checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" 711 | 712 | [[package]] 713 | name = "js-sys" 714 | version = "0.3.64" 715 | source = "registry+https://github.com/rust-lang/crates.io-index" 716 | checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" 717 | dependencies = [ 718 | "wasm-bindgen", 719 | ] 720 | 721 | [[package]] 722 | name = "lazy_static" 723 | version = "1.4.0" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 726 | dependencies = [ 727 | "spin 0.5.2", 728 | ] 729 | 730 | [[package]] 731 | name = "libc" 732 | version = "0.2.147" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 735 | 736 | [[package]] 737 | name = "libm" 738 | version = "0.2.7" 739 | source = "registry+https://github.com/rust-lang/crates.io-index" 740 | checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" 741 | 742 | [[package]] 743 | name = "libsqlite3-sys" 744 | version = "0.26.0" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" 747 | dependencies = [ 748 | "cc", 749 | "pkg-config", 750 | "vcpkg", 751 | ] 752 | 753 | [[package]] 754 | name = "linux-raw-sys" 755 | version = "0.4.5" 756 | source = "registry+https://github.com/rust-lang/crates.io-index" 757 | checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" 758 | 759 | [[package]] 760 | name = "lock_api" 761 | version = "0.4.10" 762 | source = "registry+https://github.com/rust-lang/crates.io-index" 763 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 764 | dependencies = [ 765 | "autocfg", 766 | "scopeguard", 767 | ] 768 | 769 | [[package]] 770 | name = "log" 771 | version = "0.4.19" 772 | source = "registry+https://github.com/rust-lang/crates.io-index" 773 | checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" 774 | 775 | [[package]] 776 | name = "matchit" 777 | version = "0.7.2" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "ed1202b2a6f884ae56f04cff409ab315c5ce26b5e58d7412e484f01fd52f52ef" 780 | 781 | [[package]] 782 | name = "md-5" 783 | version = "0.10.5" 784 | source = "registry+https://github.com/rust-lang/crates.io-index" 785 | checksum = "6365506850d44bff6e2fbcb5176cf63650e48bd45ef2fe2665ae1570e0f4b9ca" 786 | dependencies = [ 787 | "digest", 788 | ] 789 | 790 | [[package]] 791 | name = "memchr" 792 | version = "2.5.0" 793 | source = "registry+https://github.com/rust-lang/crates.io-index" 794 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 795 | 796 | [[package]] 797 | name = "mime" 798 | version = "0.3.17" 799 | source = "registry+https://github.com/rust-lang/crates.io-index" 800 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 801 | 802 | [[package]] 803 | name = "minimal-lexical" 804 | version = "0.2.1" 805 | source = "registry+https://github.com/rust-lang/crates.io-index" 806 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 807 | 808 | [[package]] 809 | name = "miniz_oxide" 810 | version = "0.7.1" 811 | source = "registry+https://github.com/rust-lang/crates.io-index" 812 | checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" 813 | dependencies = [ 814 | "adler", 815 | ] 816 | 817 | [[package]] 818 | name = "mio" 819 | version = "0.8.8" 820 | source = "registry+https://github.com/rust-lang/crates.io-index" 821 | checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 822 | dependencies = [ 823 | "libc", 824 | "wasi", 825 | "windows-sys", 826 | ] 827 | 828 | [[package]] 829 | name = "nom" 830 | version = "7.1.3" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 833 | dependencies = [ 834 | "memchr", 835 | "minimal-lexical", 836 | ] 837 | 838 | [[package]] 839 | name = "num-bigint-dig" 840 | version = "0.8.4" 841 | source = "registry+https://github.com/rust-lang/crates.io-index" 842 | checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 843 | dependencies = [ 844 | "byteorder", 845 | "lazy_static", 846 | "libm", 847 | "num-integer", 848 | "num-iter", 849 | "num-traits", 850 | "rand", 851 | "smallvec", 852 | "zeroize", 853 | ] 854 | 855 | [[package]] 856 | name = "num-integer" 857 | version = "0.1.45" 858 | source = "registry+https://github.com/rust-lang/crates.io-index" 859 | checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" 860 | dependencies = [ 861 | "autocfg", 862 | "num-traits", 863 | ] 864 | 865 | [[package]] 866 | name = "num-iter" 867 | version = "0.1.43" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" 870 | dependencies = [ 871 | "autocfg", 872 | "num-integer", 873 | "num-traits", 874 | ] 875 | 876 | [[package]] 877 | name = "num-traits" 878 | version = "0.2.16" 879 | source = "registry+https://github.com/rust-lang/crates.io-index" 880 | checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" 881 | dependencies = [ 882 | "autocfg", 883 | "libm", 884 | ] 885 | 886 | [[package]] 887 | name = "num_cpus" 888 | version = "1.16.0" 889 | source = "registry+https://github.com/rust-lang/crates.io-index" 890 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 891 | dependencies = [ 892 | "hermit-abi", 893 | "libc", 894 | ] 895 | 896 | [[package]] 897 | name = "object" 898 | version = "0.31.1" 899 | source = "registry+https://github.com/rust-lang/crates.io-index" 900 | checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" 901 | dependencies = [ 902 | "memchr", 903 | ] 904 | 905 | [[package]] 906 | name = "once_cell" 907 | version = "1.18.0" 908 | source = "registry+https://github.com/rust-lang/crates.io-index" 909 | checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" 910 | 911 | [[package]] 912 | name = "parking_lot" 913 | version = "0.12.1" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 916 | dependencies = [ 917 | "lock_api", 918 | "parking_lot_core", 919 | ] 920 | 921 | [[package]] 922 | name = "parking_lot_core" 923 | version = "0.9.8" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 926 | dependencies = [ 927 | "cfg-if", 928 | "libc", 929 | "redox_syscall", 930 | "smallvec", 931 | "windows-targets", 932 | ] 933 | 934 | [[package]] 935 | name = "paste" 936 | version = "1.0.14" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" 939 | 940 | [[package]] 941 | name = "pem-rfc7468" 942 | version = "0.7.0" 943 | source = "registry+https://github.com/rust-lang/crates.io-index" 944 | checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 945 | dependencies = [ 946 | "base64ct", 947 | ] 948 | 949 | [[package]] 950 | name = "percent-encoding" 951 | version = "2.3.0" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" 954 | 955 | [[package]] 956 | name = "phf" 957 | version = "0.11.2" 958 | source = "registry+https://github.com/rust-lang/crates.io-index" 959 | checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" 960 | dependencies = [ 961 | "phf_shared", 962 | ] 963 | 964 | [[package]] 965 | name = "phf_shared" 966 | version = "0.11.2" 967 | source = "registry+https://github.com/rust-lang/crates.io-index" 968 | checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" 969 | dependencies = [ 970 | "siphasher", 971 | ] 972 | 973 | [[package]] 974 | name = "pin-project" 975 | version = "1.1.3" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" 978 | dependencies = [ 979 | "pin-project-internal", 980 | ] 981 | 982 | [[package]] 983 | name = "pin-project-internal" 984 | version = "1.1.3" 985 | source = "registry+https://github.com/rust-lang/crates.io-index" 986 | checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" 987 | dependencies = [ 988 | "proc-macro2", 989 | "quote", 990 | "syn 2.0.28", 991 | ] 992 | 993 | [[package]] 994 | name = "pin-project-lite" 995 | version = "0.2.12" 996 | source = "registry+https://github.com/rust-lang/crates.io-index" 997 | checksum = "12cc1b0bf1727a77a54b6654e7b5f1af8604923edc8b81885f8ec92f9e3f0a05" 998 | 999 | [[package]] 1000 | name = "pin-utils" 1001 | version = "0.1.0" 1002 | source = "registry+https://github.com/rust-lang/crates.io-index" 1003 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1004 | 1005 | [[package]] 1006 | name = "pkcs1" 1007 | version = "0.7.5" 1008 | source = "registry+https://github.com/rust-lang/crates.io-index" 1009 | checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 1010 | dependencies = [ 1011 | "der", 1012 | "pkcs8", 1013 | "spki", 1014 | ] 1015 | 1016 | [[package]] 1017 | name = "pkcs8" 1018 | version = "0.10.2" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 1021 | dependencies = [ 1022 | "der", 1023 | "spki", 1024 | ] 1025 | 1026 | [[package]] 1027 | name = "pkg-config" 1028 | version = "0.3.27" 1029 | source = "registry+https://github.com/rust-lang/crates.io-index" 1030 | checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" 1031 | 1032 | [[package]] 1033 | name = "postgres" 1034 | version = "0.19.6" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "2843af30d9b6dccec9f8779eb50d56cfbec54b38c7b1bbaf50b37d6c8a4f8959" 1037 | dependencies = [ 1038 | "bytes", 1039 | "fallible-iterator", 1040 | "futures-util", 1041 | "log", 1042 | "tokio", 1043 | "tokio-postgres", 1044 | ] 1045 | 1046 | [[package]] 1047 | name = "postgres-protocol" 1048 | version = "0.6.6" 1049 | source = "registry+https://github.com/rust-lang/crates.io-index" 1050 | checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" 1051 | dependencies = [ 1052 | "base64 0.21.2", 1053 | "byteorder", 1054 | "bytes", 1055 | "fallible-iterator", 1056 | "hmac", 1057 | "md-5", 1058 | "memchr", 1059 | "rand", 1060 | "sha2", 1061 | "stringprep", 1062 | ] 1063 | 1064 | [[package]] 1065 | name = "postgres-types" 1066 | version = "0.2.6" 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" 1068 | checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c" 1069 | dependencies = [ 1070 | "array-init", 1071 | "bytes", 1072 | "fallible-iterator", 1073 | "postgres-protocol", 1074 | "time", 1075 | "uuid", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "ppv-lite86" 1080 | version = "0.2.17" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 1083 | 1084 | [[package]] 1085 | name = "proc-macro2" 1086 | version = "1.0.66" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" 1089 | dependencies = [ 1090 | "unicode-ident", 1091 | ] 1092 | 1093 | [[package]] 1094 | name = "quote" 1095 | version = "1.0.32" 1096 | source = "registry+https://github.com/rust-lang/crates.io-index" 1097 | checksum = "50f3b39ccfb720540debaa0164757101c08ecb8d326b15358ce76a62c7e85965" 1098 | dependencies = [ 1099 | "proc-macro2", 1100 | ] 1101 | 1102 | [[package]] 1103 | name = "r2d2" 1104 | version = "0.8.10" 1105 | source = "registry+https://github.com/rust-lang/crates.io-index" 1106 | checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" 1107 | dependencies = [ 1108 | "log", 1109 | "parking_lot", 1110 | "scheduled-thread-pool", 1111 | ] 1112 | 1113 | [[package]] 1114 | name = "r2d2_postgres" 1115 | version = "0.18.1" 1116 | source = "registry+https://github.com/rust-lang/crates.io-index" 1117 | checksum = "7029c56be658cb54f321e0bee597810ee16796b735fa2559d7056bf06b12230b" 1118 | dependencies = [ 1119 | "postgres", 1120 | "r2d2", 1121 | ] 1122 | 1123 | [[package]] 1124 | name = "rand" 1125 | version = "0.8.5" 1126 | source = "registry+https://github.com/rust-lang/crates.io-index" 1127 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 1128 | dependencies = [ 1129 | "libc", 1130 | "rand_chacha", 1131 | "rand_core", 1132 | ] 1133 | 1134 | [[package]] 1135 | name = "rand_chacha" 1136 | version = "0.3.1" 1137 | source = "registry+https://github.com/rust-lang/crates.io-index" 1138 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 1139 | dependencies = [ 1140 | "ppv-lite86", 1141 | "rand_core", 1142 | ] 1143 | 1144 | [[package]] 1145 | name = "rand_core" 1146 | version = "0.6.4" 1147 | source = "registry+https://github.com/rust-lang/crates.io-index" 1148 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 1149 | dependencies = [ 1150 | "getrandom", 1151 | ] 1152 | 1153 | [[package]] 1154 | name = "redox_syscall" 1155 | version = "0.3.5" 1156 | source = "registry+https://github.com/rust-lang/crates.io-index" 1157 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 1158 | dependencies = [ 1159 | "bitflags 1.3.2", 1160 | ] 1161 | 1162 | [[package]] 1163 | name = "rinha-axum" 1164 | version = "0.1.0" 1165 | dependencies = [ 1166 | "axum", 1167 | "dashmap", 1168 | "rinha-core", 1169 | "serde", 1170 | "serde_json", 1171 | "sqlx", 1172 | "time", 1173 | "tokio", 1174 | "uuid", 1175 | ] 1176 | 1177 | [[package]] 1178 | name = "rinha-core" 1179 | version = "0.1.0" 1180 | dependencies = [ 1181 | "serde", 1182 | "sqlx", 1183 | "time", 1184 | "uuid", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "rinha-touche" 1189 | version = "0.1.0" 1190 | dependencies = [ 1191 | "dashmap", 1192 | "postgres", 1193 | "r2d2", 1194 | "r2d2_postgres", 1195 | "rinha-core", 1196 | "serde", 1197 | "serde_json", 1198 | "serde_urlencoded", 1199 | "time", 1200 | "touche", 1201 | "uuid", 1202 | ] 1203 | 1204 | [[package]] 1205 | name = "rsa" 1206 | version = "0.9.2" 1207 | source = "registry+https://github.com/rust-lang/crates.io-index" 1208 | checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" 1209 | dependencies = [ 1210 | "byteorder", 1211 | "const-oid", 1212 | "digest", 1213 | "num-bigint-dig", 1214 | "num-integer", 1215 | "num-iter", 1216 | "num-traits", 1217 | "pkcs1", 1218 | "pkcs8", 1219 | "rand_core", 1220 | "signature", 1221 | "spki", 1222 | "subtle", 1223 | "zeroize", 1224 | ] 1225 | 1226 | [[package]] 1227 | name = "rustc-demangle" 1228 | version = "0.1.23" 1229 | source = "registry+https://github.com/rust-lang/crates.io-index" 1230 | checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" 1231 | 1232 | [[package]] 1233 | name = "rustix" 1234 | version = "0.38.8" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" 1237 | dependencies = [ 1238 | "bitflags 2.4.0", 1239 | "errno", 1240 | "libc", 1241 | "linux-raw-sys", 1242 | "windows-sys", 1243 | ] 1244 | 1245 | [[package]] 1246 | name = "rustversion" 1247 | version = "1.0.14" 1248 | source = "registry+https://github.com/rust-lang/crates.io-index" 1249 | checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" 1250 | 1251 | [[package]] 1252 | name = "ryu" 1253 | version = "1.0.15" 1254 | source = "registry+https://github.com/rust-lang/crates.io-index" 1255 | checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" 1256 | 1257 | [[package]] 1258 | name = "scheduled-thread-pool" 1259 | version = "0.2.7" 1260 | source = "registry+https://github.com/rust-lang/crates.io-index" 1261 | checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" 1262 | dependencies = [ 1263 | "parking_lot", 1264 | ] 1265 | 1266 | [[package]] 1267 | name = "scopeguard" 1268 | version = "1.2.0" 1269 | source = "registry+https://github.com/rust-lang/crates.io-index" 1270 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 1271 | 1272 | [[package]] 1273 | name = "serde" 1274 | version = "1.0.183" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "32ac8da02677876d532745a130fc9d8e6edfa81a269b107c5b00829b91d8eb3c" 1277 | dependencies = [ 1278 | "serde_derive", 1279 | ] 1280 | 1281 | [[package]] 1282 | name = "serde_derive" 1283 | version = "1.0.183" 1284 | source = "registry+https://github.com/rust-lang/crates.io-index" 1285 | checksum = "aafe972d60b0b9bee71a91b92fee2d4fb3c9d7e8f6b179aa99f27203d99a4816" 1286 | dependencies = [ 1287 | "proc-macro2", 1288 | "quote", 1289 | "syn 2.0.28", 1290 | ] 1291 | 1292 | [[package]] 1293 | name = "serde_json" 1294 | version = "1.0.104" 1295 | source = "registry+https://github.com/rust-lang/crates.io-index" 1296 | checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" 1297 | dependencies = [ 1298 | "itoa", 1299 | "ryu", 1300 | "serde", 1301 | ] 1302 | 1303 | [[package]] 1304 | name = "serde_path_to_error" 1305 | version = "0.1.14" 1306 | source = "registry+https://github.com/rust-lang/crates.io-index" 1307 | checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335" 1308 | dependencies = [ 1309 | "itoa", 1310 | "serde", 1311 | ] 1312 | 1313 | [[package]] 1314 | name = "serde_urlencoded" 1315 | version = "0.7.1" 1316 | source = "registry+https://github.com/rust-lang/crates.io-index" 1317 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 1318 | dependencies = [ 1319 | "form_urlencoded", 1320 | "itoa", 1321 | "ryu", 1322 | "serde", 1323 | ] 1324 | 1325 | [[package]] 1326 | name = "sha1" 1327 | version = "0.10.5" 1328 | source = "registry+https://github.com/rust-lang/crates.io-index" 1329 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 1330 | dependencies = [ 1331 | "cfg-if", 1332 | "cpufeatures", 1333 | "digest", 1334 | ] 1335 | 1336 | [[package]] 1337 | name = "sha2" 1338 | version = "0.10.7" 1339 | source = "registry+https://github.com/rust-lang/crates.io-index" 1340 | checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" 1341 | dependencies = [ 1342 | "cfg-if", 1343 | "cpufeatures", 1344 | "digest", 1345 | ] 1346 | 1347 | [[package]] 1348 | name = "signal-hook-registry" 1349 | version = "1.4.1" 1350 | source = "registry+https://github.com/rust-lang/crates.io-index" 1351 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 1352 | dependencies = [ 1353 | "libc", 1354 | ] 1355 | 1356 | [[package]] 1357 | name = "signature" 1358 | version = "2.1.0" 1359 | source = "registry+https://github.com/rust-lang/crates.io-index" 1360 | checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" 1361 | dependencies = [ 1362 | "digest", 1363 | "rand_core", 1364 | ] 1365 | 1366 | [[package]] 1367 | name = "siphasher" 1368 | version = "0.3.10" 1369 | source = "registry+https://github.com/rust-lang/crates.io-index" 1370 | checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" 1371 | 1372 | [[package]] 1373 | name = "slab" 1374 | version = "0.4.8" 1375 | source = "registry+https://github.com/rust-lang/crates.io-index" 1376 | checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" 1377 | dependencies = [ 1378 | "autocfg", 1379 | ] 1380 | 1381 | [[package]] 1382 | name = "smallvec" 1383 | version = "1.11.0" 1384 | source = "registry+https://github.com/rust-lang/crates.io-index" 1385 | checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" 1386 | 1387 | [[package]] 1388 | name = "socket2" 1389 | version = "0.4.9" 1390 | source = "registry+https://github.com/rust-lang/crates.io-index" 1391 | checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" 1392 | dependencies = [ 1393 | "libc", 1394 | "winapi", 1395 | ] 1396 | 1397 | [[package]] 1398 | name = "socket2" 1399 | version = "0.5.3" 1400 | source = "registry+https://github.com/rust-lang/crates.io-index" 1401 | checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" 1402 | dependencies = [ 1403 | "libc", 1404 | "windows-sys", 1405 | ] 1406 | 1407 | [[package]] 1408 | name = "spin" 1409 | version = "0.5.2" 1410 | source = "registry+https://github.com/rust-lang/crates.io-index" 1411 | checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" 1412 | 1413 | [[package]] 1414 | name = "spin" 1415 | version = "0.9.8" 1416 | source = "registry+https://github.com/rust-lang/crates.io-index" 1417 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 1418 | dependencies = [ 1419 | "lock_api", 1420 | ] 1421 | 1422 | [[package]] 1423 | name = "spki" 1424 | version = "0.7.2" 1425 | source = "registry+https://github.com/rust-lang/crates.io-index" 1426 | checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" 1427 | dependencies = [ 1428 | "base64ct", 1429 | "der", 1430 | ] 1431 | 1432 | [[package]] 1433 | name = "sqlformat" 1434 | version = "0.2.1" 1435 | source = "registry+https://github.com/rust-lang/crates.io-index" 1436 | checksum = "0c12bc9199d1db8234678b7051747c07f517cdcf019262d1847b94ec8b1aee3e" 1437 | dependencies = [ 1438 | "itertools", 1439 | "nom", 1440 | "unicode_categories", 1441 | ] 1442 | 1443 | [[package]] 1444 | name = "sqlx" 1445 | version = "0.7.1" 1446 | source = "registry+https://github.com/rust-lang/crates.io-index" 1447 | checksum = "8e58421b6bc416714d5115a2ca953718f6c621a51b68e4f4922aea5a4391a721" 1448 | dependencies = [ 1449 | "sqlx-core", 1450 | "sqlx-macros", 1451 | "sqlx-mysql", 1452 | "sqlx-postgres", 1453 | "sqlx-sqlite", 1454 | ] 1455 | 1456 | [[package]] 1457 | name = "sqlx-core" 1458 | version = "0.7.1" 1459 | source = "registry+https://github.com/rust-lang/crates.io-index" 1460 | checksum = "dd4cef4251aabbae751a3710927945901ee1d97ee96d757f6880ebb9a79bfd53" 1461 | dependencies = [ 1462 | "ahash", 1463 | "atoi", 1464 | "byteorder", 1465 | "bytes", 1466 | "crc", 1467 | "crossbeam-queue", 1468 | "dotenvy", 1469 | "either", 1470 | "event-listener", 1471 | "futures-channel", 1472 | "futures-core", 1473 | "futures-intrusive", 1474 | "futures-io", 1475 | "futures-util", 1476 | "hashlink", 1477 | "hex", 1478 | "indexmap", 1479 | "log", 1480 | "memchr", 1481 | "once_cell", 1482 | "paste", 1483 | "percent-encoding", 1484 | "serde", 1485 | "serde_json", 1486 | "sha2", 1487 | "smallvec", 1488 | "sqlformat", 1489 | "thiserror", 1490 | "time", 1491 | "tokio", 1492 | "tokio-stream", 1493 | "tracing", 1494 | "url", 1495 | "uuid", 1496 | ] 1497 | 1498 | [[package]] 1499 | name = "sqlx-macros" 1500 | version = "0.7.1" 1501 | source = "registry+https://github.com/rust-lang/crates.io-index" 1502 | checksum = "208e3165167afd7f3881b16c1ef3f2af69fa75980897aac8874a0696516d12c2" 1503 | dependencies = [ 1504 | "proc-macro2", 1505 | "quote", 1506 | "sqlx-core", 1507 | "sqlx-macros-core", 1508 | "syn 1.0.109", 1509 | ] 1510 | 1511 | [[package]] 1512 | name = "sqlx-macros-core" 1513 | version = "0.7.1" 1514 | source = "registry+https://github.com/rust-lang/crates.io-index" 1515 | checksum = "8a4a8336d278c62231d87f24e8a7a74898156e34c1c18942857be2acb29c7dfc" 1516 | dependencies = [ 1517 | "dotenvy", 1518 | "either", 1519 | "heck", 1520 | "hex", 1521 | "once_cell", 1522 | "proc-macro2", 1523 | "quote", 1524 | "serde", 1525 | "serde_json", 1526 | "sha2", 1527 | "sqlx-core", 1528 | "sqlx-mysql", 1529 | "sqlx-postgres", 1530 | "sqlx-sqlite", 1531 | "syn 1.0.109", 1532 | "tempfile", 1533 | "tokio", 1534 | "url", 1535 | ] 1536 | 1537 | [[package]] 1538 | name = "sqlx-mysql" 1539 | version = "0.7.1" 1540 | source = "registry+https://github.com/rust-lang/crates.io-index" 1541 | checksum = "8ca69bf415b93b60b80dc8fda3cb4ef52b2336614d8da2de5456cc942a110482" 1542 | dependencies = [ 1543 | "atoi", 1544 | "base64 0.21.2", 1545 | "bitflags 2.4.0", 1546 | "byteorder", 1547 | "bytes", 1548 | "crc", 1549 | "digest", 1550 | "dotenvy", 1551 | "either", 1552 | "futures-channel", 1553 | "futures-core", 1554 | "futures-io", 1555 | "futures-util", 1556 | "generic-array", 1557 | "hex", 1558 | "hkdf", 1559 | "hmac", 1560 | "itoa", 1561 | "log", 1562 | "md-5", 1563 | "memchr", 1564 | "once_cell", 1565 | "percent-encoding", 1566 | "rand", 1567 | "rsa", 1568 | "serde", 1569 | "sha1", 1570 | "sha2", 1571 | "smallvec", 1572 | "sqlx-core", 1573 | "stringprep", 1574 | "thiserror", 1575 | "time", 1576 | "tracing", 1577 | "uuid", 1578 | "whoami", 1579 | ] 1580 | 1581 | [[package]] 1582 | name = "sqlx-postgres" 1583 | version = "0.7.1" 1584 | source = "registry+https://github.com/rust-lang/crates.io-index" 1585 | checksum = "a0db2df1b8731c3651e204629dd55e52adbae0462fa1bdcbed56a2302c18181e" 1586 | dependencies = [ 1587 | "atoi", 1588 | "base64 0.21.2", 1589 | "bitflags 2.4.0", 1590 | "byteorder", 1591 | "crc", 1592 | "dotenvy", 1593 | "etcetera", 1594 | "futures-channel", 1595 | "futures-core", 1596 | "futures-io", 1597 | "futures-util", 1598 | "hex", 1599 | "hkdf", 1600 | "hmac", 1601 | "home", 1602 | "itoa", 1603 | "log", 1604 | "md-5", 1605 | "memchr", 1606 | "once_cell", 1607 | "rand", 1608 | "serde", 1609 | "serde_json", 1610 | "sha1", 1611 | "sha2", 1612 | "smallvec", 1613 | "sqlx-core", 1614 | "stringprep", 1615 | "thiserror", 1616 | "time", 1617 | "tracing", 1618 | "uuid", 1619 | "whoami", 1620 | ] 1621 | 1622 | [[package]] 1623 | name = "sqlx-sqlite" 1624 | version = "0.7.1" 1625 | source = "registry+https://github.com/rust-lang/crates.io-index" 1626 | checksum = "be4c21bf34c7cae5b283efb3ac1bcc7670df7561124dc2f8bdc0b59be40f79a2" 1627 | dependencies = [ 1628 | "atoi", 1629 | "flume", 1630 | "futures-channel", 1631 | "futures-core", 1632 | "futures-executor", 1633 | "futures-intrusive", 1634 | "futures-util", 1635 | "libsqlite3-sys", 1636 | "log", 1637 | "percent-encoding", 1638 | "serde", 1639 | "sqlx-core", 1640 | "time", 1641 | "tracing", 1642 | "url", 1643 | "uuid", 1644 | ] 1645 | 1646 | [[package]] 1647 | name = "stringprep" 1648 | version = "0.1.3" 1649 | source = "registry+https://github.com/rust-lang/crates.io-index" 1650 | checksum = "db3737bde7edce97102e0e2b15365bf7a20bfdb5f60f4f9e8d7004258a51a8da" 1651 | dependencies = [ 1652 | "unicode-bidi", 1653 | "unicode-normalization", 1654 | ] 1655 | 1656 | [[package]] 1657 | name = "subtle" 1658 | version = "2.5.0" 1659 | source = "registry+https://github.com/rust-lang/crates.io-index" 1660 | checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" 1661 | 1662 | [[package]] 1663 | name = "syn" 1664 | version = "1.0.109" 1665 | source = "registry+https://github.com/rust-lang/crates.io-index" 1666 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 1667 | dependencies = [ 1668 | "proc-macro2", 1669 | "quote", 1670 | "unicode-ident", 1671 | ] 1672 | 1673 | [[package]] 1674 | name = "syn" 1675 | version = "2.0.28" 1676 | source = "registry+https://github.com/rust-lang/crates.io-index" 1677 | checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567" 1678 | dependencies = [ 1679 | "proc-macro2", 1680 | "quote", 1681 | "unicode-ident", 1682 | ] 1683 | 1684 | [[package]] 1685 | name = "sync_wrapper" 1686 | version = "0.1.2" 1687 | source = "registry+https://github.com/rust-lang/crates.io-index" 1688 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 1689 | 1690 | [[package]] 1691 | name = "tempfile" 1692 | version = "3.7.1" 1693 | source = "registry+https://github.com/rust-lang/crates.io-index" 1694 | checksum = "dc02fddf48964c42031a0b3fe0428320ecf3a73c401040fc0096f97794310651" 1695 | dependencies = [ 1696 | "cfg-if", 1697 | "fastrand", 1698 | "redox_syscall", 1699 | "rustix", 1700 | "windows-sys", 1701 | ] 1702 | 1703 | [[package]] 1704 | name = "thiserror" 1705 | version = "1.0.44" 1706 | source = "registry+https://github.com/rust-lang/crates.io-index" 1707 | checksum = "611040a08a0439f8248d1990b111c95baa9c704c805fa1f62104b39655fd7f90" 1708 | dependencies = [ 1709 | "thiserror-impl", 1710 | ] 1711 | 1712 | [[package]] 1713 | name = "thiserror-impl" 1714 | version = "1.0.44" 1715 | source = "registry+https://github.com/rust-lang/crates.io-index" 1716 | checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" 1717 | dependencies = [ 1718 | "proc-macro2", 1719 | "quote", 1720 | "syn 2.0.28", 1721 | ] 1722 | 1723 | [[package]] 1724 | name = "threadpool" 1725 | version = "1.8.1" 1726 | source = "registry+https://github.com/rust-lang/crates.io-index" 1727 | checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" 1728 | dependencies = [ 1729 | "num_cpus", 1730 | ] 1731 | 1732 | [[package]] 1733 | name = "time" 1734 | version = "0.3.25" 1735 | source = "registry+https://github.com/rust-lang/crates.io-index" 1736 | checksum = "b0fdd63d58b18d663fbdf70e049f00a22c8e42be082203be7f26589213cd75ea" 1737 | dependencies = [ 1738 | "deranged", 1739 | "itoa", 1740 | "serde", 1741 | "time-core", 1742 | "time-macros", 1743 | ] 1744 | 1745 | [[package]] 1746 | name = "time-core" 1747 | version = "0.1.1" 1748 | source = "registry+https://github.com/rust-lang/crates.io-index" 1749 | checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" 1750 | 1751 | [[package]] 1752 | name = "time-macros" 1753 | version = "0.2.11" 1754 | source = "registry+https://github.com/rust-lang/crates.io-index" 1755 | checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd" 1756 | dependencies = [ 1757 | "time-core", 1758 | ] 1759 | 1760 | [[package]] 1761 | name = "tinyvec" 1762 | version = "1.6.0" 1763 | source = "registry+https://github.com/rust-lang/crates.io-index" 1764 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1765 | dependencies = [ 1766 | "tinyvec_macros", 1767 | ] 1768 | 1769 | [[package]] 1770 | name = "tinyvec_macros" 1771 | version = "0.1.1" 1772 | source = "registry+https://github.com/rust-lang/crates.io-index" 1773 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1774 | 1775 | [[package]] 1776 | name = "tokio" 1777 | version = "1.30.0" 1778 | source = "registry+https://github.com/rust-lang/crates.io-index" 1779 | checksum = "2d3ce25f50619af8b0aec2eb23deebe84249e19e2ddd393a6e16e3300a6dadfd" 1780 | dependencies = [ 1781 | "backtrace", 1782 | "bytes", 1783 | "libc", 1784 | "mio", 1785 | "num_cpus", 1786 | "parking_lot", 1787 | "pin-project-lite", 1788 | "signal-hook-registry", 1789 | "socket2 0.5.3", 1790 | "tokio-macros", 1791 | "windows-sys", 1792 | ] 1793 | 1794 | [[package]] 1795 | name = "tokio-macros" 1796 | version = "2.1.0" 1797 | source = "registry+https://github.com/rust-lang/crates.io-index" 1798 | checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" 1799 | dependencies = [ 1800 | "proc-macro2", 1801 | "quote", 1802 | "syn 2.0.28", 1803 | ] 1804 | 1805 | [[package]] 1806 | name = "tokio-postgres" 1807 | version = "0.7.9" 1808 | source = "registry+https://github.com/rust-lang/crates.io-index" 1809 | checksum = "000387915083ea6406ee44b50ca74813aba799fe682a7689e382bf9e13b74ce9" 1810 | dependencies = [ 1811 | "async-trait", 1812 | "byteorder", 1813 | "bytes", 1814 | "fallible-iterator", 1815 | "futures-channel", 1816 | "futures-util", 1817 | "log", 1818 | "parking_lot", 1819 | "percent-encoding", 1820 | "phf", 1821 | "pin-project-lite", 1822 | "postgres-protocol", 1823 | "postgres-types", 1824 | "rand", 1825 | "socket2 0.5.3", 1826 | "tokio", 1827 | "tokio-util", 1828 | "whoami", 1829 | ] 1830 | 1831 | [[package]] 1832 | name = "tokio-stream" 1833 | version = "0.1.14" 1834 | source = "registry+https://github.com/rust-lang/crates.io-index" 1835 | checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" 1836 | dependencies = [ 1837 | "futures-core", 1838 | "pin-project-lite", 1839 | "tokio", 1840 | ] 1841 | 1842 | [[package]] 1843 | name = "tokio-util" 1844 | version = "0.7.8" 1845 | source = "registry+https://github.com/rust-lang/crates.io-index" 1846 | checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" 1847 | dependencies = [ 1848 | "bytes", 1849 | "futures-core", 1850 | "futures-sink", 1851 | "pin-project-lite", 1852 | "tokio", 1853 | "tracing", 1854 | ] 1855 | 1856 | [[package]] 1857 | name = "touche" 1858 | version = "0.0.7" 1859 | source = "registry+https://github.com/rust-lang/crates.io-index" 1860 | checksum = "562b01d923116fc4d71a51fe393193b29f6ff5bb15fd4fdd7dc67fd35d090da1" 1861 | dependencies = [ 1862 | "headers", 1863 | "http", 1864 | "httparse", 1865 | "thiserror", 1866 | "threadpool", 1867 | ] 1868 | 1869 | [[package]] 1870 | name = "tower" 1871 | version = "0.4.13" 1872 | source = "registry+https://github.com/rust-lang/crates.io-index" 1873 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 1874 | dependencies = [ 1875 | "futures-core", 1876 | "futures-util", 1877 | "pin-project", 1878 | "pin-project-lite", 1879 | "tokio", 1880 | "tower-layer", 1881 | "tower-service", 1882 | "tracing", 1883 | ] 1884 | 1885 | [[package]] 1886 | name = "tower-layer" 1887 | version = "0.3.2" 1888 | source = "registry+https://github.com/rust-lang/crates.io-index" 1889 | checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" 1890 | 1891 | [[package]] 1892 | name = "tower-service" 1893 | version = "0.3.2" 1894 | source = "registry+https://github.com/rust-lang/crates.io-index" 1895 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1896 | 1897 | [[package]] 1898 | name = "tracing" 1899 | version = "0.1.37" 1900 | source = "registry+https://github.com/rust-lang/crates.io-index" 1901 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1902 | dependencies = [ 1903 | "cfg-if", 1904 | "log", 1905 | "pin-project-lite", 1906 | "tracing-attributes", 1907 | "tracing-core", 1908 | ] 1909 | 1910 | [[package]] 1911 | name = "tracing-attributes" 1912 | version = "0.1.26" 1913 | source = "registry+https://github.com/rust-lang/crates.io-index" 1914 | checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" 1915 | dependencies = [ 1916 | "proc-macro2", 1917 | "quote", 1918 | "syn 2.0.28", 1919 | ] 1920 | 1921 | [[package]] 1922 | name = "tracing-core" 1923 | version = "0.1.31" 1924 | source = "registry+https://github.com/rust-lang/crates.io-index" 1925 | checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" 1926 | dependencies = [ 1927 | "once_cell", 1928 | ] 1929 | 1930 | [[package]] 1931 | name = "try-lock" 1932 | version = "0.2.4" 1933 | source = "registry+https://github.com/rust-lang/crates.io-index" 1934 | checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 1935 | 1936 | [[package]] 1937 | name = "typenum" 1938 | version = "1.16.0" 1939 | source = "registry+https://github.com/rust-lang/crates.io-index" 1940 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1941 | 1942 | [[package]] 1943 | name = "unicode-bidi" 1944 | version = "0.3.13" 1945 | source = "registry+https://github.com/rust-lang/crates.io-index" 1946 | checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" 1947 | 1948 | [[package]] 1949 | name = "unicode-ident" 1950 | version = "1.0.11" 1951 | source = "registry+https://github.com/rust-lang/crates.io-index" 1952 | checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" 1953 | 1954 | [[package]] 1955 | name = "unicode-normalization" 1956 | version = "0.1.22" 1957 | source = "registry+https://github.com/rust-lang/crates.io-index" 1958 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1959 | dependencies = [ 1960 | "tinyvec", 1961 | ] 1962 | 1963 | [[package]] 1964 | name = "unicode-segmentation" 1965 | version = "1.10.1" 1966 | source = "registry+https://github.com/rust-lang/crates.io-index" 1967 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 1968 | 1969 | [[package]] 1970 | name = "unicode_categories" 1971 | version = "0.1.1" 1972 | source = "registry+https://github.com/rust-lang/crates.io-index" 1973 | checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" 1974 | 1975 | [[package]] 1976 | name = "url" 1977 | version = "2.4.0" 1978 | source = "registry+https://github.com/rust-lang/crates.io-index" 1979 | checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" 1980 | dependencies = [ 1981 | "form_urlencoded", 1982 | "idna", 1983 | "percent-encoding", 1984 | ] 1985 | 1986 | [[package]] 1987 | name = "uuid" 1988 | version = "1.4.1" 1989 | source = "registry+https://github.com/rust-lang/crates.io-index" 1990 | checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" 1991 | dependencies = [ 1992 | "atomic", 1993 | "getrandom", 1994 | "serde", 1995 | ] 1996 | 1997 | [[package]] 1998 | name = "vcpkg" 1999 | version = "0.2.15" 2000 | source = "registry+https://github.com/rust-lang/crates.io-index" 2001 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 2002 | 2003 | [[package]] 2004 | name = "version_check" 2005 | version = "0.9.4" 2006 | source = "registry+https://github.com/rust-lang/crates.io-index" 2007 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 2008 | 2009 | [[package]] 2010 | name = "want" 2011 | version = "0.3.1" 2012 | source = "registry+https://github.com/rust-lang/crates.io-index" 2013 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 2014 | dependencies = [ 2015 | "try-lock", 2016 | ] 2017 | 2018 | [[package]] 2019 | name = "wasi" 2020 | version = "0.11.0+wasi-snapshot-preview1" 2021 | source = "registry+https://github.com/rust-lang/crates.io-index" 2022 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 2023 | 2024 | [[package]] 2025 | name = "wasm-bindgen" 2026 | version = "0.2.87" 2027 | source = "registry+https://github.com/rust-lang/crates.io-index" 2028 | checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" 2029 | dependencies = [ 2030 | "cfg-if", 2031 | "wasm-bindgen-macro", 2032 | ] 2033 | 2034 | [[package]] 2035 | name = "wasm-bindgen-backend" 2036 | version = "0.2.87" 2037 | source = "registry+https://github.com/rust-lang/crates.io-index" 2038 | checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" 2039 | dependencies = [ 2040 | "bumpalo", 2041 | "log", 2042 | "once_cell", 2043 | "proc-macro2", 2044 | "quote", 2045 | "syn 2.0.28", 2046 | "wasm-bindgen-shared", 2047 | ] 2048 | 2049 | [[package]] 2050 | name = "wasm-bindgen-macro" 2051 | version = "0.2.87" 2052 | source = "registry+https://github.com/rust-lang/crates.io-index" 2053 | checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" 2054 | dependencies = [ 2055 | "quote", 2056 | "wasm-bindgen-macro-support", 2057 | ] 2058 | 2059 | [[package]] 2060 | name = "wasm-bindgen-macro-support" 2061 | version = "0.2.87" 2062 | source = "registry+https://github.com/rust-lang/crates.io-index" 2063 | checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" 2064 | dependencies = [ 2065 | "proc-macro2", 2066 | "quote", 2067 | "syn 2.0.28", 2068 | "wasm-bindgen-backend", 2069 | "wasm-bindgen-shared", 2070 | ] 2071 | 2072 | [[package]] 2073 | name = "wasm-bindgen-shared" 2074 | version = "0.2.87" 2075 | source = "registry+https://github.com/rust-lang/crates.io-index" 2076 | checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" 2077 | 2078 | [[package]] 2079 | name = "web-sys" 2080 | version = "0.3.64" 2081 | source = "registry+https://github.com/rust-lang/crates.io-index" 2082 | checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" 2083 | dependencies = [ 2084 | "js-sys", 2085 | "wasm-bindgen", 2086 | ] 2087 | 2088 | [[package]] 2089 | name = "whoami" 2090 | version = "1.4.1" 2091 | source = "registry+https://github.com/rust-lang/crates.io-index" 2092 | checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" 2093 | dependencies = [ 2094 | "wasm-bindgen", 2095 | "web-sys", 2096 | ] 2097 | 2098 | [[package]] 2099 | name = "winapi" 2100 | version = "0.3.9" 2101 | source = "registry+https://github.com/rust-lang/crates.io-index" 2102 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 2103 | dependencies = [ 2104 | "winapi-i686-pc-windows-gnu", 2105 | "winapi-x86_64-pc-windows-gnu", 2106 | ] 2107 | 2108 | [[package]] 2109 | name = "winapi-i686-pc-windows-gnu" 2110 | version = "0.4.0" 2111 | source = "registry+https://github.com/rust-lang/crates.io-index" 2112 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 2113 | 2114 | [[package]] 2115 | name = "winapi-x86_64-pc-windows-gnu" 2116 | version = "0.4.0" 2117 | source = "registry+https://github.com/rust-lang/crates.io-index" 2118 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 2119 | 2120 | [[package]] 2121 | name = "windows-sys" 2122 | version = "0.48.0" 2123 | source = "registry+https://github.com/rust-lang/crates.io-index" 2124 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 2125 | dependencies = [ 2126 | "windows-targets", 2127 | ] 2128 | 2129 | [[package]] 2130 | name = "windows-targets" 2131 | version = "0.48.1" 2132 | source = "registry+https://github.com/rust-lang/crates.io-index" 2133 | checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" 2134 | dependencies = [ 2135 | "windows_aarch64_gnullvm", 2136 | "windows_aarch64_msvc", 2137 | "windows_i686_gnu", 2138 | "windows_i686_msvc", 2139 | "windows_x86_64_gnu", 2140 | "windows_x86_64_gnullvm", 2141 | "windows_x86_64_msvc", 2142 | ] 2143 | 2144 | [[package]] 2145 | name = "windows_aarch64_gnullvm" 2146 | version = "0.48.0" 2147 | source = "registry+https://github.com/rust-lang/crates.io-index" 2148 | checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" 2149 | 2150 | [[package]] 2151 | name = "windows_aarch64_msvc" 2152 | version = "0.48.0" 2153 | source = "registry+https://github.com/rust-lang/crates.io-index" 2154 | checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" 2155 | 2156 | [[package]] 2157 | name = "windows_i686_gnu" 2158 | version = "0.48.0" 2159 | source = "registry+https://github.com/rust-lang/crates.io-index" 2160 | checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" 2161 | 2162 | [[package]] 2163 | name = "windows_i686_msvc" 2164 | version = "0.48.0" 2165 | source = "registry+https://github.com/rust-lang/crates.io-index" 2166 | checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" 2167 | 2168 | [[package]] 2169 | name = "windows_x86_64_gnu" 2170 | version = "0.48.0" 2171 | source = "registry+https://github.com/rust-lang/crates.io-index" 2172 | checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" 2173 | 2174 | [[package]] 2175 | name = "windows_x86_64_gnullvm" 2176 | version = "0.48.0" 2177 | source = "registry+https://github.com/rust-lang/crates.io-index" 2178 | checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" 2179 | 2180 | [[package]] 2181 | name = "windows_x86_64_msvc" 2182 | version = "0.48.0" 2183 | source = "registry+https://github.com/rust-lang/crates.io-index" 2184 | checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" 2185 | 2186 | [[package]] 2187 | name = "zeroize" 2188 | version = "1.6.0" 2189 | source = "registry+https://github.com/rust-lang/crates.io-index" 2190 | checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" 2191 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "./rinha-axum", 4 | "./rinha-core", 5 | "./rinha-touche", 6 | ] 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rinha Backend™ Rust 2 | 3 | Repositório de a implementação em [Rust da Rinha de Backend 2023](https://github.com/zanfranceschi/rinha-de-backend-2023-q3). 4 | 5 | ## Lives 6 | 7 | O código está sendo implementado em uma série de lives no Youtube: 8 | 9 | ### Parte 1 - Endpoints do Axum e "persistência" mais rápida do mundo 10 | 11 | [![Parte 01](.github/live01.png)](https://www.youtube.com/watch?v=aXQenZGvLrQ) 12 | https://www.youtube.com/watch?v=aXQenZGvLrQ 13 | 14 | ### Parte 2 - Persistência menos rápida com Postgres 15 | 16 | [![Parte 02](.github/live02.png)](https://www.youtube.com/watch?v=zkP6zA69Vd4) 17 | https://www.youtube.com/watch?v=zkP6zA69Vd4 18 | 19 | 20 | ### Parte 3 - Refatoração e introdução a macros 21 | 22 | [![Parte 03](.github/live03.png)](https://www.youtube.com/watch?v=5k52-nKoYfE) 23 | https://www.youtube.com/watch?v=5k52-nKoYfE 24 | -------------------------------------------------------------------------------- /db/v0001__create_people.sql: -------------------------------------------------------------------------------- 1 | CREATE EXTENSION pg_trgm; 2 | 3 | CREATE OR REPLACE FUNCTION ARRAY_TO_STRING_IMMUTABLE ( 4 | arr TEXT[], 5 | sep TEXT 6 | ) RETURNS TEXT IMMUTABLE PARALLEL SAFE LANGUAGE SQL AS $$ 7 | SELECT ARRAY_TO_STRING(arr, sep) $$; 8 | 9 | CREATE TABLE people ( 10 | id UUID PRIMARY KEY, 11 | name VARCHAR(100) NOT NULL, 12 | nick VARCHAR(32) NOT NULL, 13 | birth_date DATE NOT NULL, 14 | stack VARCHAR(32)[], 15 | search TEXT GENERATED ALWAYS AS ( 16 | name || ' ' || nick || ' ' || COALESCE(ARRAY_TO_STRING_IMMUTABLE(stack, ' '), '') 17 | ) STORED, 18 | CONSTRAINT unique_nick UNIQUE (nick) 19 | ); 20 | 21 | CREATE INDEX people_search_index ON people USING GIST (search gist_trgm_ops); 22 | 23 | CREATE OR REPLACE FUNCTION notify_person_created() RETURNS TRIGGER as $notify_person_created$ 24 | BEGIN 25 | IF (TG_OP = 'INSERT') THEN 26 | PERFORM PG_NOTIFY( 27 | 'person_created', 28 | JSON_BUILD_OBJECT( 29 | 'id', NEW.id, 30 | 'nome', NEW.name, 31 | 'apelido', NEW.nick, 32 | 'nascimento', NEW.birth_date, 33 | 'stack', ARRAY_TO_JSON(NEW.stack::VARCHAR(32)[]) 34 | )::TEXT 35 | ); 36 | END IF; 37 | RETURN NEW; 38 | END; 39 | $notify_person_created$ LANGUAGE plpgsql; 40 | 41 | CREATE TRIGGER notify_person_created AFTER INSERT ON people FOR EACH ROW EXECUTE PROCEDURE notify_person_created(); 42 | -------------------------------------------------------------------------------- /docker-compose-axum-local.yml: -------------------------------------------------------------------------------- 1 | version: "3.5" 2 | 3 | services: 4 | api1: 5 | build: 6 | context: . 7 | dockerfile: ./rinha-axum/Dockerfile 8 | hostname: api1 9 | environment: 10 | PORT: 80 11 | DATABASE_URL: postgres://rinha:rinha@db/rinha 12 | depends_on: 13 | - db 14 | expose: 15 | - "80" 16 | deploy: 17 | resources: 18 | limits: 19 | cpus: "0.25" 20 | memory: "0.5GB" 21 | 22 | api2: 23 | build: 24 | context: . 25 | dockerfile: ./rinha-axum/Dockerfile 26 | hostname: api2 27 | environment: 28 | PORT: 80 29 | DATABASE_URL: postgres://rinha:rinha@db/rinha 30 | depends_on: 31 | - db 32 | expose: 33 | - "80" 34 | deploy: 35 | resources: 36 | limits: 37 | cpus: "0.25" 38 | memory: "0.5GB" 39 | 40 | nginx: 41 | image: nginx:latest 42 | volumes: 43 | - ./nginx.conf:/etc/nginx/nginx.conf:ro 44 | depends_on: 45 | - api1 46 | - api2 47 | ports: 48 | - "9999:9999" 49 | deploy: 50 | resources: 51 | limits: 52 | cpus: "0.3" 53 | memory: "0.5GB" 54 | 55 | db: 56 | image: postgres:15 57 | volumes: 58 | - ./db:/docker-entrypoint-initdb.d 59 | command: postgres -c log_min_messages=FATAL 60 | environment: 61 | POSTGRES_USER: rinha 62 | POSTGRES_PASSWORD: rinha 63 | POSTGRES_DB: rinha 64 | ports: 65 | - "5432:5432" 66 | deploy: 67 | resources: 68 | limits: 69 | cpus: "0.7" 70 | memory: "1.5GB" 71 | -------------------------------------------------------------------------------- /docker-compose-axum-prod.yml: -------------------------------------------------------------------------------- 1 | version: "3.5" 2 | 3 | services: 4 | api1: 5 | image: rnavarro/rinha-backend-axum:1 6 | hostname: api1 7 | environment: 8 | PORT: 80 9 | DATABASE_URL: postgres://rinha:rinha@db/rinha 10 | depends_on: 11 | - db 12 | expose: 13 | - "80" 14 | deploy: 15 | resources: 16 | limits: 17 | cpus: "0.25" 18 | memory: "0.5GB" 19 | 20 | api2: 21 | image: rnavarro/rinha-backend-axum:1 22 | hostname: api2 23 | environment: 24 | PORT: 80 25 | DATABASE_URL: postgres://rinha:rinha@db/rinha 26 | depends_on: 27 | - db 28 | expose: 29 | - "80" 30 | deploy: 31 | resources: 32 | limits: 33 | cpus: "0.25" 34 | memory: "0.5GB" 35 | 36 | nginx: 37 | image: nginx:latest 38 | volumes: 39 | - ./nginx.conf:/etc/nginx/nginx.conf:ro 40 | depends_on: 41 | - api1 42 | - api2 43 | ports: 44 | - "9999:9999" 45 | deploy: 46 | resources: 47 | limits: 48 | cpus: "0.3" 49 | memory: "0.5GB" 50 | 51 | db: 52 | image: postgres:15 53 | volumes: 54 | - ./db:/docker-entrypoint-initdb.d 55 | command: postgres -c log_min_messages=FATAL 56 | environment: 57 | POSTGRES_USER: rinha 58 | POSTGRES_PASSWORD: rinha 59 | POSTGRES_DB: rinha 60 | deploy: 61 | resources: 62 | limits: 63 | cpus: "0.7" 64 | memory: "1.5GB" 65 | -------------------------------------------------------------------------------- /docker-compose-dev.yml: -------------------------------------------------------------------------------- 1 | version: "3.5" 2 | 3 | services: 4 | postgres: 5 | container_name: rinha_backend_postgres 6 | image: postgres:15 7 | volumes: 8 | - ./db:/docker-entrypoint-initdb.d 9 | environment: 10 | POSTGRES_USER: rinha 11 | POSTGRES_PASSWORD: rinha 12 | POSTGRES_DB: rinha 13 | ports: 14 | - "5432:5432" 15 | deploy: 16 | resources: 17 | limits: 18 | cpus: "0.7" 19 | memory: "1.5GB" 20 | -------------------------------------------------------------------------------- /docker-compose-touche-local.yml: -------------------------------------------------------------------------------- 1 | version: "3.5" 2 | 3 | services: 4 | api1: 5 | build: 6 | context: . 7 | dockerfile: ./rinha-touche/Dockerfile 8 | hostname: api1 9 | environment: 10 | PORT: 80 11 | DATABASE_URL: postgres://rinha:rinha@db/rinha 12 | DATABASE_POOL: 50 13 | MAX_THREADS: 600 14 | depends_on: 15 | - db 16 | expose: 17 | - "80" 18 | deploy: 19 | resources: 20 | limits: 21 | cpus: "0.25" 22 | memory: "0.5GB" 23 | 24 | api2: 25 | build: 26 | context: . 27 | dockerfile: ./rinha-touche/Dockerfile 28 | hostname: api2 29 | environment: 30 | PORT: 80 31 | DATABASE_URL: postgres://rinha:rinha@db/rinha 32 | DATABASE_POOL: 50 33 | MAX_THREADS: 600 34 | depends_on: 35 | - db 36 | expose: 37 | - "80" 38 | deploy: 39 | resources: 40 | limits: 41 | cpus: "0.25" 42 | memory: "0.5GB" 43 | 44 | nginx: 45 | image: nginx:latest 46 | volumes: 47 | - ./nginx.conf:/etc/nginx/nginx.conf:ro 48 | depends_on: 49 | - api1 50 | - api2 51 | ports: 52 | - "9999:9999" 53 | deploy: 54 | resources: 55 | limits: 56 | cpus: "0.3" 57 | memory: "0.5GB" 58 | ulimits: 59 | nproc: 65535 60 | nofile: 61 | soft: 40000 62 | hard: 40000 63 | 64 | db: 65 | image: postgres:15 66 | volumes: 67 | - ./db:/docker-entrypoint-initdb.d 68 | command: postgres -c log_min_messages=FATAL -c max_connections=110 69 | environment: 70 | POSTGRES_USER: rinha 71 | POSTGRES_PASSWORD: rinha 72 | POSTGRES_DB: rinha 73 | ports: 74 | - "5432:5432" 75 | deploy: 76 | resources: 77 | limits: 78 | cpus: "0.7" 79 | memory: "1.5GB" 80 | -------------------------------------------------------------------------------- /docker-compose-touche-prod.yml: -------------------------------------------------------------------------------- 1 | version: "3.5" 2 | 3 | services: 4 | api1: 5 | image: rnavarro/rinha-backend-touche:1 6 | hostname: api1 7 | environment: 8 | PORT: 80 9 | DATABASE_URL: postgres://rinha:rinha@db/rinha 10 | DATABASE_POOL: 50 11 | MAX_THREADS: 600 12 | depends_on: 13 | - db 14 | expose: 15 | - "80" 16 | deploy: 17 | resources: 18 | limits: 19 | cpus: "0.25" 20 | memory: "0.5GB" 21 | 22 | api2: 23 | image: rnavarro/rinha-backend-touche:1 24 | hostname: api2 25 | environment: 26 | PORT: 80 27 | DATABASE_URL: postgres://rinha:rinha@db/rinha 28 | DATABASE_POOL: 50 29 | MAX_THREADS: 600 30 | depends_on: 31 | - db 32 | expose: 33 | - "80" 34 | deploy: 35 | resources: 36 | limits: 37 | cpus: "0.25" 38 | memory: "0.5GB" 39 | 40 | nginx: 41 | image: nginx:latest 42 | volumes: 43 | - ./nginx.conf:/etc/nginx/nginx.conf:ro 44 | depends_on: 45 | - api1 46 | - api2 47 | ports: 48 | - "9999:9999" 49 | deploy: 50 | resources: 51 | limits: 52 | cpus: "0.3" 53 | memory: "0.5GB" 54 | 55 | db: 56 | image: postgres:15 57 | volumes: 58 | - ./db:/docker-entrypoint-initdb.d 59 | command: postgres -c log_min_messages=FATAL -c max_connections=110 60 | environment: 61 | POSTGRES_USER: rinha 62 | POSTGRES_PASSWORD: rinha 63 | POSTGRES_DB: rinha 64 | deploy: 65 | resources: 66 | limits: 67 | cpus: "0.7" 68 | memory: "1.5GB" 69 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | events { 2 | worker_connections 30000; 3 | multi_accept on; 4 | } 5 | 6 | error_log /dev/null emerg; 7 | 8 | http { 9 | access_log off; 10 | 11 | upstream api { 12 | server api1:80; 13 | server api2:80; 14 | } 15 | 16 | server { 17 | listen 9999 default_server; 18 | 19 | location / { 20 | proxy_pass http://api; 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /rinha-axum/.sqlx/query-5734c5bec575d6962bf295754ea21ae83f96758ba99faf90d4d1bdc55ce91b55.json: -------------------------------------------------------------------------------- 1 | { 2 | "db_name": "PostgreSQL", 3 | "query": "SELECT COUNT(*) AS count FROM people", 4 | "describe": { 5 | "columns": [ 6 | { 7 | "ordinal": 0, 8 | "name": "count", 9 | "type_info": "Int8" 10 | } 11 | ], 12 | "parameters": { 13 | "Left": [] 14 | }, 15 | "nullable": [ 16 | null 17 | ] 18 | }, 19 | "hash": "5734c5bec575d6962bf295754ea21ae83f96758ba99faf90d4d1bdc55ce91b55" 20 | } 21 | -------------------------------------------------------------------------------- /rinha-axum/.sqlx/query-be7a47438fe43899e0a8cda76075c532153d4657d5fa0b044acecf55a2320f70.json: -------------------------------------------------------------------------------- 1 | { 2 | "db_name": "PostgreSQL", 3 | "query": "\n INSERT INTO people (id, name, nick, birth_date, stack)\n VALUES ($1, $2, $3, $4, $5)\n RETURNING id\n ", 4 | "describe": { 5 | "columns": [ 6 | { 7 | "ordinal": 0, 8 | "name": "id", 9 | "type_info": "Uuid" 10 | } 11 | ], 12 | "parameters": { 13 | "Left": [ 14 | "Uuid", 15 | "Varchar", 16 | "Varchar", 17 | "Date", 18 | "VarcharArray" 19 | ] 20 | }, 21 | "nullable": [ 22 | false 23 | ] 24 | }, 25 | "hash": "be7a47438fe43899e0a8cda76075c532153d4657d5fa0b044acecf55a2320f70" 26 | } 27 | -------------------------------------------------------------------------------- /rinha-axum/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rinha-axum" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [profile.release] 7 | codegen-units = 1 8 | lto = true 9 | panic = "abort" 10 | 11 | [dependencies] 12 | axum = "0.6.20" 13 | dashmap = "5.5.0" 14 | rinha-core = { path = "../rinha-core", features = ["sqlx"] } 15 | serde = { version = "1.0.183", features = ["derive"] } 16 | serde_json = "1.0.104" 17 | sqlx = { version = "0.7.1", features = ["postgres", "runtime-tokio", "time", "uuid", "macros"] } 18 | time = { version = "0.3.25", features = ["macros", "serde", "formatting", "parsing"] } 19 | tokio = { version = "1.30.0", features = ["full"] } 20 | uuid = { version = "1.4.1", features = ["v7", "serde"] } 21 | -------------------------------------------------------------------------------- /rinha-axum/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1-slim-buster AS build 2 | 3 | RUN cargo new --bin app 4 | WORKDIR /app 5 | RUN cargo new --lib rinha-core 6 | RUN cargo new --bin rinha-axum 7 | RUN cargo new --lib rinha-touche 8 | RUN mv /app/src/main.rs /app/rinha-axum/src/main.rs 9 | 10 | COPY Cargo.toml /app/ 11 | COPY Cargo.lock /app/ 12 | COPY .cargo /app/.cargo 13 | COPY rinha-core/Cargo.toml /app/rinha-core/ 14 | COPY rinha-touche/Cargo.toml /app/rinha-touche/ 15 | COPY rinha-axum/Cargo.toml /app/rinha-axum/ 16 | RUN cargo build --release -p rinha-axum 17 | 18 | COPY rinha-core/src /app/rinha-core/src 19 | COPY rinha-axum/src /app/rinha-axum/src 20 | COPY rinha-axum/.sqlx /app/rinha-axum/.sqlx 21 | RUN touch /app/rinha-core/src/lib.rs 22 | RUN touch /app/rinha-axum/src/main.rs 23 | RUN cargo build --release -p rinha-axum 24 | 25 | FROM debian:buster-slim 26 | 27 | COPY --from=build /app/target/release/rinha-axum /app/rinha 28 | 29 | CMD "/app/rinha" 30 | -------------------------------------------------------------------------------- /rinha-axum/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{env, net::SocketAddr, sync::Arc}; 2 | 3 | use axum::{ 4 | extract::{Path, Query, State}, 5 | http::{header, StatusCode}, 6 | response::IntoResponse, 7 | routing::{get, post}, 8 | Json, Router, 9 | }; 10 | use rinha_core::NewPerson; 11 | use serde::Deserialize; 12 | use uuid::Uuid; 13 | 14 | use crate::persistence::{PersistenceError, PostgresRepository}; 15 | 16 | mod persistence; 17 | 18 | type AppState = Arc; 19 | 20 | #[tokio::main] 21 | async fn main() { 22 | let port = env::var("PORT") 23 | .ok() 24 | .and_then(|port| port.parse::().ok()) 25 | .unwrap_or(9999); 26 | 27 | let database_url = env::var("DATABASE_URL") 28 | .unwrap_or(String::from("postgres://rinha:rinha@localhost:5432/rinha")); 29 | 30 | let database_pool_size = env::var("DATABASE_POOL") 31 | .ok() 32 | .and_then(|port| port.parse::().ok()) 33 | .unwrap_or(30); 34 | 35 | let repo = PostgresRepository::connect(&database_url, database_pool_size) 36 | .await 37 | .unwrap(); 38 | 39 | let app_state = Arc::new(repo); 40 | 41 | let app = Router::new() 42 | .route("/pessoas", get(search_people)) 43 | .route("/pessoas/:id", get(find_person)) 44 | .route("/pessoas", post(create_person)) 45 | .route("/contagem-pessoas", get(count_people)) 46 | .with_state(app_state); 47 | 48 | axum::Server::bind(&SocketAddr::from(([0, 0, 0, 0], port))) 49 | .serve(app.into_make_service()) 50 | .await 51 | .unwrap(); 52 | } 53 | 54 | #[derive(Deserialize)] 55 | struct PersonSearchQuery { 56 | #[serde(rename = "t")] 57 | query: String, 58 | } 59 | async fn search_people( 60 | State(people): State, 61 | Query(PersonSearchQuery { query }): Query, 62 | ) -> impl IntoResponse { 63 | match people.search_people(&query).await { 64 | Ok(people) => Ok(Json(people)), 65 | Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), 66 | } 67 | } 68 | 69 | async fn find_person( 70 | State(people): State, 71 | Path(person_id): Path, 72 | ) -> impl IntoResponse { 73 | match people.find_person(person_id).await { 74 | Ok(Some(person)) => Ok(Json(person)), 75 | Ok(None) => Err(StatusCode::NOT_FOUND), 76 | Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), 77 | } 78 | } 79 | 80 | async fn create_person( 81 | State(people): State, 82 | Json(new_person): Json, 83 | ) -> impl IntoResponse { 84 | match people.create_person(new_person).await { 85 | Ok(id) => Ok(( 86 | StatusCode::CREATED, 87 | [(header::LOCATION, format!("/pessoas/{}", id))], 88 | )), 89 | Err(PersistenceError::UniqueViolation) => Err(StatusCode::UNPROCESSABLE_ENTITY), 90 | Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), 91 | } 92 | } 93 | 94 | async fn count_people(State(people): State) -> impl IntoResponse { 95 | match people.count_people().await { 96 | Ok(count) => Ok(Json(count)), 97 | Err(_) => Err(StatusCode::INTERNAL_SERVER_ERROR), 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /rinha-axum/src/persistence.rs: -------------------------------------------------------------------------------- 1 | use std::{error::Error, sync::Arc}; 2 | 3 | use dashmap::{DashMap, DashSet}; 4 | use rinha_core::{NewPerson, Person}; 5 | use sqlx::{ 6 | postgres::{PgListener, PgPoolOptions}, 7 | PgPool, 8 | }; 9 | use uuid::Uuid; 10 | 11 | pub enum PersistenceError { 12 | UniqueViolation, 13 | DatabaseError(Box), 14 | } 15 | 16 | impl From for PersistenceError { 17 | fn from(error: sqlx::Error) -> Self { 18 | match error { 19 | sqlx::Error::Database(err) if err.is_unique_violation() => { 20 | PersistenceError::UniqueViolation 21 | } 22 | _ => PersistenceError::DatabaseError(Box::new(error)), 23 | } 24 | } 25 | } 26 | 27 | type PersistenceResult = Result; 28 | 29 | pub struct PostgresRepository { 30 | pool: PgPool, 31 | cache: Arc>, 32 | nicks: Arc>, 33 | } 34 | 35 | impl PostgresRepository { 36 | pub async fn connect(url: &str, pool_size: u32) -> Result { 37 | let pool = PgPoolOptions::new() 38 | .max_connections(pool_size) 39 | .connect(url) 40 | .await?; 41 | 42 | let cache = Arc::new(DashMap::with_capacity(30_000)); 43 | let nicks = Arc::new(DashSet::new()); 44 | 45 | tokio::spawn({ 46 | let pool = pool.clone(); 47 | let cache = cache.clone(); 48 | let nicks = nicks.clone(); 49 | async move { 50 | if let Ok(mut listener) = PgListener::connect_with(&pool).await { 51 | listener.listen("person_created").await.ok(); 52 | while let Ok(msg) = listener.recv().await { 53 | if let Ok(person) = serde_json::from_str::(msg.payload()) { 54 | nicks.insert(person.nick.as_str().to_owned()); 55 | cache.insert(person.id, person); 56 | } 57 | } 58 | } 59 | } 60 | }); 61 | 62 | Ok(PostgresRepository { pool, cache, nicks }) 63 | } 64 | 65 | pub async fn find_person(&self, id: Uuid) -> PersistenceResult> { 66 | if let Some(person) = self.cache.get(&id).map(|entry| entry.value().clone()) { 67 | return Ok(Some(person)); 68 | } 69 | 70 | sqlx::query_as( 71 | " 72 | SELECT id, name, nick, birth_date, stack 73 | FROM people 74 | WHERE id = $1 75 | ", 76 | ) 77 | .bind(id) 78 | .fetch_optional(&self.pool) 79 | .await 80 | .map_err(PersistenceError::from) 81 | } 82 | 83 | pub async fn create_person(&self, new_person: NewPerson) -> PersistenceResult { 84 | if self.nicks.contains(new_person.nick.as_str()) { 85 | return Err(PersistenceError::UniqueViolation); 86 | } 87 | 88 | let stack = new_person 89 | .stack 90 | .map(|stack| stack.into_iter().map(String::from).collect::>()); 91 | 92 | sqlx::query!( 93 | " 94 | INSERT INTO people (id, name, nick, birth_date, stack) 95 | VALUES ($1, $2, $3, $4, $5) 96 | RETURNING id 97 | ", 98 | Uuid::now_v7(), 99 | new_person.name.as_str(), 100 | new_person.nick.as_str(), 101 | new_person.birth_date, 102 | stack.as_ref().map(|stack| stack.as_slice()), 103 | ) 104 | .fetch_one(&self.pool) 105 | .await 106 | .map(|row| row.id) 107 | .map_err(PersistenceError::from) 108 | } 109 | 110 | pub async fn search_people(&self, query: &str) -> PersistenceResult> { 111 | sqlx::query_as( 112 | " 113 | SELECT id, name, nick, birth_date, stack 114 | FROM people 115 | WHERE search ILIKE $1 116 | LIMIT 50 117 | ", 118 | ) 119 | .bind(format!("%{query}%")) 120 | .fetch_all(&self.pool) 121 | .await 122 | .map_err(PersistenceError::from) 123 | } 124 | 125 | pub async fn count_people(&self) -> PersistenceResult { 126 | sqlx::query!("SELECT COUNT(*) AS count FROM people") 127 | .fetch_one(&self.pool) 128 | .await 129 | .map(|row| row.count.unwrap_or_default()) 130 | .map(|count| count.unsigned_abs()) 131 | .map_err(PersistenceError::from) 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /rinha-core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rinha-core" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [features] 7 | default = [] 8 | slqx = ["sqlx"] 9 | 10 | [dependencies] 11 | serde = { version = "1.0.183", features = ["derive"] } 12 | sqlx = { version = "0.7.1", optional = true, features = ["postgres", "runtime-tokio", "time", "uuid", "macros"] } 13 | time = { version = "0.3.25", features = ["macros", "serde", "formatting", "parsing"] } 14 | uuid = { version = "1.4.1", features = ["v7", "serde"] } 15 | -------------------------------------------------------------------------------- /rinha-core/src/lib.rs: -------------------------------------------------------------------------------- 1 | use serde::{Deserialize, Serialize}; 2 | use time::Date; 3 | use uuid::Uuid; 4 | 5 | #[derive(Clone, Serialize, Deserialize)] 6 | #[cfg_attr(feature = "sqlx", derive(sqlx::FromRow))] 7 | pub struct Person { 8 | pub id: Uuid, 9 | #[serde(rename = "nome")] 10 | pub name: PersonName, 11 | #[serde(rename = "apelido")] 12 | pub nick: Nick, 13 | #[serde(rename = "nascimento", with = "date_format")] 14 | pub birth_date: Date, 15 | pub stack: Option>, 16 | } 17 | 18 | #[derive(Clone, Deserialize)] 19 | pub struct NewPerson { 20 | #[serde(rename = "nome")] 21 | pub name: PersonName, 22 | #[serde(rename = "apelido")] 23 | pub nick: Nick, 24 | #[serde(rename = "nascimento", with = "date_format")] 25 | pub birth_date: Date, 26 | pub stack: Option>, 27 | } 28 | 29 | macro_rules! new_string_type { 30 | ($type:ident, max_length = $max_length:expr, error = $error_message:expr) => { 31 | #[derive(Clone, Serialize, Deserialize)] 32 | #[serde(try_from = "String")] 33 | #[cfg_attr(feature = "sqlx", derive(sqlx::Type))] 34 | #[cfg_attr(feature = "sqlx", sqlx(transparent))] 35 | pub struct $type(String); 36 | 37 | impl $type { 38 | pub fn as_str(&self) -> &str { 39 | &self.0 40 | } 41 | } 42 | 43 | impl TryFrom for $type { 44 | type Error = &'static str; 45 | 46 | fn try_from(value: String) -> Result { 47 | if value.len() <= $max_length { 48 | Ok($type(value)) 49 | } else { 50 | Err($error_message) 51 | } 52 | } 53 | } 54 | 55 | impl From<$type> for String { 56 | fn from(value: $type) -> Self { 57 | value.0 58 | } 59 | } 60 | }; 61 | } 62 | 63 | new_string_type!(PersonName, max_length = 100, error = "name is too big"); 64 | new_string_type!(Nick, max_length = 32, error = "nick is too big"); 65 | new_string_type!(Tech, max_length = 32, error = "tech is too big"); 66 | 67 | time::serde::format_description!(date_format, Date, "[year]-[month]-[day]"); 68 | -------------------------------------------------------------------------------- /rinha-touche/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rinha-touche" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [profile.release] 7 | codegen-units = 1 8 | lto = true 9 | panic = "abort" 10 | 11 | [dependencies] 12 | dashmap = "5.5.0" 13 | postgres = { version = "0.19.5", features = ["array-impls", "with-time-0_3", "with-uuid-1"] } 14 | r2d2 = "0.8.10" 15 | r2d2_postgres = "0.18.1" 16 | rinha-core = { path = "../rinha-core" } 17 | serde = { version = "1.0.183", features = ["derive"] } 18 | serde_json = "1.0.104" 19 | serde_urlencoded = "0.7.1" 20 | time = { version = "0.3.25", features = ["macros", "serde", "formatting", "parsing"] } 21 | touche = "0.0.7" 22 | uuid = { version = "1.4.1", features = ["v7", "serde"] } 23 | -------------------------------------------------------------------------------- /rinha-touche/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:1-slim-buster AS build 2 | 3 | RUN cargo new --bin app 4 | WORKDIR /app 5 | RUN cargo new --lib rinha-core 6 | RUN cargo new --bin rinha-axum 7 | RUN cargo new --bin rinha-touche 8 | RUN mv /app/src/main.rs /app/rinha-touche/src/main.rs 9 | 10 | COPY Cargo.toml /app/ 11 | COPY Cargo.lock /app/ 12 | COPY .cargo /app/.cargo 13 | COPY rinha-core/Cargo.toml /app/rinha-core/ 14 | COPY rinha-axum/Cargo.toml /app/rinha-axum/ 15 | COPY rinha-touche/Cargo.toml /app/rinha-touche/ 16 | RUN cargo build --release -p rinha-touche 17 | 18 | COPY rinha-core/src /app/rinha-core/src 19 | COPY rinha-touche/src /app/rinha-touche/src 20 | RUN touch /app/rinha-core/src/lib.rs 21 | RUN touch /app/rinha-touche/src/main.rs 22 | RUN cargo build --release -p rinha-touche 23 | 24 | FROM debian:buster-slim 25 | 26 | COPY --from=build /app/target/release/rinha-touche /app/rinha 27 | 28 | CMD "/app/rinha" 29 | -------------------------------------------------------------------------------- /rinha-touche/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::{env, io, net::SocketAddr, sync::Arc}; 2 | 3 | use persistence::PersistenceError; 4 | use rinha_core::NewPerson; 5 | use serde::Deserialize; 6 | use touche::{Body, HttpBody, Method, Request, Response, Server, StatusCode}; 7 | use uuid::Uuid; 8 | 9 | use crate::persistence::PostgresRepository; 10 | 11 | mod persistence; 12 | 13 | #[derive(Deserialize)] 14 | struct PersonSearchQuery { 15 | #[serde(rename = "t")] 16 | query: String, 17 | } 18 | 19 | fn main() -> io::Result<()> { 20 | let port = env::var("PORT") 21 | .ok() 22 | .and_then(|port| port.parse::().ok()) 23 | .unwrap_or(9999); 24 | 25 | let database_url = env::var("DATABASE_URL") 26 | .unwrap_or(String::from("postgres://rinha:rinha@localhost:5432/rinha")); 27 | 28 | let database_pool_size = env::var("DATABASE_POOL") 29 | .ok() 30 | .and_then(|port| port.parse::().ok()) 31 | .unwrap_or(50); 32 | 33 | let max_threads = env::var("MAX_THREADS") 34 | .ok() 35 | .and_then(|port| port.parse::().ok()) 36 | .unwrap_or(400); 37 | 38 | let repo = PostgresRepository::connect(&database_url, database_pool_size).unwrap(); 39 | let repo = Arc::new(repo); 40 | 41 | Server::builder() 42 | .max_threads(max_threads) 43 | .bind(SocketAddr::from(([0, 0, 0, 0], port))) 44 | .serve(move |req: Request| { 45 | let repo = repo.clone(); 46 | let segments = req.uri().path().split('/').skip(1).collect::>(); 47 | 48 | match (req.method(), segments.as_slice()) { 49 | (&Method::GET, ["pessoas"]) => { 50 | let query = req.uri().query().unwrap_or_default(); 51 | match serde_urlencoded::from_str::(query) { 52 | Ok(PersonSearchQuery { query }) => match repo.search_people(&query) { 53 | Ok(people) => { 54 | let people = serde_json::to_vec(&people).unwrap(); 55 | Response::builder() 56 | .status(StatusCode::OK) 57 | .header("content-type", "application/json") 58 | .body(Body::from(people)) 59 | } 60 | Err(_) => Response::builder() 61 | .status(StatusCode::UNPROCESSABLE_ENTITY) 62 | .body(Body::empty()), 63 | }, 64 | Err(_) => Response::builder() 65 | .status(StatusCode::BAD_REQUEST) 66 | .body(Body::empty()), 67 | } 68 | } 69 | 70 | (&Method::POST, ["pessoas"]) => { 71 | let body = req.into_body(); 72 | match serde_json::from_reader::<_, NewPerson>(body.into_reader()) { 73 | Ok(person) => match repo.create_person(person) { 74 | Ok(id) => Response::builder() 75 | .status(StatusCode::CREATED) 76 | .header("location", format!("/pessoas/{id}")) 77 | .body(Body::empty()), 78 | Err(PersistenceError::UniqueViolation) => Response::builder() 79 | .status(StatusCode::UNPROCESSABLE_ENTITY) 80 | .body(Body::empty()), 81 | Err(_) => Response::builder() 82 | .status(StatusCode::INTERNAL_SERVER_ERROR) 83 | .body(Body::empty()), 84 | }, 85 | Err(_) => Response::builder() 86 | .status(StatusCode::UNPROCESSABLE_ENTITY) 87 | .body(Body::empty()), 88 | } 89 | } 90 | 91 | (&Method::GET, ["pessoas", id]) => match Uuid::parse_str(id) { 92 | Ok(id) => match repo.find_person(id) { 93 | Ok(Some(person)) => { 94 | let person = serde_json::to_vec(&person).unwrap(); 95 | Response::builder() 96 | .status(StatusCode::OK) 97 | .header("content-type", "application/json") 98 | .body(Body::from(person)) 99 | } 100 | Ok(None) => Response::builder() 101 | .status(StatusCode::NOT_FOUND) 102 | .body(Body::empty()), 103 | Err(_) => Response::builder() 104 | .status(StatusCode::INTERNAL_SERVER_ERROR) 105 | .body(Body::empty()), 106 | }, 107 | Err(_) => Response::builder() 108 | .status(StatusCode::NOT_FOUND) 109 | .body(Body::empty()), 110 | }, 111 | 112 | (&Method::GET, ["contagem-pessoas"]) => match repo.count_people() { 113 | Ok(count) => Response::builder() 114 | .status(StatusCode::OK) 115 | .body(Body::from(count.to_string())), 116 | Err(_) => Response::builder() 117 | .status(StatusCode::INTERNAL_SERVER_ERROR) 118 | .body(Body::empty()), 119 | }, 120 | 121 | _ => Response::builder() 122 | .status(StatusCode::NOT_FOUND) 123 | .body(Body::empty()), 124 | } 125 | }) 126 | } 127 | -------------------------------------------------------------------------------- /rinha-touche/src/persistence.rs: -------------------------------------------------------------------------------- 1 | use std::{error::Error, fmt::Display, str::FromStr, sync::Arc, thread}; 2 | 3 | use dashmap::{DashMap, DashSet}; 4 | use postgres::{ 5 | error::SqlState, fallible_iterator::FallibleIterator, Config as PgConfig, Error as PgError, 6 | NoTls, Row, 7 | }; 8 | use r2d2::{Error as PoolError, Pool}; 9 | use r2d2_postgres::PostgresConnectionManager; 10 | use rinha_core::{NewPerson, Nick, Person, PersonName}; 11 | use time::Date; 12 | use uuid::Uuid; 13 | 14 | struct PersistedPerson { 15 | id: Uuid, 16 | name: PersonName, 17 | nick: Nick, 18 | birth_date: Date, 19 | stack: Option>, 20 | } 21 | 22 | impl TryFrom for PersistedPerson { 23 | type Error = Box; 24 | 25 | fn try_from(value: Row) -> Result { 26 | Ok(Self { 27 | id: value.try_get("id")?, 28 | name: value.try_get::<_, String>("name")?.try_into()?, 29 | nick: value.try_get::<_, String>("nick")?.try_into()?, 30 | birth_date: value.try_get("birth_date")?, 31 | stack: value.try_get("stack")?, 32 | }) 33 | } 34 | } 35 | 36 | impl From for Person { 37 | fn from(person: PersistedPerson) -> Self { 38 | Self { 39 | id: person.id, 40 | name: person.name, 41 | nick: person.nick, 42 | birth_date: person.birth_date, 43 | stack: person.stack, 44 | } 45 | } 46 | } 47 | 48 | pub type PersistenceResult = Result; 49 | 50 | #[derive(Debug)] 51 | pub enum PersistenceError { 52 | UniqueViolation, 53 | DatabaseError(Box), 54 | } 55 | 56 | impl Display for PersistenceError { 57 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 58 | match self { 59 | Self::UniqueViolation => write!(f, "unique constraint violated"), 60 | Self::DatabaseError(err) => write!(f, "{}", err), 61 | } 62 | } 63 | } 64 | 65 | impl From for PersistenceError { 66 | fn from(value: PgError) -> Self { 67 | match value.code() { 68 | Some(&SqlState::UNIQUE_VIOLATION) => PersistenceError::UniqueViolation, 69 | _ => PersistenceError::DatabaseError(Box::new(value)), 70 | } 71 | } 72 | } 73 | 74 | impl From for PersistenceError { 75 | fn from(value: PoolError) -> Self { 76 | PersistenceError::DatabaseError(Box::new(value)) 77 | } 78 | } 79 | 80 | pub struct PostgresRepository { 81 | pool: Pool>, 82 | cache: Arc>, 83 | nicks: Arc>, 84 | } 85 | 86 | impl PostgresRepository { 87 | pub fn connect(url: &str, pool_size: usize) -> Result> { 88 | let pool = r2d2::Pool::builder() 89 | .max_size(pool_size.try_into()?) 90 | .build(PostgresConnectionManager::new( 91 | PgConfig::from_str(url).unwrap(), 92 | NoTls, 93 | )) 94 | .unwrap(); 95 | 96 | let cache = Arc::new(DashMap::new()); 97 | let nicks = Arc::new(DashSet::new()); 98 | 99 | thread::spawn({ 100 | let mut conn = pool.get()?; 101 | let cache = cache.clone(); 102 | let nicks = nicks.clone(); 103 | move || { 104 | conn.execute("LISTEN person_created", &[])?; 105 | let mut notifications = conn.notifications(); 106 | notifications.blocking_iter().for_each(|msg| { 107 | if let Ok(person) = serde_json::from_str::(msg.payload()) { 108 | nicks.insert(person.nick.as_str().to_owned()); 109 | cache.insert(person.id, person); 110 | } 111 | Ok(()) 112 | })?; 113 | Ok::<_, Box>(()) 114 | } 115 | }); 116 | 117 | Ok(Self { pool, cache, nicks }) 118 | } 119 | 120 | pub fn create_person(&self, person: NewPerson) -> PersistenceResult { 121 | if self.nicks.contains(person.nick.as_str()) { 122 | return Err(PersistenceError::UniqueViolation); 123 | } 124 | 125 | let mut conn = self.pool.get()?; 126 | 127 | let stmt = conn.prepare( 128 | " 129 | INSERT INTO 130 | people (id, name, nick, birth_date, stack) 131 | VALUES ($1, $2, $3, $4, $5) 132 | RETURNING id 133 | ", 134 | )?; 135 | 136 | let result = conn.query_one( 137 | &stmt, 138 | &[ 139 | &Uuid::now_v7(), 140 | &String::from(person.name), 141 | &String::from(person.nick), 142 | &person.birth_date, 143 | &person 144 | .stack 145 | .map(|stack| stack.into_iter().map(String::from).collect::>()), 146 | ], 147 | )?; 148 | 149 | Ok(result.try_get(0)?) 150 | } 151 | 152 | pub fn find_person(&self, id: Uuid) -> PersistenceResult> { 153 | if let Some(person) = self.cache.get(&id).map(|entry| entry.value().clone()) { 154 | return Ok(Some(person)); 155 | } 156 | 157 | let mut conn = self.pool.get()?; 158 | 159 | let stmt = conn.prepare( 160 | " 161 | SELECT id, name, nick, birth_date, stack 162 | FROM people 163 | WHERE id = $1 164 | ", 165 | )?; 166 | 167 | match conn.query_opt(&stmt, &[&id])? { 168 | Some(row) => Ok(Some( 169 | PersistedPerson::try_from(row) 170 | .map(Person::from) 171 | .map_err(PersistenceError::DatabaseError)?, 172 | )), 173 | None => Ok(None), 174 | } 175 | } 176 | 177 | pub fn search_people(&self, query: &str) -> PersistenceResult> { 178 | let mut conn = self.pool.get()?; 179 | 180 | let stmt = conn.prepare( 181 | " 182 | SELECT id, name, nick, birth_date, stack 183 | FROM people 184 | WHERE search ILIKE $1 185 | LIMIT 50 186 | ", 187 | )?; 188 | 189 | conn.query(&stmt, &[&format!("%{query}%")])? 190 | .into_iter() 191 | .map(|person| { 192 | PersistedPerson::try_from(person) 193 | .map(Person::from) 194 | .map_err(PersistenceError::DatabaseError) 195 | }) 196 | .collect() 197 | } 198 | 199 | pub fn count_people(&self) -> PersistenceResult { 200 | let mut conn = self.pool.get()?; 201 | let stmt = conn.prepare("SELECT COUNT(*) FROM people")?; 202 | let row = conn.query_one(&stmt, &[])?; 203 | let count: i64 = row.try_get(0)?; 204 | Ok(count.unsigned_abs()) 205 | } 206 | } 207 | --------------------------------------------------------------------------------