├── .env.template ├── .gitignore ├── .gitlab-ci.yml ├── .idea ├── misc.xml ├── modules.xml └── vcs.xml ├── Cargo.lock ├── Cargo.toml ├── README.md ├── build.rs ├── geofancy-rust.iml ├── proto └── geofancy.proto └── src ├── geofancy.rs ├── geofancy_server.rs ├── main.rs └── tile38_client.rs /.env.template: -------------------------------------------------------------------------------- 1 | # grpc server 2 | GRPC_SERVER_PORT=xxxx 3 | GRPC_SERVER_USE_TLS=false 4 | 5 | #tile38 connection 6 | TILE38_CONNECTION=redis://xxxxxxx:xxxx/x -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### JetBrains template 2 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm 3 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 4 | 5 | # User-specific stuff: 6 | .idea/**/workspace.xml 7 | .idea/**/tasks.xml 8 | .idea/dictionaries 9 | 10 | # Sensitive or high-churn files: 11 | .idea/**/dataSources/ 12 | .idea/**/dataSources.ids 13 | .idea/**/dataSources.local.xml 14 | .idea/**/sqlDataSources.xml 15 | .idea/**/dynamic.xml 16 | .idea/**/uiDesigner.xml 17 | 18 | # JIRA plugin 19 | atlassian-ide-plugin.xml 20 | 21 | ### Rust template 22 | # Generated by Cargo 23 | # will have compiled files and executables 24 | /target/ 25 | **/*.rs.bk 26 | .env 27 | 28 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 29 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 30 | # Cargo.lock 31 | 32 | # These are backup files generated by rustfmt 33 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | # Official language image. Look for the different tagged releases at: 2 | # https://hub.docker.com/r/library/rust/tags/ 3 | image: "rust:latest" 4 | 5 | # Optional: Pick zero or more services to be used on all builds. 6 | # Only needed when using a docker container to run your tests in. 7 | # Check out: http://docs.gitlab.com/ce/ci/docker/using_docker_images.html#what-is-a-service 8 | services: 9 | - tile38/tile38:latest 10 | # - redis:latest 11 | # - postgres:latest 12 | 13 | before_script: 14 | # install unzip 15 | - apt update -yqq 16 | - apt install -yqq unzip 17 | # install protoc 18 | - curl -OL https://github.com/google/protobuf/releases/download/v3.5.1/protoc-3.5.1-linux-x86_64.zip 19 | - unzip protoc-3.5.1-linux-x86_64.zip -d protoc3 20 | - mv protoc3/bin/* /usr/local/bin/ 21 | - mv protoc3/include/* /usr/local/include/ 22 | 23 | # Use cargo to test the project 24 | test:cargo: 25 | script: 26 | - rustc --version && cargo --version # Print version info for debugging 27 | - cargo test --all --verbose 28 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 13 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /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.22.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" 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 = "aho-corasick" 22 | version = "1.1.3" 23 | source = "registry+https://github.com/rust-lang/crates.io-index" 24 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 25 | dependencies = [ 26 | "memchr", 27 | ] 28 | 29 | [[package]] 30 | name = "anyhow" 31 | version = "1.0.86" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" 34 | 35 | [[package]] 36 | name = "async-stream" 37 | version = "0.3.5" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" 40 | dependencies = [ 41 | "async-stream-impl", 42 | "futures-core", 43 | "pin-project-lite", 44 | ] 45 | 46 | [[package]] 47 | name = "async-stream-impl" 48 | version = "0.3.5" 49 | source = "registry+https://github.com/rust-lang/crates.io-index" 50 | checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" 51 | dependencies = [ 52 | "proc-macro2", 53 | "quote", 54 | "syn", 55 | ] 56 | 57 | [[package]] 58 | name = "async-trait" 59 | version = "0.1.80" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" 62 | dependencies = [ 63 | "proc-macro2", 64 | "quote", 65 | "syn", 66 | ] 67 | 68 | [[package]] 69 | name = "autocfg" 70 | version = "1.3.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" 73 | 74 | [[package]] 75 | name = "axum" 76 | version = "0.6.20" 77 | source = "registry+https://github.com/rust-lang/crates.io-index" 78 | checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" 79 | dependencies = [ 80 | "async-trait", 81 | "axum-core", 82 | "bitflags 1.3.2", 83 | "bytes", 84 | "futures-util", 85 | "http", 86 | "http-body", 87 | "hyper", 88 | "itoa", 89 | "matchit", 90 | "memchr", 91 | "mime", 92 | "percent-encoding", 93 | "pin-project-lite", 94 | "rustversion", 95 | "serde", 96 | "sync_wrapper", 97 | "tower", 98 | "tower-layer", 99 | "tower-service", 100 | ] 101 | 102 | [[package]] 103 | name = "axum-core" 104 | version = "0.3.4" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" 107 | dependencies = [ 108 | "async-trait", 109 | "bytes", 110 | "futures-util", 111 | "http", 112 | "http-body", 113 | "mime", 114 | "rustversion", 115 | "tower-layer", 116 | "tower-service", 117 | ] 118 | 119 | [[package]] 120 | name = "backtrace" 121 | version = "0.3.73" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" 124 | dependencies = [ 125 | "addr2line", 126 | "cc", 127 | "cfg-if", 128 | "libc", 129 | "miniz_oxide", 130 | "object", 131 | "rustc-demangle", 132 | ] 133 | 134 | [[package]] 135 | name = "base64" 136 | version = "0.21.7" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 139 | 140 | [[package]] 141 | name = "bitflags" 142 | version = "1.3.2" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 145 | 146 | [[package]] 147 | name = "bitflags" 148 | version = "2.5.0" 149 | source = "registry+https://github.com/rust-lang/crates.io-index" 150 | checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" 151 | 152 | [[package]] 153 | name = "bytes" 154 | version = "1.6.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" 157 | 158 | [[package]] 159 | name = "cc" 160 | version = "1.0.99" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" 163 | 164 | [[package]] 165 | name = "cfg-if" 166 | version = "1.0.0" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 169 | 170 | [[package]] 171 | name = "combine" 172 | version = "4.6.7" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" 175 | dependencies = [ 176 | "bytes", 177 | "futures-core", 178 | "memchr", 179 | "pin-project-lite", 180 | "tokio", 181 | "tokio-util", 182 | ] 183 | 184 | [[package]] 185 | name = "dotenv" 186 | version = "0.15.0" 187 | source = "registry+https://github.com/rust-lang/crates.io-index" 188 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 189 | 190 | [[package]] 191 | name = "either" 192 | version = "1.12.0" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" 195 | 196 | [[package]] 197 | name = "equivalent" 198 | version = "1.0.1" 199 | source = "registry+https://github.com/rust-lang/crates.io-index" 200 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 201 | 202 | [[package]] 203 | name = "errno" 204 | version = "0.3.9" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 207 | dependencies = [ 208 | "libc", 209 | "windows-sys 0.52.0", 210 | ] 211 | 212 | [[package]] 213 | name = "fastrand" 214 | version = "2.1.0" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" 217 | 218 | [[package]] 219 | name = "fixedbitset" 220 | version = "0.4.2" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" 223 | 224 | [[package]] 225 | name = "fnv" 226 | version = "1.0.7" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 229 | 230 | [[package]] 231 | name = "form_urlencoded" 232 | version = "1.2.1" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 235 | dependencies = [ 236 | "percent-encoding", 237 | ] 238 | 239 | [[package]] 240 | name = "futures" 241 | version = "0.3.30" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" 244 | dependencies = [ 245 | "futures-channel", 246 | "futures-core", 247 | "futures-executor", 248 | "futures-io", 249 | "futures-sink", 250 | "futures-task", 251 | "futures-util", 252 | ] 253 | 254 | [[package]] 255 | name = "futures-channel" 256 | version = "0.3.30" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" 259 | dependencies = [ 260 | "futures-core", 261 | "futures-sink", 262 | ] 263 | 264 | [[package]] 265 | name = "futures-core" 266 | version = "0.3.30" 267 | source = "registry+https://github.com/rust-lang/crates.io-index" 268 | checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" 269 | 270 | [[package]] 271 | name = "futures-executor" 272 | version = "0.3.30" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" 275 | dependencies = [ 276 | "futures-core", 277 | "futures-task", 278 | "futures-util", 279 | ] 280 | 281 | [[package]] 282 | name = "futures-io" 283 | version = "0.3.30" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" 286 | 287 | [[package]] 288 | name = "futures-macro" 289 | version = "0.3.30" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" 292 | dependencies = [ 293 | "proc-macro2", 294 | "quote", 295 | "syn", 296 | ] 297 | 298 | [[package]] 299 | name = "futures-sink" 300 | version = "0.3.30" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" 303 | 304 | [[package]] 305 | name = "futures-task" 306 | version = "0.3.30" 307 | source = "registry+https://github.com/rust-lang/crates.io-index" 308 | checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" 309 | 310 | [[package]] 311 | name = "futures-util" 312 | version = "0.3.30" 313 | source = "registry+https://github.com/rust-lang/crates.io-index" 314 | checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" 315 | dependencies = [ 316 | "futures-channel", 317 | "futures-core", 318 | "futures-io", 319 | "futures-macro", 320 | "futures-sink", 321 | "futures-task", 322 | "memchr", 323 | "pin-project-lite", 324 | "pin-utils", 325 | "slab", 326 | ] 327 | 328 | [[package]] 329 | name = "geofancy-rust" 330 | version = "0.1.0" 331 | dependencies = [ 332 | "bytes", 333 | "dotenv", 334 | "futures", 335 | "log", 336 | "prost", 337 | "redis", 338 | "tokio", 339 | "tonic", 340 | "tonic-build", 341 | ] 342 | 343 | [[package]] 344 | name = "getrandom" 345 | version = "0.2.15" 346 | source = "registry+https://github.com/rust-lang/crates.io-index" 347 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 348 | dependencies = [ 349 | "cfg-if", 350 | "libc", 351 | "wasi", 352 | ] 353 | 354 | [[package]] 355 | name = "gimli" 356 | version = "0.29.0" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" 359 | 360 | [[package]] 361 | name = "h2" 362 | version = "0.3.26" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 365 | dependencies = [ 366 | "bytes", 367 | "fnv", 368 | "futures-core", 369 | "futures-sink", 370 | "futures-util", 371 | "http", 372 | "indexmap 2.2.6", 373 | "slab", 374 | "tokio", 375 | "tokio-util", 376 | "tracing", 377 | ] 378 | 379 | [[package]] 380 | name = "hashbrown" 381 | version = "0.12.3" 382 | source = "registry+https://github.com/rust-lang/crates.io-index" 383 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 384 | 385 | [[package]] 386 | name = "hashbrown" 387 | version = "0.14.5" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 390 | 391 | [[package]] 392 | name = "heck" 393 | version = "0.5.0" 394 | source = "registry+https://github.com/rust-lang/crates.io-index" 395 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 396 | 397 | [[package]] 398 | name = "hermit-abi" 399 | version = "0.3.9" 400 | source = "registry+https://github.com/rust-lang/crates.io-index" 401 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 402 | 403 | [[package]] 404 | name = "http" 405 | version = "0.2.12" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 408 | dependencies = [ 409 | "bytes", 410 | "fnv", 411 | "itoa", 412 | ] 413 | 414 | [[package]] 415 | name = "http-body" 416 | version = "0.4.6" 417 | source = "registry+https://github.com/rust-lang/crates.io-index" 418 | checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" 419 | dependencies = [ 420 | "bytes", 421 | "http", 422 | "pin-project-lite", 423 | ] 424 | 425 | [[package]] 426 | name = "httparse" 427 | version = "1.9.4" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" 430 | 431 | [[package]] 432 | name = "httpdate" 433 | version = "1.0.3" 434 | source = "registry+https://github.com/rust-lang/crates.io-index" 435 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 436 | 437 | [[package]] 438 | name = "hyper" 439 | version = "0.14.29" 440 | source = "registry+https://github.com/rust-lang/crates.io-index" 441 | checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" 442 | dependencies = [ 443 | "bytes", 444 | "futures-channel", 445 | "futures-core", 446 | "futures-util", 447 | "h2", 448 | "http", 449 | "http-body", 450 | "httparse", 451 | "httpdate", 452 | "itoa", 453 | "pin-project-lite", 454 | "socket2", 455 | "tokio", 456 | "tower-service", 457 | "tracing", 458 | "want", 459 | ] 460 | 461 | [[package]] 462 | name = "hyper-timeout" 463 | version = "0.4.1" 464 | source = "registry+https://github.com/rust-lang/crates.io-index" 465 | checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" 466 | dependencies = [ 467 | "hyper", 468 | "pin-project-lite", 469 | "tokio", 470 | "tokio-io-timeout", 471 | ] 472 | 473 | [[package]] 474 | name = "idna" 475 | version = "0.5.0" 476 | source = "registry+https://github.com/rust-lang/crates.io-index" 477 | checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" 478 | dependencies = [ 479 | "unicode-bidi", 480 | "unicode-normalization", 481 | ] 482 | 483 | [[package]] 484 | name = "indexmap" 485 | version = "1.9.3" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 488 | dependencies = [ 489 | "autocfg", 490 | "hashbrown 0.12.3", 491 | ] 492 | 493 | [[package]] 494 | name = "indexmap" 495 | version = "2.2.6" 496 | source = "registry+https://github.com/rust-lang/crates.io-index" 497 | checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" 498 | dependencies = [ 499 | "equivalent", 500 | "hashbrown 0.14.5", 501 | ] 502 | 503 | [[package]] 504 | name = "itertools" 505 | version = "0.12.1" 506 | source = "registry+https://github.com/rust-lang/crates.io-index" 507 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 508 | dependencies = [ 509 | "either", 510 | ] 511 | 512 | [[package]] 513 | name = "itoa" 514 | version = "1.0.11" 515 | source = "registry+https://github.com/rust-lang/crates.io-index" 516 | checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" 517 | 518 | [[package]] 519 | name = "libc" 520 | version = "0.2.155" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" 523 | 524 | [[package]] 525 | name = "linux-raw-sys" 526 | version = "0.4.14" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 529 | 530 | [[package]] 531 | name = "lock_api" 532 | version = "0.4.12" 533 | source = "registry+https://github.com/rust-lang/crates.io-index" 534 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 535 | dependencies = [ 536 | "autocfg", 537 | "scopeguard", 538 | ] 539 | 540 | [[package]] 541 | name = "log" 542 | version = "0.4.21" 543 | source = "registry+https://github.com/rust-lang/crates.io-index" 544 | checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" 545 | 546 | [[package]] 547 | name = "matchit" 548 | version = "0.7.3" 549 | source = "registry+https://github.com/rust-lang/crates.io-index" 550 | checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" 551 | 552 | [[package]] 553 | name = "memchr" 554 | version = "2.7.4" 555 | source = "registry+https://github.com/rust-lang/crates.io-index" 556 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 557 | 558 | [[package]] 559 | name = "mime" 560 | version = "0.3.17" 561 | source = "registry+https://github.com/rust-lang/crates.io-index" 562 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 563 | 564 | [[package]] 565 | name = "miniz_oxide" 566 | version = "0.7.4" 567 | source = "registry+https://github.com/rust-lang/crates.io-index" 568 | checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" 569 | dependencies = [ 570 | "adler", 571 | ] 572 | 573 | [[package]] 574 | name = "mio" 575 | version = "0.8.11" 576 | source = "registry+https://github.com/rust-lang/crates.io-index" 577 | checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" 578 | dependencies = [ 579 | "libc", 580 | "wasi", 581 | "windows-sys 0.48.0", 582 | ] 583 | 584 | [[package]] 585 | name = "multimap" 586 | version = "0.10.0" 587 | source = "registry+https://github.com/rust-lang/crates.io-index" 588 | checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" 589 | 590 | [[package]] 591 | name = "num_cpus" 592 | version = "1.16.0" 593 | source = "registry+https://github.com/rust-lang/crates.io-index" 594 | checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" 595 | dependencies = [ 596 | "hermit-abi", 597 | "libc", 598 | ] 599 | 600 | [[package]] 601 | name = "object" 602 | version = "0.36.0" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" 605 | dependencies = [ 606 | "memchr", 607 | ] 608 | 609 | [[package]] 610 | name = "once_cell" 611 | version = "1.19.0" 612 | source = "registry+https://github.com/rust-lang/crates.io-index" 613 | checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" 614 | 615 | [[package]] 616 | name = "parking_lot" 617 | version = "0.12.3" 618 | source = "registry+https://github.com/rust-lang/crates.io-index" 619 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 620 | dependencies = [ 621 | "lock_api", 622 | "parking_lot_core", 623 | ] 624 | 625 | [[package]] 626 | name = "parking_lot_core" 627 | version = "0.9.10" 628 | source = "registry+https://github.com/rust-lang/crates.io-index" 629 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 630 | dependencies = [ 631 | "cfg-if", 632 | "libc", 633 | "redox_syscall", 634 | "smallvec", 635 | "windows-targets 0.52.5", 636 | ] 637 | 638 | [[package]] 639 | name = "percent-encoding" 640 | version = "2.3.1" 641 | source = "registry+https://github.com/rust-lang/crates.io-index" 642 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 643 | 644 | [[package]] 645 | name = "petgraph" 646 | version = "0.6.5" 647 | source = "registry+https://github.com/rust-lang/crates.io-index" 648 | checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" 649 | dependencies = [ 650 | "fixedbitset", 651 | "indexmap 2.2.6", 652 | ] 653 | 654 | [[package]] 655 | name = "pin-project" 656 | version = "1.1.5" 657 | source = "registry+https://github.com/rust-lang/crates.io-index" 658 | checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" 659 | dependencies = [ 660 | "pin-project-internal", 661 | ] 662 | 663 | [[package]] 664 | name = "pin-project-internal" 665 | version = "1.1.5" 666 | source = "registry+https://github.com/rust-lang/crates.io-index" 667 | checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" 668 | dependencies = [ 669 | "proc-macro2", 670 | "quote", 671 | "syn", 672 | ] 673 | 674 | [[package]] 675 | name = "pin-project-lite" 676 | version = "0.2.14" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" 679 | 680 | [[package]] 681 | name = "pin-utils" 682 | version = "0.1.0" 683 | source = "registry+https://github.com/rust-lang/crates.io-index" 684 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 685 | 686 | [[package]] 687 | name = "ppv-lite86" 688 | version = "0.2.17" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 691 | 692 | [[package]] 693 | name = "prettyplease" 694 | version = "0.2.20" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" 697 | dependencies = [ 698 | "proc-macro2", 699 | "syn", 700 | ] 701 | 702 | [[package]] 703 | name = "proc-macro2" 704 | version = "1.0.86" 705 | source = "registry+https://github.com/rust-lang/crates.io-index" 706 | checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" 707 | dependencies = [ 708 | "unicode-ident", 709 | ] 710 | 711 | [[package]] 712 | name = "prost" 713 | version = "0.12.6" 714 | source = "registry+https://github.com/rust-lang/crates.io-index" 715 | checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" 716 | dependencies = [ 717 | "bytes", 718 | "prost-derive", 719 | ] 720 | 721 | [[package]] 722 | name = "prost-build" 723 | version = "0.12.6" 724 | source = "registry+https://github.com/rust-lang/crates.io-index" 725 | checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" 726 | dependencies = [ 727 | "bytes", 728 | "heck", 729 | "itertools", 730 | "log", 731 | "multimap", 732 | "once_cell", 733 | "petgraph", 734 | "prettyplease", 735 | "prost", 736 | "prost-types", 737 | "regex", 738 | "syn", 739 | "tempfile", 740 | ] 741 | 742 | [[package]] 743 | name = "prost-derive" 744 | version = "0.12.6" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" 747 | dependencies = [ 748 | "anyhow", 749 | "itertools", 750 | "proc-macro2", 751 | "quote", 752 | "syn", 753 | ] 754 | 755 | [[package]] 756 | name = "prost-types" 757 | version = "0.12.6" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" 760 | dependencies = [ 761 | "prost", 762 | ] 763 | 764 | [[package]] 765 | name = "quote" 766 | version = "1.0.36" 767 | source = "registry+https://github.com/rust-lang/crates.io-index" 768 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 769 | dependencies = [ 770 | "proc-macro2", 771 | ] 772 | 773 | [[package]] 774 | name = "rand" 775 | version = "0.8.5" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 778 | dependencies = [ 779 | "libc", 780 | "rand_chacha", 781 | "rand_core", 782 | ] 783 | 784 | [[package]] 785 | name = "rand_chacha" 786 | version = "0.3.1" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 789 | dependencies = [ 790 | "ppv-lite86", 791 | "rand_core", 792 | ] 793 | 794 | [[package]] 795 | name = "rand_core" 796 | version = "0.6.4" 797 | source = "registry+https://github.com/rust-lang/crates.io-index" 798 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 799 | dependencies = [ 800 | "getrandom", 801 | ] 802 | 803 | [[package]] 804 | name = "redis" 805 | version = "0.25.4" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "e0d7a6955c7511f60f3ba9e86c6d02b3c3f144f8c24b288d1f4e18074ab8bbec" 808 | dependencies = [ 809 | "async-trait", 810 | "bytes", 811 | "combine", 812 | "futures-util", 813 | "itoa", 814 | "percent-encoding", 815 | "pin-project-lite", 816 | "ryu", 817 | "sha1_smol", 818 | "socket2", 819 | "tokio", 820 | "tokio-util", 821 | "url", 822 | ] 823 | 824 | [[package]] 825 | name = "redox_syscall" 826 | version = "0.5.2" 827 | source = "registry+https://github.com/rust-lang/crates.io-index" 828 | checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" 829 | dependencies = [ 830 | "bitflags 2.5.0", 831 | ] 832 | 833 | [[package]] 834 | name = "regex" 835 | version = "1.10.5" 836 | source = "registry+https://github.com/rust-lang/crates.io-index" 837 | checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" 838 | dependencies = [ 839 | "aho-corasick", 840 | "memchr", 841 | "regex-automata", 842 | "regex-syntax", 843 | ] 844 | 845 | [[package]] 846 | name = "regex-automata" 847 | version = "0.4.7" 848 | source = "registry+https://github.com/rust-lang/crates.io-index" 849 | checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" 850 | dependencies = [ 851 | "aho-corasick", 852 | "memchr", 853 | "regex-syntax", 854 | ] 855 | 856 | [[package]] 857 | name = "regex-syntax" 858 | version = "0.8.4" 859 | source = "registry+https://github.com/rust-lang/crates.io-index" 860 | checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" 861 | 862 | [[package]] 863 | name = "rustc-demangle" 864 | version = "0.1.24" 865 | source = "registry+https://github.com/rust-lang/crates.io-index" 866 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 867 | 868 | [[package]] 869 | name = "rustix" 870 | version = "0.38.34" 871 | source = "registry+https://github.com/rust-lang/crates.io-index" 872 | checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" 873 | dependencies = [ 874 | "bitflags 2.5.0", 875 | "errno", 876 | "libc", 877 | "linux-raw-sys", 878 | "windows-sys 0.52.0", 879 | ] 880 | 881 | [[package]] 882 | name = "rustversion" 883 | version = "1.0.17" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" 886 | 887 | [[package]] 888 | name = "ryu" 889 | version = "1.0.18" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 892 | 893 | [[package]] 894 | name = "scopeguard" 895 | version = "1.2.0" 896 | source = "registry+https://github.com/rust-lang/crates.io-index" 897 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 898 | 899 | [[package]] 900 | name = "serde" 901 | version = "1.0.203" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" 904 | dependencies = [ 905 | "serde_derive", 906 | ] 907 | 908 | [[package]] 909 | name = "serde_derive" 910 | version = "1.0.203" 911 | source = "registry+https://github.com/rust-lang/crates.io-index" 912 | checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" 913 | dependencies = [ 914 | "proc-macro2", 915 | "quote", 916 | "syn", 917 | ] 918 | 919 | [[package]] 920 | name = "sha1_smol" 921 | version = "1.0.0" 922 | source = "registry+https://github.com/rust-lang/crates.io-index" 923 | checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" 924 | 925 | [[package]] 926 | name = "signal-hook-registry" 927 | version = "1.4.2" 928 | source = "registry+https://github.com/rust-lang/crates.io-index" 929 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 930 | dependencies = [ 931 | "libc", 932 | ] 933 | 934 | [[package]] 935 | name = "slab" 936 | version = "0.4.9" 937 | source = "registry+https://github.com/rust-lang/crates.io-index" 938 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 939 | dependencies = [ 940 | "autocfg", 941 | ] 942 | 943 | [[package]] 944 | name = "smallvec" 945 | version = "1.13.2" 946 | source = "registry+https://github.com/rust-lang/crates.io-index" 947 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 948 | 949 | [[package]] 950 | name = "socket2" 951 | version = "0.5.7" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 954 | dependencies = [ 955 | "libc", 956 | "windows-sys 0.52.0", 957 | ] 958 | 959 | [[package]] 960 | name = "syn" 961 | version = "2.0.67" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90" 964 | dependencies = [ 965 | "proc-macro2", 966 | "quote", 967 | "unicode-ident", 968 | ] 969 | 970 | [[package]] 971 | name = "sync_wrapper" 972 | version = "0.1.2" 973 | source = "registry+https://github.com/rust-lang/crates.io-index" 974 | checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" 975 | 976 | [[package]] 977 | name = "tempfile" 978 | version = "3.10.1" 979 | source = "registry+https://github.com/rust-lang/crates.io-index" 980 | checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" 981 | dependencies = [ 982 | "cfg-if", 983 | "fastrand", 984 | "rustix", 985 | "windows-sys 0.52.0", 986 | ] 987 | 988 | [[package]] 989 | name = "tinyvec" 990 | version = "1.6.0" 991 | source = "registry+https://github.com/rust-lang/crates.io-index" 992 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 993 | dependencies = [ 994 | "tinyvec_macros", 995 | ] 996 | 997 | [[package]] 998 | name = "tinyvec_macros" 999 | version = "0.1.1" 1000 | source = "registry+https://github.com/rust-lang/crates.io-index" 1001 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1002 | 1003 | [[package]] 1004 | name = "tokio" 1005 | version = "1.38.0" 1006 | source = "registry+https://github.com/rust-lang/crates.io-index" 1007 | checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" 1008 | dependencies = [ 1009 | "backtrace", 1010 | "bytes", 1011 | "libc", 1012 | "mio", 1013 | "num_cpus", 1014 | "parking_lot", 1015 | "pin-project-lite", 1016 | "signal-hook-registry", 1017 | "socket2", 1018 | "tokio-macros", 1019 | "windows-sys 0.48.0", 1020 | ] 1021 | 1022 | [[package]] 1023 | name = "tokio-io-timeout" 1024 | version = "1.2.0" 1025 | source = "registry+https://github.com/rust-lang/crates.io-index" 1026 | checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" 1027 | dependencies = [ 1028 | "pin-project-lite", 1029 | "tokio", 1030 | ] 1031 | 1032 | [[package]] 1033 | name = "tokio-macros" 1034 | version = "2.3.0" 1035 | source = "registry+https://github.com/rust-lang/crates.io-index" 1036 | checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" 1037 | dependencies = [ 1038 | "proc-macro2", 1039 | "quote", 1040 | "syn", 1041 | ] 1042 | 1043 | [[package]] 1044 | name = "tokio-stream" 1045 | version = "0.1.15" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" 1048 | dependencies = [ 1049 | "futures-core", 1050 | "pin-project-lite", 1051 | "tokio", 1052 | ] 1053 | 1054 | [[package]] 1055 | name = "tokio-util" 1056 | version = "0.7.11" 1057 | source = "registry+https://github.com/rust-lang/crates.io-index" 1058 | checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" 1059 | dependencies = [ 1060 | "bytes", 1061 | "futures-core", 1062 | "futures-sink", 1063 | "pin-project-lite", 1064 | "tokio", 1065 | ] 1066 | 1067 | [[package]] 1068 | name = "tonic" 1069 | version = "0.11.0" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" 1072 | dependencies = [ 1073 | "async-stream", 1074 | "async-trait", 1075 | "axum", 1076 | "base64", 1077 | "bytes", 1078 | "h2", 1079 | "http", 1080 | "http-body", 1081 | "hyper", 1082 | "hyper-timeout", 1083 | "percent-encoding", 1084 | "pin-project", 1085 | "prost", 1086 | "tokio", 1087 | "tokio-stream", 1088 | "tower", 1089 | "tower-layer", 1090 | "tower-service", 1091 | "tracing", 1092 | ] 1093 | 1094 | [[package]] 1095 | name = "tonic-build" 1096 | version = "0.11.0" 1097 | source = "registry+https://github.com/rust-lang/crates.io-index" 1098 | checksum = "be4ef6dd70a610078cb4e338a0f79d06bc759ff1b22d2120c2ff02ae264ba9c2" 1099 | dependencies = [ 1100 | "prettyplease", 1101 | "proc-macro2", 1102 | "prost-build", 1103 | "quote", 1104 | "syn", 1105 | ] 1106 | 1107 | [[package]] 1108 | name = "tower" 1109 | version = "0.4.13" 1110 | source = "registry+https://github.com/rust-lang/crates.io-index" 1111 | checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 1112 | dependencies = [ 1113 | "futures-core", 1114 | "futures-util", 1115 | "indexmap 1.9.3", 1116 | "pin-project", 1117 | "pin-project-lite", 1118 | "rand", 1119 | "slab", 1120 | "tokio", 1121 | "tokio-util", 1122 | "tower-layer", 1123 | "tower-service", 1124 | "tracing", 1125 | ] 1126 | 1127 | [[package]] 1128 | name = "tower-layer" 1129 | version = "0.3.2" 1130 | source = "registry+https://github.com/rust-lang/crates.io-index" 1131 | checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" 1132 | 1133 | [[package]] 1134 | name = "tower-service" 1135 | version = "0.3.2" 1136 | source = "registry+https://github.com/rust-lang/crates.io-index" 1137 | checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" 1138 | 1139 | [[package]] 1140 | name = "tracing" 1141 | version = "0.1.40" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 1144 | dependencies = [ 1145 | "pin-project-lite", 1146 | "tracing-attributes", 1147 | "tracing-core", 1148 | ] 1149 | 1150 | [[package]] 1151 | name = "tracing-attributes" 1152 | version = "0.1.27" 1153 | source = "registry+https://github.com/rust-lang/crates.io-index" 1154 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 1155 | dependencies = [ 1156 | "proc-macro2", 1157 | "quote", 1158 | "syn", 1159 | ] 1160 | 1161 | [[package]] 1162 | name = "tracing-core" 1163 | version = "0.1.32" 1164 | source = "registry+https://github.com/rust-lang/crates.io-index" 1165 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 1166 | dependencies = [ 1167 | "once_cell", 1168 | ] 1169 | 1170 | [[package]] 1171 | name = "try-lock" 1172 | version = "0.2.5" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1175 | 1176 | [[package]] 1177 | name = "unicode-bidi" 1178 | version = "0.3.15" 1179 | source = "registry+https://github.com/rust-lang/crates.io-index" 1180 | checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" 1181 | 1182 | [[package]] 1183 | name = "unicode-ident" 1184 | version = "1.0.12" 1185 | source = "registry+https://github.com/rust-lang/crates.io-index" 1186 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 1187 | 1188 | [[package]] 1189 | name = "unicode-normalization" 1190 | version = "0.1.23" 1191 | source = "registry+https://github.com/rust-lang/crates.io-index" 1192 | checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" 1193 | dependencies = [ 1194 | "tinyvec", 1195 | ] 1196 | 1197 | [[package]] 1198 | name = "url" 1199 | version = "2.5.2" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" 1202 | dependencies = [ 1203 | "form_urlencoded", 1204 | "idna", 1205 | "percent-encoding", 1206 | ] 1207 | 1208 | [[package]] 1209 | name = "want" 1210 | version = "0.3.1" 1211 | source = "registry+https://github.com/rust-lang/crates.io-index" 1212 | checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1213 | dependencies = [ 1214 | "try-lock", 1215 | ] 1216 | 1217 | [[package]] 1218 | name = "wasi" 1219 | version = "0.11.0+wasi-snapshot-preview1" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1222 | 1223 | [[package]] 1224 | name = "windows-sys" 1225 | version = "0.48.0" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 1228 | dependencies = [ 1229 | "windows-targets 0.48.5", 1230 | ] 1231 | 1232 | [[package]] 1233 | name = "windows-sys" 1234 | version = "0.52.0" 1235 | source = "registry+https://github.com/rust-lang/crates.io-index" 1236 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1237 | dependencies = [ 1238 | "windows-targets 0.52.5", 1239 | ] 1240 | 1241 | [[package]] 1242 | name = "windows-targets" 1243 | version = "0.48.5" 1244 | source = "registry+https://github.com/rust-lang/crates.io-index" 1245 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 1246 | dependencies = [ 1247 | "windows_aarch64_gnullvm 0.48.5", 1248 | "windows_aarch64_msvc 0.48.5", 1249 | "windows_i686_gnu 0.48.5", 1250 | "windows_i686_msvc 0.48.5", 1251 | "windows_x86_64_gnu 0.48.5", 1252 | "windows_x86_64_gnullvm 0.48.5", 1253 | "windows_x86_64_msvc 0.48.5", 1254 | ] 1255 | 1256 | [[package]] 1257 | name = "windows-targets" 1258 | version = "0.52.5" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" 1261 | dependencies = [ 1262 | "windows_aarch64_gnullvm 0.52.5", 1263 | "windows_aarch64_msvc 0.52.5", 1264 | "windows_i686_gnu 0.52.5", 1265 | "windows_i686_gnullvm", 1266 | "windows_i686_msvc 0.52.5", 1267 | "windows_x86_64_gnu 0.52.5", 1268 | "windows_x86_64_gnullvm 0.52.5", 1269 | "windows_x86_64_msvc 0.52.5", 1270 | ] 1271 | 1272 | [[package]] 1273 | name = "windows_aarch64_gnullvm" 1274 | version = "0.48.5" 1275 | source = "registry+https://github.com/rust-lang/crates.io-index" 1276 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 1277 | 1278 | [[package]] 1279 | name = "windows_aarch64_gnullvm" 1280 | version = "0.52.5" 1281 | source = "registry+https://github.com/rust-lang/crates.io-index" 1282 | checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" 1283 | 1284 | [[package]] 1285 | name = "windows_aarch64_msvc" 1286 | version = "0.48.5" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 1289 | 1290 | [[package]] 1291 | name = "windows_aarch64_msvc" 1292 | version = "0.52.5" 1293 | source = "registry+https://github.com/rust-lang/crates.io-index" 1294 | checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" 1295 | 1296 | [[package]] 1297 | name = "windows_i686_gnu" 1298 | version = "0.48.5" 1299 | source = "registry+https://github.com/rust-lang/crates.io-index" 1300 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 1301 | 1302 | [[package]] 1303 | name = "windows_i686_gnu" 1304 | version = "0.52.5" 1305 | source = "registry+https://github.com/rust-lang/crates.io-index" 1306 | checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" 1307 | 1308 | [[package]] 1309 | name = "windows_i686_gnullvm" 1310 | version = "0.52.5" 1311 | source = "registry+https://github.com/rust-lang/crates.io-index" 1312 | checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" 1313 | 1314 | [[package]] 1315 | name = "windows_i686_msvc" 1316 | version = "0.48.5" 1317 | source = "registry+https://github.com/rust-lang/crates.io-index" 1318 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 1319 | 1320 | [[package]] 1321 | name = "windows_i686_msvc" 1322 | version = "0.52.5" 1323 | source = "registry+https://github.com/rust-lang/crates.io-index" 1324 | checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" 1325 | 1326 | [[package]] 1327 | name = "windows_x86_64_gnu" 1328 | version = "0.48.5" 1329 | source = "registry+https://github.com/rust-lang/crates.io-index" 1330 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 1331 | 1332 | [[package]] 1333 | name = "windows_x86_64_gnu" 1334 | version = "0.52.5" 1335 | source = "registry+https://github.com/rust-lang/crates.io-index" 1336 | checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" 1337 | 1338 | [[package]] 1339 | name = "windows_x86_64_gnullvm" 1340 | version = "0.48.5" 1341 | source = "registry+https://github.com/rust-lang/crates.io-index" 1342 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 1343 | 1344 | [[package]] 1345 | name = "windows_x86_64_gnullvm" 1346 | version = "0.52.5" 1347 | source = "registry+https://github.com/rust-lang/crates.io-index" 1348 | checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" 1349 | 1350 | [[package]] 1351 | name = "windows_x86_64_msvc" 1352 | version = "0.48.5" 1353 | source = "registry+https://github.com/rust-lang/crates.io-index" 1354 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 1355 | 1356 | [[package]] 1357 | name = "windows_x86_64_msvc" 1358 | version = "0.52.5" 1359 | source = "registry+https://github.com/rust-lang/crates.io-index" 1360 | checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" 1361 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "geofancy-rust" 3 | version = "0.1.0" 4 | build = "build.rs" 5 | edition = "2021" 6 | 7 | [dependencies] 8 | log = "0.4.3" 9 | redis = { version = "0.25", features = ["tokio-comp"] } 10 | prost = "0.12" 11 | tonic = "0.11" 12 | futures = "0.3" 13 | bytes = "1" 14 | dotenv = "0.15" 15 | tokio = { version = "1", features = ["full"] } 16 | 17 | [build-dependencies] 18 | tonic-build = "0.11" 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # geofancy-rs 2 | 3 | Geofancy is a (hopefully) simple [gRPC](http://grpc.io) service that implements a subset of [Tile38](http://tile38.com). 4 | 5 | This repository contains the Rust implementation. 6 | 7 | There is also another repository ([geofancy-java](https://github.com/MovingGauteng/geofancy-java)), which contains the Java/Kotlin implementation of the server. 8 | 9 | ## Why Geofancy? 10 | 11 | Tile38 is a great program, that amongst others, allows one to set geofences between moving and static geospatial objects; with the ability to trigger webhooks when conditions are met. 12 | 13 | While we have tried out Tile38, we didn't want to implement all the logic that we wanted within some of our services, so we decided to create a separate service instead. 14 | 15 | Geofancy is a stand-alone microservice that connects with Tile38, and exposes a subset of its API via a gRPC service. 16 | 17 | ### Implemented Methods 18 | 19 | You can view the `geofancy.proto` , which lists the RPCs that are supported. 20 | 21 | At the time of writing (imagine a blog post with no date having this line) ... The API is still unstable, and can evolve. 22 | We have 23 | 24 | ```proto 25 | service GeofancyService { 26 | rpc CreateWebHook (GeoFence) returns (CommandResult) {} 27 | rpc DeleteWebHook (SearchString) returns (CommandResult) {} 28 | rpc SetDocument (Document) returns (CommandResult) {} 29 | rpc DeleteDocument (Document) returns (CommandResult) {} 30 | rpc DeleteCollection (Document) returns (CommandResult) {} 31 | } 32 | ``` 33 | 34 | Notice that we return a very simple `CommandResult` message. Contributions are welcome, if anyone would like to return something more solid as a result. -------------------------------------------------------------------------------- /build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), Box> { 2 | println!("cargo:rerun-if-changed=proto/geofancy.proto"); 3 | std::env::set_var("OUT_DIR", "src"); 4 | tonic_build::configure() 5 | .build_server(true) 6 | .compile(&["proto/geofancy.proto"], &["proto/"])?; 7 | Ok(()) 8 | } 9 | -------------------------------------------------------------------------------- /geofancy-rust.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /proto/geofancy.proto: -------------------------------------------------------------------------------- 1 | // version = 0.0.1 2 | 3 | // Version Changelog: 4 | // 5 | // v0.0.1 6 | // - initial message stubs, shape of messages not fully defined 7 | 8 | syntax = "proto3"; 9 | 10 | package geofancy; 11 | 12 | option java_multiple_files = true; 13 | option java_package = "za.co.movinggauteng.protos.geofancy"; 14 | option java_outer_classname = "GeofancyProto"; 15 | 16 | service GeofancyService { 17 | // CUD on entries 18 | rpc CreateWebHook (GeoFence) returns (CommandResult) {} 19 | rpc DeleteWebHook (SearchString) returns (CommandResult) {} 20 | rpc SetDocument (Document) returns (CommandResult) {} 21 | rpc DeleteDocument (Document) returns (CommandResult) {} 22 | rpc DeleteCollection (Document) returns (CommandResult) {} 23 | } 24 | 25 | message CommandResult { 26 | 27 | enum CommandStatus { 28 | COMMAND_OK = 0; 29 | COMMAND_FAILURE = 1; 30 | } 31 | 32 | CommandStatus status = 1; 33 | string message = 2; 34 | } 35 | 36 | message Document { 37 | string collection = 1; 38 | string id = 2; 39 | // TODO add FIELD data as a map/set 40 | oneof geo { 41 | Point point = 4; 42 | LineString line = 5; 43 | Bounds bounds = 6; 44 | string geojson = 7; 45 | } 46 | uint64 expiry = 10; // EX 47 | bool notExist = 11; // NX 48 | bool alreadyExist = 12; // XX 49 | } 50 | 51 | message Bounds { 52 | Coordinate southWest = 1; 53 | Coordinate northEast = 2; 54 | } 55 | 56 | message GeoFence { 57 | string id = 1; 58 | string endpoint = 2; 59 | oneof query { 60 | QueryNearby nearby = 3; 61 | QueryWithin within = 4; 62 | QueryIntersects intersects = 5; 63 | } 64 | string match = 6; 65 | repeated Detect detect = 7; 66 | repeated Commands commands = 8; 67 | // fence 68 | // TODO support more types per spec if we need them 69 | Point point = 9; 70 | uint64 distance = 10; 71 | 72 | message QueryNearby { 73 | string collection = 1; 74 | } 75 | message QueryWithin { 76 | string collection = 1; 77 | } 78 | message QueryIntersects { 79 | string collection = 1; 80 | } 81 | 82 | enum Detect { 83 | INSIDE = 0; 84 | OUTSIDE = 1; 85 | ENTER = 2; 86 | EXIT = 3; 87 | CROSS = 4; 88 | } 89 | 90 | enum Commands { 91 | SET = 0; 92 | DEL = 1; 93 | DROP = 2; 94 | } 95 | } 96 | 97 | message Point { 98 | Coordinate coord = 1; 99 | } 100 | 101 | message LineString { 102 | repeated Coordinate coords = 1; 103 | } 104 | 105 | message Coordinate { 106 | double lat = 1; 107 | double lng = 2; 108 | } 109 | 110 | message SearchString { 111 | string value = 1; 112 | } -------------------------------------------------------------------------------- /src/geofancy.rs: -------------------------------------------------------------------------------- 1 | // This file is @generated by prost-build. 2 | #[allow(clippy::derive_partial_eq_without_eq)] 3 | #[derive(Clone, PartialEq, ::prost::Message)] 4 | pub struct CommandResult { 5 | #[prost(enumeration = "command_result::CommandStatus", tag = "1")] 6 | pub status: i32, 7 | #[prost(string, tag = "2")] 8 | pub message: ::prost::alloc::string::String, 9 | } 10 | /// Nested message and enum types in `CommandResult`. 11 | pub mod command_result { 12 | #[derive( 13 | Clone, 14 | Copy, 15 | Debug, 16 | PartialEq, 17 | Eq, 18 | Hash, 19 | PartialOrd, 20 | Ord, 21 | ::prost::Enumeration 22 | )] 23 | #[repr(i32)] 24 | pub enum CommandStatus { 25 | CommandOk = 0, 26 | CommandFailure = 1, 27 | } 28 | impl CommandStatus { 29 | /// String value of the enum field names used in the ProtoBuf definition. 30 | /// 31 | /// The values are not transformed in any way and thus are considered stable 32 | /// (if the ProtoBuf definition does not change) and safe for programmatic use. 33 | pub fn as_str_name(&self) -> &'static str { 34 | match self { 35 | CommandStatus::CommandOk => "COMMAND_OK", 36 | CommandStatus::CommandFailure => "COMMAND_FAILURE", 37 | } 38 | } 39 | /// Creates an enum from field names used in the ProtoBuf definition. 40 | pub fn from_str_name(value: &str) -> ::core::option::Option { 41 | match value { 42 | "COMMAND_OK" => Some(Self::CommandOk), 43 | "COMMAND_FAILURE" => Some(Self::CommandFailure), 44 | _ => None, 45 | } 46 | } 47 | } 48 | } 49 | #[allow(clippy::derive_partial_eq_without_eq)] 50 | #[derive(Clone, PartialEq, ::prost::Message)] 51 | pub struct Document { 52 | #[prost(string, tag = "1")] 53 | pub collection: ::prost::alloc::string::String, 54 | #[prost(string, tag = "2")] 55 | pub id: ::prost::alloc::string::String, 56 | /// EX 57 | #[prost(uint64, tag = "10")] 58 | pub expiry: u64, 59 | /// NX 60 | #[prost(bool, tag = "11")] 61 | pub not_exist: bool, 62 | /// XX 63 | #[prost(bool, tag = "12")] 64 | pub already_exist: bool, 65 | /// TODO add FIELD data as a map/set 66 | #[prost(oneof = "document::Geo", tags = "4, 5, 6, 7")] 67 | pub geo: ::core::option::Option, 68 | } 69 | /// Nested message and enum types in `Document`. 70 | pub mod document { 71 | /// TODO add FIELD data as a map/set 72 | #[allow(clippy::derive_partial_eq_without_eq)] 73 | #[derive(Clone, PartialEq, ::prost::Oneof)] 74 | pub enum Geo { 75 | #[prost(message, tag = "4")] 76 | Point(super::Point), 77 | #[prost(message, tag = "5")] 78 | Line(super::LineString), 79 | #[prost(message, tag = "6")] 80 | Bounds(super::Bounds), 81 | #[prost(string, tag = "7")] 82 | Geojson(::prost::alloc::string::String), 83 | } 84 | } 85 | #[allow(clippy::derive_partial_eq_without_eq)] 86 | #[derive(Clone, PartialEq, ::prost::Message)] 87 | pub struct Bounds { 88 | #[prost(message, optional, tag = "1")] 89 | pub south_west: ::core::option::Option, 90 | #[prost(message, optional, tag = "2")] 91 | pub north_east: ::core::option::Option, 92 | } 93 | #[allow(clippy::derive_partial_eq_without_eq)] 94 | #[derive(Clone, PartialEq, ::prost::Message)] 95 | pub struct GeoFence { 96 | #[prost(string, tag = "1")] 97 | pub id: ::prost::alloc::string::String, 98 | #[prost(string, tag = "2")] 99 | pub endpoint: ::prost::alloc::string::String, 100 | #[prost(string, tag = "6")] 101 | pub r#match: ::prost::alloc::string::String, 102 | #[prost(enumeration = "geo_fence::Detect", repeated, tag = "7")] 103 | pub detect: ::prost::alloc::vec::Vec, 104 | #[prost(enumeration = "geo_fence::Commands", repeated, tag = "8")] 105 | pub commands: ::prost::alloc::vec::Vec, 106 | /// fence 107 | /// TODO support more types per spec if we need them 108 | #[prost(message, optional, tag = "9")] 109 | pub point: ::core::option::Option, 110 | #[prost(uint64, tag = "10")] 111 | pub distance: u64, 112 | #[prost(oneof = "geo_fence::Query", tags = "3, 4, 5")] 113 | pub query: ::core::option::Option, 114 | } 115 | /// Nested message and enum types in `GeoFence`. 116 | pub mod geo_fence { 117 | #[allow(clippy::derive_partial_eq_without_eq)] 118 | #[derive(Clone, PartialEq, ::prost::Message)] 119 | pub struct QueryNearby { 120 | #[prost(string, tag = "1")] 121 | pub collection: ::prost::alloc::string::String, 122 | } 123 | #[allow(clippy::derive_partial_eq_without_eq)] 124 | #[derive(Clone, PartialEq, ::prost::Message)] 125 | pub struct QueryWithin { 126 | #[prost(string, tag = "1")] 127 | pub collection: ::prost::alloc::string::String, 128 | } 129 | #[allow(clippy::derive_partial_eq_without_eq)] 130 | #[derive(Clone, PartialEq, ::prost::Message)] 131 | pub struct QueryIntersects { 132 | #[prost(string, tag = "1")] 133 | pub collection: ::prost::alloc::string::String, 134 | } 135 | #[derive( 136 | Clone, 137 | Copy, 138 | Debug, 139 | PartialEq, 140 | Eq, 141 | Hash, 142 | PartialOrd, 143 | Ord, 144 | ::prost::Enumeration 145 | )] 146 | #[repr(i32)] 147 | pub enum Detect { 148 | Inside = 0, 149 | Outside = 1, 150 | Enter = 2, 151 | Exit = 3, 152 | Cross = 4, 153 | } 154 | impl Detect { 155 | /// String value of the enum field names used in the ProtoBuf definition. 156 | /// 157 | /// The values are not transformed in any way and thus are considered stable 158 | /// (if the ProtoBuf definition does not change) and safe for programmatic use. 159 | pub fn as_str_name(&self) -> &'static str { 160 | match self { 161 | Detect::Inside => "INSIDE", 162 | Detect::Outside => "OUTSIDE", 163 | Detect::Enter => "ENTER", 164 | Detect::Exit => "EXIT", 165 | Detect::Cross => "CROSS", 166 | } 167 | } 168 | /// Creates an enum from field names used in the ProtoBuf definition. 169 | pub fn from_str_name(value: &str) -> ::core::option::Option { 170 | match value { 171 | "INSIDE" => Some(Self::Inside), 172 | "OUTSIDE" => Some(Self::Outside), 173 | "ENTER" => Some(Self::Enter), 174 | "EXIT" => Some(Self::Exit), 175 | "CROSS" => Some(Self::Cross), 176 | _ => None, 177 | } 178 | } 179 | } 180 | #[derive( 181 | Clone, 182 | Copy, 183 | Debug, 184 | PartialEq, 185 | Eq, 186 | Hash, 187 | PartialOrd, 188 | Ord, 189 | ::prost::Enumeration 190 | )] 191 | #[repr(i32)] 192 | pub enum Commands { 193 | Set = 0, 194 | Del = 1, 195 | Drop = 2, 196 | } 197 | impl Commands { 198 | /// String value of the enum field names used in the ProtoBuf definition. 199 | /// 200 | /// The values are not transformed in any way and thus are considered stable 201 | /// (if the ProtoBuf definition does not change) and safe for programmatic use. 202 | pub fn as_str_name(&self) -> &'static str { 203 | match self { 204 | Commands::Set => "SET", 205 | Commands::Del => "DEL", 206 | Commands::Drop => "DROP", 207 | } 208 | } 209 | /// Creates an enum from field names used in the ProtoBuf definition. 210 | pub fn from_str_name(value: &str) -> ::core::option::Option { 211 | match value { 212 | "SET" => Some(Self::Set), 213 | "DEL" => Some(Self::Del), 214 | "DROP" => Some(Self::Drop), 215 | _ => None, 216 | } 217 | } 218 | } 219 | #[allow(clippy::derive_partial_eq_without_eq)] 220 | #[derive(Clone, PartialEq, ::prost::Oneof)] 221 | pub enum Query { 222 | #[prost(message, tag = "3")] 223 | Nearby(QueryNearby), 224 | #[prost(message, tag = "4")] 225 | Within(QueryWithin), 226 | #[prost(message, tag = "5")] 227 | Intersects(QueryIntersects), 228 | } 229 | } 230 | #[allow(clippy::derive_partial_eq_without_eq)] 231 | #[derive(Clone, PartialEq, ::prost::Message)] 232 | pub struct Point { 233 | #[prost(message, optional, tag = "1")] 234 | pub coord: ::core::option::Option, 235 | } 236 | #[allow(clippy::derive_partial_eq_without_eq)] 237 | #[derive(Clone, PartialEq, ::prost::Message)] 238 | pub struct LineString { 239 | #[prost(message, repeated, tag = "1")] 240 | pub coords: ::prost::alloc::vec::Vec, 241 | } 242 | #[allow(clippy::derive_partial_eq_without_eq)] 243 | #[derive(Clone, PartialEq, ::prost::Message)] 244 | pub struct Coordinate { 245 | #[prost(double, tag = "1")] 246 | pub lat: f64, 247 | #[prost(double, tag = "2")] 248 | pub lng: f64, 249 | } 250 | #[allow(clippy::derive_partial_eq_without_eq)] 251 | #[derive(Clone, PartialEq, ::prost::Message)] 252 | pub struct SearchString { 253 | #[prost(string, tag = "1")] 254 | pub value: ::prost::alloc::string::String, 255 | } 256 | /// Generated client implementations. 257 | pub mod geofancy_service_client { 258 | #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] 259 | use tonic::codegen::*; 260 | use tonic::codegen::http::Uri; 261 | #[derive(Debug, Clone)] 262 | pub struct GeofancyServiceClient { 263 | inner: tonic::client::Grpc, 264 | } 265 | impl GeofancyServiceClient { 266 | /// Attempt to create a new client by connecting to a given endpoint. 267 | pub async fn connect(dst: D) -> Result 268 | where 269 | D: TryInto, 270 | D::Error: Into, 271 | { 272 | let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; 273 | Ok(Self::new(conn)) 274 | } 275 | } 276 | impl GeofancyServiceClient 277 | where 278 | T: tonic::client::GrpcService, 279 | T::Error: Into, 280 | T::ResponseBody: Body + Send + 'static, 281 | ::Error: Into + Send, 282 | { 283 | pub fn new(inner: T) -> Self { 284 | let inner = tonic::client::Grpc::new(inner); 285 | Self { inner } 286 | } 287 | pub fn with_origin(inner: T, origin: Uri) -> Self { 288 | let inner = tonic::client::Grpc::with_origin(inner, origin); 289 | Self { inner } 290 | } 291 | pub fn with_interceptor( 292 | inner: T, 293 | interceptor: F, 294 | ) -> GeofancyServiceClient> 295 | where 296 | F: tonic::service::Interceptor, 297 | T::ResponseBody: Default, 298 | T: tonic::codegen::Service< 299 | http::Request, 300 | Response = http::Response< 301 | >::ResponseBody, 302 | >, 303 | >, 304 | , 306 | >>::Error: Into + Send + Sync, 307 | { 308 | GeofancyServiceClient::new(InterceptedService::new(inner, interceptor)) 309 | } 310 | /// Compress requests with the given encoding. 311 | /// 312 | /// This requires the server to support it otherwise it might respond with an 313 | /// error. 314 | #[must_use] 315 | pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { 316 | self.inner = self.inner.send_compressed(encoding); 317 | self 318 | } 319 | /// Enable decompressing responses. 320 | #[must_use] 321 | pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { 322 | self.inner = self.inner.accept_compressed(encoding); 323 | self 324 | } 325 | /// Limits the maximum size of a decoded message. 326 | /// 327 | /// Default: `4MB` 328 | #[must_use] 329 | pub fn max_decoding_message_size(mut self, limit: usize) -> Self { 330 | self.inner = self.inner.max_decoding_message_size(limit); 331 | self 332 | } 333 | /// Limits the maximum size of an encoded message. 334 | /// 335 | /// Default: `usize::MAX` 336 | #[must_use] 337 | pub fn max_encoding_message_size(mut self, limit: usize) -> Self { 338 | self.inner = self.inner.max_encoding_message_size(limit); 339 | self 340 | } 341 | /// CUD on entries 342 | pub async fn create_web_hook( 343 | &mut self, 344 | request: impl tonic::IntoRequest, 345 | ) -> std::result::Result, tonic::Status> { 346 | self.inner 347 | .ready() 348 | .await 349 | .map_err(|e| { 350 | tonic::Status::new( 351 | tonic::Code::Unknown, 352 | format!("Service was not ready: {}", e.into()), 353 | ) 354 | })?; 355 | let codec = tonic::codec::ProstCodec::default(); 356 | let path = http::uri::PathAndQuery::from_static( 357 | "/geofancy.GeofancyService/CreateWebHook", 358 | ); 359 | let mut req = request.into_request(); 360 | req.extensions_mut() 361 | .insert(GrpcMethod::new("geofancy.GeofancyService", "CreateWebHook")); 362 | self.inner.unary(req, path, codec).await 363 | } 364 | pub async fn delete_web_hook( 365 | &mut self, 366 | request: impl tonic::IntoRequest, 367 | ) -> std::result::Result, tonic::Status> { 368 | self.inner 369 | .ready() 370 | .await 371 | .map_err(|e| { 372 | tonic::Status::new( 373 | tonic::Code::Unknown, 374 | format!("Service was not ready: {}", e.into()), 375 | ) 376 | })?; 377 | let codec = tonic::codec::ProstCodec::default(); 378 | let path = http::uri::PathAndQuery::from_static( 379 | "/geofancy.GeofancyService/DeleteWebHook", 380 | ); 381 | let mut req = request.into_request(); 382 | req.extensions_mut() 383 | .insert(GrpcMethod::new("geofancy.GeofancyService", "DeleteWebHook")); 384 | self.inner.unary(req, path, codec).await 385 | } 386 | pub async fn set_document( 387 | &mut self, 388 | request: impl tonic::IntoRequest, 389 | ) -> std::result::Result, tonic::Status> { 390 | self.inner 391 | .ready() 392 | .await 393 | .map_err(|e| { 394 | tonic::Status::new( 395 | tonic::Code::Unknown, 396 | format!("Service was not ready: {}", e.into()), 397 | ) 398 | })?; 399 | let codec = tonic::codec::ProstCodec::default(); 400 | let path = http::uri::PathAndQuery::from_static( 401 | "/geofancy.GeofancyService/SetDocument", 402 | ); 403 | let mut req = request.into_request(); 404 | req.extensions_mut() 405 | .insert(GrpcMethod::new("geofancy.GeofancyService", "SetDocument")); 406 | self.inner.unary(req, path, codec).await 407 | } 408 | pub async fn delete_document( 409 | &mut self, 410 | request: impl tonic::IntoRequest, 411 | ) -> std::result::Result, tonic::Status> { 412 | self.inner 413 | .ready() 414 | .await 415 | .map_err(|e| { 416 | tonic::Status::new( 417 | tonic::Code::Unknown, 418 | format!("Service was not ready: {}", e.into()), 419 | ) 420 | })?; 421 | let codec = tonic::codec::ProstCodec::default(); 422 | let path = http::uri::PathAndQuery::from_static( 423 | "/geofancy.GeofancyService/DeleteDocument", 424 | ); 425 | let mut req = request.into_request(); 426 | req.extensions_mut() 427 | .insert(GrpcMethod::new("geofancy.GeofancyService", "DeleteDocument")); 428 | self.inner.unary(req, path, codec).await 429 | } 430 | pub async fn delete_collection( 431 | &mut self, 432 | request: impl tonic::IntoRequest, 433 | ) -> std::result::Result, tonic::Status> { 434 | self.inner 435 | .ready() 436 | .await 437 | .map_err(|e| { 438 | tonic::Status::new( 439 | tonic::Code::Unknown, 440 | format!("Service was not ready: {}", e.into()), 441 | ) 442 | })?; 443 | let codec = tonic::codec::ProstCodec::default(); 444 | let path = http::uri::PathAndQuery::from_static( 445 | "/geofancy.GeofancyService/DeleteCollection", 446 | ); 447 | let mut req = request.into_request(); 448 | req.extensions_mut() 449 | .insert(GrpcMethod::new("geofancy.GeofancyService", "DeleteCollection")); 450 | self.inner.unary(req, path, codec).await 451 | } 452 | } 453 | } 454 | /// Generated server implementations. 455 | pub mod geofancy_service_server { 456 | #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] 457 | use tonic::codegen::*; 458 | /// Generated trait containing gRPC methods that should be implemented for use with GeofancyServiceServer. 459 | #[async_trait] 460 | pub trait GeofancyService: Send + Sync + 'static { 461 | /// CUD on entries 462 | async fn create_web_hook( 463 | &self, 464 | request: tonic::Request, 465 | ) -> std::result::Result, tonic::Status>; 466 | async fn delete_web_hook( 467 | &self, 468 | request: tonic::Request, 469 | ) -> std::result::Result, tonic::Status>; 470 | async fn set_document( 471 | &self, 472 | request: tonic::Request, 473 | ) -> std::result::Result, tonic::Status>; 474 | async fn delete_document( 475 | &self, 476 | request: tonic::Request, 477 | ) -> std::result::Result, tonic::Status>; 478 | async fn delete_collection( 479 | &self, 480 | request: tonic::Request, 481 | ) -> std::result::Result, tonic::Status>; 482 | } 483 | #[derive(Debug)] 484 | pub struct GeofancyServiceServer { 485 | inner: _Inner, 486 | accept_compression_encodings: EnabledCompressionEncodings, 487 | send_compression_encodings: EnabledCompressionEncodings, 488 | max_decoding_message_size: Option, 489 | max_encoding_message_size: Option, 490 | } 491 | struct _Inner(Arc); 492 | impl GeofancyServiceServer { 493 | pub fn new(inner: T) -> Self { 494 | Self::from_arc(Arc::new(inner)) 495 | } 496 | pub fn from_arc(inner: Arc) -> Self { 497 | let inner = _Inner(inner); 498 | Self { 499 | inner, 500 | accept_compression_encodings: Default::default(), 501 | send_compression_encodings: Default::default(), 502 | max_decoding_message_size: None, 503 | max_encoding_message_size: None, 504 | } 505 | } 506 | pub fn with_interceptor( 507 | inner: T, 508 | interceptor: F, 509 | ) -> InterceptedService 510 | where 511 | F: tonic::service::Interceptor, 512 | { 513 | InterceptedService::new(Self::new(inner), interceptor) 514 | } 515 | /// Enable decompressing requests with the given encoding. 516 | #[must_use] 517 | pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { 518 | self.accept_compression_encodings.enable(encoding); 519 | self 520 | } 521 | /// Compress responses with the given encoding, if the client supports it. 522 | #[must_use] 523 | pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { 524 | self.send_compression_encodings.enable(encoding); 525 | self 526 | } 527 | /// Limits the maximum size of a decoded message. 528 | /// 529 | /// Default: `4MB` 530 | #[must_use] 531 | pub fn max_decoding_message_size(mut self, limit: usize) -> Self { 532 | self.max_decoding_message_size = Some(limit); 533 | self 534 | } 535 | /// Limits the maximum size of an encoded message. 536 | /// 537 | /// Default: `usize::MAX` 538 | #[must_use] 539 | pub fn max_encoding_message_size(mut self, limit: usize) -> Self { 540 | self.max_encoding_message_size = Some(limit); 541 | self 542 | } 543 | } 544 | impl tonic::codegen::Service> for GeofancyServiceServer 545 | where 546 | T: GeofancyService, 547 | B: Body + Send + 'static, 548 | B::Error: Into + Send + 'static, 549 | { 550 | type Response = http::Response; 551 | type Error = std::convert::Infallible; 552 | type Future = BoxFuture; 553 | fn poll_ready( 554 | &mut self, 555 | _cx: &mut Context<'_>, 556 | ) -> Poll> { 557 | Poll::Ready(Ok(())) 558 | } 559 | fn call(&mut self, req: http::Request) -> Self::Future { 560 | let inner = self.inner.clone(); 561 | match req.uri().path() { 562 | "/geofancy.GeofancyService/CreateWebHook" => { 563 | #[allow(non_camel_case_types)] 564 | struct CreateWebHookSvc(pub Arc); 565 | impl tonic::server::UnaryService 566 | for CreateWebHookSvc { 567 | type Response = super::CommandResult; 568 | type Future = BoxFuture< 569 | tonic::Response, 570 | tonic::Status, 571 | >; 572 | fn call( 573 | &mut self, 574 | request: tonic::Request, 575 | ) -> Self::Future { 576 | let inner = Arc::clone(&self.0); 577 | let fut = async move { 578 | ::create_web_hook(&inner, request) 579 | .await 580 | }; 581 | Box::pin(fut) 582 | } 583 | } 584 | let accept_compression_encodings = self.accept_compression_encodings; 585 | let send_compression_encodings = self.send_compression_encodings; 586 | let max_decoding_message_size = self.max_decoding_message_size; 587 | let max_encoding_message_size = self.max_encoding_message_size; 588 | let inner = self.inner.clone(); 589 | let fut = async move { 590 | let inner = inner.0; 591 | let method = CreateWebHookSvc(inner); 592 | let codec = tonic::codec::ProstCodec::default(); 593 | let mut grpc = tonic::server::Grpc::new(codec) 594 | .apply_compression_config( 595 | accept_compression_encodings, 596 | send_compression_encodings, 597 | ) 598 | .apply_max_message_size_config( 599 | max_decoding_message_size, 600 | max_encoding_message_size, 601 | ); 602 | let res = grpc.unary(method, req).await; 603 | Ok(res) 604 | }; 605 | Box::pin(fut) 606 | } 607 | "/geofancy.GeofancyService/DeleteWebHook" => { 608 | #[allow(non_camel_case_types)] 609 | struct DeleteWebHookSvc(pub Arc); 610 | impl< 611 | T: GeofancyService, 612 | > tonic::server::UnaryService 613 | for DeleteWebHookSvc { 614 | type Response = super::CommandResult; 615 | type Future = BoxFuture< 616 | tonic::Response, 617 | tonic::Status, 618 | >; 619 | fn call( 620 | &mut self, 621 | request: tonic::Request, 622 | ) -> Self::Future { 623 | let inner = Arc::clone(&self.0); 624 | let fut = async move { 625 | ::delete_web_hook(&inner, request) 626 | .await 627 | }; 628 | Box::pin(fut) 629 | } 630 | } 631 | let accept_compression_encodings = self.accept_compression_encodings; 632 | let send_compression_encodings = self.send_compression_encodings; 633 | let max_decoding_message_size = self.max_decoding_message_size; 634 | let max_encoding_message_size = self.max_encoding_message_size; 635 | let inner = self.inner.clone(); 636 | let fut = async move { 637 | let inner = inner.0; 638 | let method = DeleteWebHookSvc(inner); 639 | let codec = tonic::codec::ProstCodec::default(); 640 | let mut grpc = tonic::server::Grpc::new(codec) 641 | .apply_compression_config( 642 | accept_compression_encodings, 643 | send_compression_encodings, 644 | ) 645 | .apply_max_message_size_config( 646 | max_decoding_message_size, 647 | max_encoding_message_size, 648 | ); 649 | let res = grpc.unary(method, req).await; 650 | Ok(res) 651 | }; 652 | Box::pin(fut) 653 | } 654 | "/geofancy.GeofancyService/SetDocument" => { 655 | #[allow(non_camel_case_types)] 656 | struct SetDocumentSvc(pub Arc); 657 | impl tonic::server::UnaryService 658 | for SetDocumentSvc { 659 | type Response = super::CommandResult; 660 | type Future = BoxFuture< 661 | tonic::Response, 662 | tonic::Status, 663 | >; 664 | fn call( 665 | &mut self, 666 | request: tonic::Request, 667 | ) -> Self::Future { 668 | let inner = Arc::clone(&self.0); 669 | let fut = async move { 670 | ::set_document(&inner, request).await 671 | }; 672 | Box::pin(fut) 673 | } 674 | } 675 | let accept_compression_encodings = self.accept_compression_encodings; 676 | let send_compression_encodings = self.send_compression_encodings; 677 | let max_decoding_message_size = self.max_decoding_message_size; 678 | let max_encoding_message_size = self.max_encoding_message_size; 679 | let inner = self.inner.clone(); 680 | let fut = async move { 681 | let inner = inner.0; 682 | let method = SetDocumentSvc(inner); 683 | let codec = tonic::codec::ProstCodec::default(); 684 | let mut grpc = tonic::server::Grpc::new(codec) 685 | .apply_compression_config( 686 | accept_compression_encodings, 687 | send_compression_encodings, 688 | ) 689 | .apply_max_message_size_config( 690 | max_decoding_message_size, 691 | max_encoding_message_size, 692 | ); 693 | let res = grpc.unary(method, req).await; 694 | Ok(res) 695 | }; 696 | Box::pin(fut) 697 | } 698 | "/geofancy.GeofancyService/DeleteDocument" => { 699 | #[allow(non_camel_case_types)] 700 | struct DeleteDocumentSvc(pub Arc); 701 | impl tonic::server::UnaryService 702 | for DeleteDocumentSvc { 703 | type Response = super::CommandResult; 704 | type Future = BoxFuture< 705 | tonic::Response, 706 | tonic::Status, 707 | >; 708 | fn call( 709 | &mut self, 710 | request: tonic::Request, 711 | ) -> Self::Future { 712 | let inner = Arc::clone(&self.0); 713 | let fut = async move { 714 | ::delete_document(&inner, request) 715 | .await 716 | }; 717 | Box::pin(fut) 718 | } 719 | } 720 | let accept_compression_encodings = self.accept_compression_encodings; 721 | let send_compression_encodings = self.send_compression_encodings; 722 | let max_decoding_message_size = self.max_decoding_message_size; 723 | let max_encoding_message_size = self.max_encoding_message_size; 724 | let inner = self.inner.clone(); 725 | let fut = async move { 726 | let inner = inner.0; 727 | let method = DeleteDocumentSvc(inner); 728 | let codec = tonic::codec::ProstCodec::default(); 729 | let mut grpc = tonic::server::Grpc::new(codec) 730 | .apply_compression_config( 731 | accept_compression_encodings, 732 | send_compression_encodings, 733 | ) 734 | .apply_max_message_size_config( 735 | max_decoding_message_size, 736 | max_encoding_message_size, 737 | ); 738 | let res = grpc.unary(method, req).await; 739 | Ok(res) 740 | }; 741 | Box::pin(fut) 742 | } 743 | "/geofancy.GeofancyService/DeleteCollection" => { 744 | #[allow(non_camel_case_types)] 745 | struct DeleteCollectionSvc(pub Arc); 746 | impl tonic::server::UnaryService 747 | for DeleteCollectionSvc { 748 | type Response = super::CommandResult; 749 | type Future = BoxFuture< 750 | tonic::Response, 751 | tonic::Status, 752 | >; 753 | fn call( 754 | &mut self, 755 | request: tonic::Request, 756 | ) -> Self::Future { 757 | let inner = Arc::clone(&self.0); 758 | let fut = async move { 759 | ::delete_collection(&inner, request) 760 | .await 761 | }; 762 | Box::pin(fut) 763 | } 764 | } 765 | let accept_compression_encodings = self.accept_compression_encodings; 766 | let send_compression_encodings = self.send_compression_encodings; 767 | let max_decoding_message_size = self.max_decoding_message_size; 768 | let max_encoding_message_size = self.max_encoding_message_size; 769 | let inner = self.inner.clone(); 770 | let fut = async move { 771 | let inner = inner.0; 772 | let method = DeleteCollectionSvc(inner); 773 | let codec = tonic::codec::ProstCodec::default(); 774 | let mut grpc = tonic::server::Grpc::new(codec) 775 | .apply_compression_config( 776 | accept_compression_encodings, 777 | send_compression_encodings, 778 | ) 779 | .apply_max_message_size_config( 780 | max_decoding_message_size, 781 | max_encoding_message_size, 782 | ); 783 | let res = grpc.unary(method, req).await; 784 | Ok(res) 785 | }; 786 | Box::pin(fut) 787 | } 788 | _ => { 789 | Box::pin(async move { 790 | Ok( 791 | http::Response::builder() 792 | .status(200) 793 | .header("grpc-status", "12") 794 | .header("content-type", "application/grpc") 795 | .body(empty_body()) 796 | .unwrap(), 797 | ) 798 | }) 799 | } 800 | } 801 | } 802 | } 803 | impl Clone for GeofancyServiceServer { 804 | fn clone(&self) -> Self { 805 | let inner = self.inner.clone(); 806 | Self { 807 | inner, 808 | accept_compression_encodings: self.accept_compression_encodings, 809 | send_compression_encodings: self.send_compression_encodings, 810 | max_decoding_message_size: self.max_decoding_message_size, 811 | max_encoding_message_size: self.max_encoding_message_size, 812 | } 813 | } 814 | } 815 | impl Clone for _Inner { 816 | fn clone(&self) -> Self { 817 | Self(Arc::clone(&self.0)) 818 | } 819 | } 820 | impl std::fmt::Debug for _Inner { 821 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 822 | write!(f, "{:?}", self.0) 823 | } 824 | } 825 | impl tonic::server::NamedService for GeofancyServiceServer { 826 | const NAME: &'static str = "geofancy.GeofancyService"; 827 | } 828 | } 829 | -------------------------------------------------------------------------------- /src/geofancy_server.rs: -------------------------------------------------------------------------------- 1 | 2 | use tonic::{Request, Response, Status}; 3 | 4 | 5 | use crate::geofancy::*; 6 | use crate::tile38_client::*; 7 | 8 | #[derive(Clone)] 9 | pub struct GeofancyImpl {} 10 | 11 | #[tonic::async_trait] 12 | impl geofancy_service_server::GeofancyService for GeofancyImpl { 13 | async fn create_web_hook( 14 | &self, 15 | request: Request, 16 | ) -> Result, Status> { 17 | set_webhook(request.into_inner()) 18 | .await 19 | .map(Response::new) 20 | .map_err(|e| Status::internal(e.to_string())) 21 | } 22 | 23 | async fn delete_web_hook( 24 | &self, 25 | request: Request, 26 | ) -> Result, Status> { 27 | delete_webhook(request.into_inner()) 28 | .await 29 | .map(Response::new) 30 | .map_err(|e| Status::internal(e.to_string())) 31 | } 32 | 33 | async fn set_document( 34 | &self, 35 | request: Request, 36 | ) -> Result, Status> { 37 | let doc = request.into_inner(); 38 | let id = &doc.id; 39 | let collection = &doc.collection; 40 | 41 | match doc.geo.unwrap() { 42 | document::Geo::Bounds(_bounds) => { 43 | unimplemented!() 44 | } 45 | document::Geo::Geojson(_geo_json) => { 46 | unimplemented!() 47 | } 48 | document::Geo::Line(_line) => { 49 | unimplemented!() 50 | } 51 | document::Geo::Point(point) => set_point(collection, id, point) 52 | .await 53 | .map(Response::new) 54 | .map_err(|e| Status::internal(e.to_string())), 55 | } 56 | } 57 | 58 | async fn delete_document( 59 | &self, 60 | request: Request, 61 | ) -> Result, Status> { 62 | let doc = request.into_inner(); 63 | delete_document(&doc.collection, &doc.id) 64 | .await 65 | .map(Response::new) 66 | .map_err(|e| Status::internal(e.to_string())) 67 | } 68 | 69 | async fn delete_collection( 70 | &self, 71 | request: Request, 72 | ) -> Result, Status> { 73 | let doc = request.into_inner(); 74 | delete_collection(&doc.collection) 75 | .await 76 | .map(Response::new) 77 | .map_err(|e| Status::internal(e.to_string())) 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | use tonic::transport::Server; 4 | 5 | use dotenv::dotenv; 6 | 7 | use geofancy_server::GeofancyImpl; 8 | 9 | #[tokio::main] 10 | async fn main() -> Result<(), Box> { 11 | let _ = dotenv(); 12 | 13 | let grpc_uri = env::var("GRPC_SERVER_URI")?; 14 | 15 | let handler = GeofancyImpl {}; 16 | 17 | let addr = &grpc_uri.parse().unwrap(); 18 | let new_service = geofancy::geofancy_service_server::GeofancyServiceServer::new(handler); 19 | 20 | println!("listening on {:?}", addr); 21 | 22 | Server::builder() 23 | .add_service(new_service) 24 | .serve(*addr) 25 | .await?; 26 | 27 | Ok(()) 28 | } 29 | 30 | mod geofancy; 31 | mod geofancy_server; 32 | mod tile38_client; 33 | -------------------------------------------------------------------------------- /src/tile38_client.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | 3 | use redis::RedisError; 4 | 5 | use crate::geofancy::{self, *}; 6 | 7 | async fn connect() -> Result { 8 | let host = env::var("TILE38_CONNECTION").unwrap(); 9 | redis::Client::open(host.as_str())? 10 | .get_multiplexed_async_connection_with_timeouts( 11 | std::time::Duration::from_secs(5), 12 | std::time::Duration::from_secs(5), 13 | ) 14 | .await 15 | } 16 | 17 | pub async fn set_point( 18 | collection: &str, 19 | id: &str, 20 | point: Point, 21 | ) -> Result { 22 | let mut connection = connect().await?; 23 | 24 | let coordinates = point.coord.unwrap(); 25 | 26 | redis::cmd("SET") 27 | .arg(collection) 28 | .arg(id) 29 | .arg("POINT") 30 | .arg(coordinates.lat) 31 | .arg(coordinates.lng) 32 | .query_async(&mut connection) 33 | .await?; 34 | 35 | let success = CommandResult { 36 | status: 0, 37 | ..Default::default() 38 | }; 39 | 40 | Ok(success) 41 | } 42 | 43 | pub async fn set_webhook(geofence: GeoFence) -> Result { 44 | let mut connection = connect().await?; 45 | 46 | let mut q = redis::cmd("SETHOOK"); 47 | q.arg(geofence.id.as_str()).arg(geofence.endpoint.as_str()); 48 | 49 | match geofence.query.clone().unwrap() { 50 | geofancy::geo_fence::Query::Nearby(x) => { 51 | q.arg("NEARBY").arg(x.collection); 52 | } 53 | _ => { 54 | unimplemented!() 55 | } 56 | } 57 | 58 | q.arg("MATCH").arg(geofence.r#match.as_str()).arg("FENCE"); 59 | 60 | // detect 61 | let detect: Vec<&str> = geofence 62 | .detect 63 | .clone() 64 | .into_iter() 65 | .map(|d| match d { 66 | 0 => "INSIDE", 67 | 1 => "OUTSIDE", 68 | 2 => "ENTER", 69 | 3 => "EXIT", 70 | 4 => "CROSS", 71 | _ => "", 72 | }) 73 | .collect(); 74 | 75 | if !detect.is_empty() { 76 | let mut detect_str: Vec<&str> = Vec::new(); 77 | 78 | for x in detect { 79 | detect_str.push(x); 80 | } 81 | q.arg("DETECT").arg(detect_str.as_slice().join(",")); 82 | } 83 | 84 | // commands 85 | let commands: Vec<&str> = geofence 86 | .commands 87 | .clone() 88 | .into_iter() 89 | .map(|c| match c { 90 | 0 => "SET", 91 | 1 => "DEL", 92 | 2 => "DROP", 93 | _ => "", 94 | }) 95 | .collect(); 96 | 97 | if !commands.is_empty() { 98 | let mut commands_str: Vec<&str> = Vec::new(); 99 | 100 | commands_str.push(""); 101 | 102 | for x in commands { 103 | commands_str.push(x); 104 | } 105 | q.arg("COMMANDS").arg(commands_str.as_slice().join(",")); 106 | } 107 | 108 | let point = geofence.point.unwrap(); 109 | let coordinate = &point.coord.unwrap(); 110 | 111 | q.arg("POINT") 112 | .arg(coordinate.lat) 113 | .arg(coordinate.lng) 114 | .arg(geofence.distance); 115 | 116 | q.query_async(&mut connection).await?; 117 | 118 | let success = CommandResult { 119 | status: 0, 120 | ..Default::default() 121 | }; 122 | 123 | Ok(success) 124 | } 125 | 126 | pub async fn delete_webhook(search_string: SearchString) -> Result { 127 | let mut connection = connect().await?; 128 | 129 | redis::cmd("PDELHOOK") 130 | .arg(search_string.value) 131 | .query_async(&mut connection) 132 | .await?; 133 | 134 | let success = CommandResult { 135 | status: 0, 136 | ..Default::default() 137 | }; 138 | 139 | Ok(success) 140 | } 141 | 142 | pub async fn delete_document(collection: &str, id: &str) -> Result { 143 | let mut connection = connect().await?; 144 | 145 | redis::cmd("DEL") 146 | .arg(collection) 147 | .arg(id) 148 | .query_async(&mut connection) 149 | .await?; 150 | 151 | let success = CommandResult { 152 | status: 0, 153 | ..Default::default() 154 | }; 155 | 156 | Ok(success) 157 | } 158 | 159 | pub async fn delete_collection(collection: &str) -> Result { 160 | let mut connection = connect().await?; 161 | 162 | redis::cmd("DROP") 163 | .arg(collection) 164 | .query_async(&mut connection) 165 | .await?; 166 | 167 | let success = CommandResult { 168 | status: 0, 169 | ..Default::default() 170 | }; 171 | 172 | Ok(success) 173 | } 174 | 175 | #[cfg(test)] 176 | mod tests { 177 | use super::*; 178 | 179 | #[tokio::test] 180 | async fn set_point_test() { 181 | env::set_var("TILE38_CONNECTION", "redis://tile38-tile38:9851/0"); 182 | let point = Point { 183 | coord: Some(Coordinate { 184 | lat: 12.355, 185 | lng: -26.215, 186 | }), 187 | }; 188 | let result = set_point("test-collection", "test-id", point).await; 189 | // println!("{:?}", point); 190 | match result { 191 | Ok(result) => { 192 | assert!(result.status == 0); 193 | } 194 | Err(_e) => {} 195 | } 196 | } 197 | } 198 | --------------------------------------------------------------------------------