├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── docker-compose.yml └── src ├── bin ├── client.rs └── server.rs ├── cache.rs ├── kafka.rs └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "actix" 5 | version = "0.9.0" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | checksum = "a4af87564ff659dee8f9981540cac9418c45e910c8072fdedd643a262a38fcaf" 8 | dependencies = [ 9 | "actix-http", 10 | "actix-rt", 11 | "actix_derive", 12 | "bitflags", 13 | "bytes", 14 | "crossbeam-channel", 15 | "derive_more", 16 | "futures 0.3.5", 17 | "lazy_static", 18 | "log", 19 | "parking_lot", 20 | "pin-project", 21 | "smallvec", 22 | "tokio", 23 | "tokio-util 0.2.0", 24 | "trust-dns-proto", 25 | "trust-dns-resolver", 26 | ] 27 | 28 | [[package]] 29 | name = "actix-codec" 30 | version = "0.2.0" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | checksum = "09e55f0a5c2ca15795035d90c46bd0e73a5123b72f68f12596d6ba5282051380" 33 | dependencies = [ 34 | "bitflags", 35 | "bytes", 36 | "futures-core", 37 | "futures-sink", 38 | "log", 39 | "tokio", 40 | "tokio-util 0.2.0", 41 | ] 42 | 43 | [[package]] 44 | name = "actix-connect" 45 | version = "1.0.2" 46 | source = "registry+https://github.com/rust-lang/crates.io-index" 47 | checksum = "c95cc9569221e9802bf4c377f6c18b90ef10227d787611decf79fd47d2a8e76c" 48 | dependencies = [ 49 | "actix-codec", 50 | "actix-rt", 51 | "actix-service", 52 | "actix-utils", 53 | "derive_more", 54 | "either", 55 | "futures 0.3.5", 56 | "http", 57 | "log", 58 | "trust-dns-proto", 59 | "trust-dns-resolver", 60 | ] 61 | 62 | [[package]] 63 | name = "actix-http" 64 | version = "1.0.1" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "c16664cc4fdea8030837ad5a845eb231fb93fc3c5c171edfefb52fad92ce9019" 67 | dependencies = [ 68 | "actix-codec", 69 | "actix-connect", 70 | "actix-rt", 71 | "actix-service", 72 | "actix-threadpool", 73 | "actix-utils", 74 | "base64", 75 | "bitflags", 76 | "brotli2", 77 | "bytes", 78 | "chrono", 79 | "copyless", 80 | "derive_more", 81 | "either", 82 | "encoding_rs", 83 | "failure", 84 | "flate2", 85 | "futures-channel", 86 | "futures-core", 87 | "futures-util", 88 | "fxhash", 89 | "h2", 90 | "http", 91 | "httparse", 92 | "indexmap", 93 | "language-tags", 94 | "lazy_static", 95 | "log", 96 | "mime", 97 | "percent-encoding", 98 | "pin-project", 99 | "rand", 100 | "regex", 101 | "serde", 102 | "serde_json", 103 | "serde_urlencoded", 104 | "sha1", 105 | "slab", 106 | "time", 107 | ] 108 | 109 | [[package]] 110 | name = "actix-macros" 111 | version = "0.1.2" 112 | source = "registry+https://github.com/rust-lang/crates.io-index" 113 | checksum = "a60f9ba7c4e6df97f3aacb14bb5c0cd7d98a49dcbaed0d7f292912ad9a6a3ed2" 114 | dependencies = [ 115 | "quote", 116 | "syn", 117 | ] 118 | 119 | [[package]] 120 | name = "actix-router" 121 | version = "0.2.4" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "9d7a10ca4d94e8c8e7a87c5173aba1b97ba9a6563ca02b0e1cd23531093d3ec8" 124 | dependencies = [ 125 | "bytestring", 126 | "http", 127 | "log", 128 | "regex", 129 | "serde", 130 | ] 131 | 132 | [[package]] 133 | name = "actix-rt" 134 | version = "1.1.1" 135 | source = "registry+https://github.com/rust-lang/crates.io-index" 136 | checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227" 137 | dependencies = [ 138 | "actix-macros", 139 | "actix-threadpool", 140 | "copyless", 141 | "futures-channel", 142 | "futures-util", 143 | "smallvec", 144 | "tokio", 145 | ] 146 | 147 | [[package]] 148 | name = "actix-server" 149 | version = "1.0.3" 150 | source = "registry+https://github.com/rust-lang/crates.io-index" 151 | checksum = "e6d74b464215a473c973a2d7d03a69cc10f4ce1f4b38a7659c5193dc5c675630" 152 | dependencies = [ 153 | "actix-codec", 154 | "actix-rt", 155 | "actix-service", 156 | "actix-utils", 157 | "futures-channel", 158 | "futures-util", 159 | "log", 160 | "mio", 161 | "mio-uds", 162 | "num_cpus", 163 | "slab", 164 | "socket2", 165 | ] 166 | 167 | [[package]] 168 | name = "actix-service" 169 | version = "1.0.5" 170 | source = "registry+https://github.com/rust-lang/crates.io-index" 171 | checksum = "d3e4fc95dfa7e24171b2d0bb46b85f8ab0e8499e4e3caec691fc4ea65c287564" 172 | dependencies = [ 173 | "futures-util", 174 | "pin-project", 175 | ] 176 | 177 | [[package]] 178 | name = "actix-testing" 179 | version = "1.0.1" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c" 182 | dependencies = [ 183 | "actix-macros", 184 | "actix-rt", 185 | "actix-server", 186 | "actix-service", 187 | "log", 188 | "socket2", 189 | ] 190 | 191 | [[package]] 192 | name = "actix-threadpool" 193 | version = "0.3.2" 194 | source = "registry+https://github.com/rust-lang/crates.io-index" 195 | checksum = "91164716d956745c79dcea5e66d2aa04506549958accefcede5368c70f2fd4ff" 196 | dependencies = [ 197 | "derive_more", 198 | "futures-channel", 199 | "lazy_static", 200 | "log", 201 | "num_cpus", 202 | "parking_lot", 203 | "threadpool", 204 | ] 205 | 206 | [[package]] 207 | name = "actix-tls" 208 | version = "1.0.0" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "a4e5b4faaf105e9a6d389c606c298dcdb033061b00d532af9df56ff3a54995a8" 211 | dependencies = [ 212 | "actix-codec", 213 | "actix-rt", 214 | "actix-service", 215 | "actix-utils", 216 | "derive_more", 217 | "either", 218 | "futures 0.3.5", 219 | "log", 220 | ] 221 | 222 | [[package]] 223 | name = "actix-utils" 224 | version = "1.0.6" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "fcf8f5631bf01adec2267808f00e228b761c60c0584cc9fa0b5364f41d147f4e" 227 | dependencies = [ 228 | "actix-codec", 229 | "actix-rt", 230 | "actix-service", 231 | "bitflags", 232 | "bytes", 233 | "either", 234 | "futures 0.3.5", 235 | "log", 236 | "pin-project", 237 | "slab", 238 | ] 239 | 240 | [[package]] 241 | name = "actix-web" 242 | version = "2.0.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "3158e822461040822f0dbf1735b9c2ce1f95f93b651d7a7aded00b1efbb1f635" 245 | dependencies = [ 246 | "actix-codec", 247 | "actix-http", 248 | "actix-macros", 249 | "actix-router", 250 | "actix-rt", 251 | "actix-server", 252 | "actix-service", 253 | "actix-testing", 254 | "actix-threadpool", 255 | "actix-tls", 256 | "actix-utils", 257 | "actix-web-codegen", 258 | "awc", 259 | "bytes", 260 | "derive_more", 261 | "encoding_rs", 262 | "futures 0.3.5", 263 | "fxhash", 264 | "log", 265 | "mime", 266 | "net2", 267 | "pin-project", 268 | "regex", 269 | "serde", 270 | "serde_json", 271 | "serde_urlencoded", 272 | "time", 273 | "url", 274 | ] 275 | 276 | [[package]] 277 | name = "actix-web-codegen" 278 | version = "0.2.2" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "a71bf475cbe07281d0b3696abb48212db118e7e23219f13596ce865235ff5766" 281 | dependencies = [ 282 | "proc-macro2", 283 | "quote", 284 | "syn", 285 | ] 286 | 287 | [[package]] 288 | name = "actix_derive" 289 | version = "0.5.0" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c" 292 | dependencies = [ 293 | "proc-macro2", 294 | "quote", 295 | "syn", 296 | ] 297 | 298 | [[package]] 299 | name = "addr2line" 300 | version = "0.12.1" 301 | source = "registry+https://github.com/rust-lang/crates.io-index" 302 | checksum = "a49806b9dadc843c61e7c97e72490ad7f7220ae249012fbda9ad0609457c0543" 303 | dependencies = [ 304 | "gimli", 305 | ] 306 | 307 | [[package]] 308 | name = "adler32" 309 | version = "1.0.4" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" 312 | 313 | [[package]] 314 | name = "aho-corasick" 315 | version = "0.7.10" 316 | source = "registry+https://github.com/rust-lang/crates.io-index" 317 | checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" 318 | dependencies = [ 319 | "memchr", 320 | ] 321 | 322 | [[package]] 323 | name = "arc-swap" 324 | version = "0.4.7" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034" 327 | 328 | [[package]] 329 | name = "ascii" 330 | version = "0.9.3" 331 | source = "registry+https://github.com/rust-lang/crates.io-index" 332 | checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" 333 | 334 | [[package]] 335 | name = "async-trait" 336 | version = "0.1.35" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "89cb5d814ab2a47fd66d3266e9efccb53ca4c740b7451043b8ffcf9a6208f3f8" 339 | dependencies = [ 340 | "proc-macro2", 341 | "quote", 342 | "syn", 343 | ] 344 | 345 | [[package]] 346 | name = "atty" 347 | version = "0.2.14" 348 | source = "registry+https://github.com/rust-lang/crates.io-index" 349 | checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" 350 | dependencies = [ 351 | "hermit-abi", 352 | "libc", 353 | "winapi 0.3.8", 354 | ] 355 | 356 | [[package]] 357 | name = "autocfg" 358 | version = "1.0.0" 359 | source = "registry+https://github.com/rust-lang/crates.io-index" 360 | checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" 361 | 362 | [[package]] 363 | name = "awc" 364 | version = "1.0.1" 365 | source = "registry+https://github.com/rust-lang/crates.io-index" 366 | checksum = "d7601d4d1d7ef2335d6597a41b5fe069f6ab799b85f53565ab390e7b7065aac5" 367 | dependencies = [ 368 | "actix-codec", 369 | "actix-http", 370 | "actix-rt", 371 | "actix-service", 372 | "base64", 373 | "bytes", 374 | "derive_more", 375 | "futures-core", 376 | "log", 377 | "mime", 378 | "percent-encoding", 379 | "rand", 380 | "serde", 381 | "serde_json", 382 | "serde_urlencoded", 383 | ] 384 | 385 | [[package]] 386 | name = "backtrace" 387 | version = "0.3.48" 388 | source = "registry+https://github.com/rust-lang/crates.io-index" 389 | checksum = "0df2f85c8a2abbe3b7d7e748052fdd9b76a0458fdeb16ad4223f5eca78c7c130" 390 | dependencies = [ 391 | "addr2line", 392 | "cfg-if", 393 | "libc", 394 | "object", 395 | "rustc-demangle", 396 | ] 397 | 398 | [[package]] 399 | name = "base64" 400 | version = "0.11.0" 401 | source = "registry+https://github.com/rust-lang/crates.io-index" 402 | checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" 403 | 404 | [[package]] 405 | name = "bitflags" 406 | version = "1.2.1" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" 409 | 410 | [[package]] 411 | name = "brotli-sys" 412 | version = "0.3.2" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" 415 | dependencies = [ 416 | "cc", 417 | "libc", 418 | ] 419 | 420 | [[package]] 421 | name = "brotli2" 422 | version = "0.3.2" 423 | source = "registry+https://github.com/rust-lang/crates.io-index" 424 | checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" 425 | dependencies = [ 426 | "brotli-sys", 427 | "libc", 428 | ] 429 | 430 | [[package]] 431 | name = "byteorder" 432 | version = "1.3.4" 433 | source = "registry+https://github.com/rust-lang/crates.io-index" 434 | checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" 435 | 436 | [[package]] 437 | name = "bytes" 438 | version = "0.5.4" 439 | source = "registry+https://github.com/rust-lang/crates.io-index" 440 | checksum = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" 441 | 442 | [[package]] 443 | name = "bytestring" 444 | version = "0.1.5" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "fc7c05fa5172da78a62d9949d662d2ac89d4cc7355d7b49adee5163f1fb3f363" 447 | dependencies = [ 448 | "bytes", 449 | ] 450 | 451 | [[package]] 452 | name = "cc" 453 | version = "1.0.54" 454 | source = "registry+https://github.com/rust-lang/crates.io-index" 455 | checksum = "7bbb73db36c1246e9034e307d0fba23f9a2e251faa47ade70c1bd252220c8311" 456 | 457 | [[package]] 458 | name = "cfg-if" 459 | version = "0.1.10" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 462 | 463 | [[package]] 464 | name = "chrono" 465 | version = "0.4.11" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" 468 | dependencies = [ 469 | "num-integer", 470 | "num-traits", 471 | "time", 472 | ] 473 | 474 | [[package]] 475 | name = "cloudabi" 476 | version = "0.0.3" 477 | source = "registry+https://github.com/rust-lang/crates.io-index" 478 | checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" 479 | dependencies = [ 480 | "bitflags", 481 | ] 482 | 483 | [[package]] 484 | name = "combine" 485 | version = "3.8.1" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" 488 | dependencies = [ 489 | "ascii", 490 | "byteorder", 491 | "either", 492 | "memchr", 493 | "unreachable", 494 | ] 495 | 496 | [[package]] 497 | name = "copyless" 498 | version = "0.1.5" 499 | source = "registry+https://github.com/rust-lang/crates.io-index" 500 | checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" 501 | 502 | [[package]] 503 | name = "crc32fast" 504 | version = "1.2.0" 505 | source = "registry+https://github.com/rust-lang/crates.io-index" 506 | checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" 507 | dependencies = [ 508 | "cfg-if", 509 | ] 510 | 511 | [[package]] 512 | name = "crossbeam-channel" 513 | version = "0.4.2" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" 516 | dependencies = [ 517 | "crossbeam-utils", 518 | "maybe-uninit", 519 | ] 520 | 521 | [[package]] 522 | name = "crossbeam-utils" 523 | version = "0.7.2" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" 526 | dependencies = [ 527 | "autocfg", 528 | "cfg-if", 529 | "lazy_static", 530 | ] 531 | 532 | [[package]] 533 | name = "derivative" 534 | version = "2.1.1" 535 | source = "registry+https://github.com/rust-lang/crates.io-index" 536 | checksum = "cb582b60359da160a9477ee80f15c8d784c477e69c217ef2cdd4169c24ea380f" 537 | dependencies = [ 538 | "proc-macro2", 539 | "quote", 540 | "syn", 541 | ] 542 | 543 | [[package]] 544 | name = "derive_more" 545 | version = "0.99.7" 546 | source = "registry+https://github.com/rust-lang/crates.io-index" 547 | checksum = "2127768764f1556535c01b5326ef94bd60ff08dcfbdc544d53e69ed155610f5d" 548 | dependencies = [ 549 | "proc-macro2", 550 | "quote", 551 | "syn", 552 | ] 553 | 554 | [[package]] 555 | name = "dtoa" 556 | version = "0.4.5" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" 559 | 560 | [[package]] 561 | name = "either" 562 | version = "1.5.3" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" 565 | 566 | [[package]] 567 | name = "encoding_rs" 568 | version = "0.8.23" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "e8ac63f94732332f44fe654443c46f6375d1939684c17b0afb6cb56b0456e171" 571 | dependencies = [ 572 | "cfg-if", 573 | ] 574 | 575 | [[package]] 576 | name = "enum-as-inner" 577 | version = "0.3.2" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "bc4bfcfacb61d231109d1d55202c1f33263319668b168843e02ad4652725ec9c" 580 | dependencies = [ 581 | "heck", 582 | "proc-macro2", 583 | "quote", 584 | "syn", 585 | ] 586 | 587 | [[package]] 588 | name = "env_logger" 589 | version = "0.7.1" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" 592 | dependencies = [ 593 | "atty", 594 | "humantime", 595 | "log", 596 | "regex", 597 | "termcolor", 598 | ] 599 | 600 | [[package]] 601 | name = "failure" 602 | version = "0.1.8" 603 | source = "registry+https://github.com/rust-lang/crates.io-index" 604 | checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" 605 | dependencies = [ 606 | "backtrace", 607 | "failure_derive", 608 | ] 609 | 610 | [[package]] 611 | name = "failure_derive" 612 | version = "0.1.8" 613 | source = "registry+https://github.com/rust-lang/crates.io-index" 614 | checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" 615 | dependencies = [ 616 | "proc-macro2", 617 | "quote", 618 | "syn", 619 | "synstructure", 620 | ] 621 | 622 | [[package]] 623 | name = "flate2" 624 | version = "1.0.14" 625 | source = "registry+https://github.com/rust-lang/crates.io-index" 626 | checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" 627 | dependencies = [ 628 | "cfg-if", 629 | "crc32fast", 630 | "libc", 631 | "miniz_oxide", 632 | ] 633 | 634 | [[package]] 635 | name = "fnv" 636 | version = "1.0.7" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 639 | 640 | [[package]] 641 | name = "fuchsia-zircon" 642 | version = "0.3.3" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" 645 | dependencies = [ 646 | "bitflags", 647 | "fuchsia-zircon-sys", 648 | ] 649 | 650 | [[package]] 651 | name = "fuchsia-zircon-sys" 652 | version = "0.3.3" 653 | source = "registry+https://github.com/rust-lang/crates.io-index" 654 | checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" 655 | 656 | [[package]] 657 | name = "futures" 658 | version = "0.1.29" 659 | source = "registry+https://github.com/rust-lang/crates.io-index" 660 | checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" 661 | 662 | [[package]] 663 | name = "futures" 664 | version = "0.3.5" 665 | source = "registry+https://github.com/rust-lang/crates.io-index" 666 | checksum = "1e05b85ec287aac0dc34db7d4a569323df697f9c55b99b15d6b4ef8cde49f613" 667 | dependencies = [ 668 | "futures-channel", 669 | "futures-core", 670 | "futures-executor", 671 | "futures-io", 672 | "futures-sink", 673 | "futures-task", 674 | "futures-util", 675 | ] 676 | 677 | [[package]] 678 | name = "futures-channel" 679 | version = "0.3.5" 680 | source = "registry+https://github.com/rust-lang/crates.io-index" 681 | checksum = "f366ad74c28cca6ba456d95e6422883cfb4b252a83bed929c83abfdbbf2967d5" 682 | dependencies = [ 683 | "futures-core", 684 | "futures-sink", 685 | ] 686 | 687 | [[package]] 688 | name = "futures-core" 689 | version = "0.3.5" 690 | source = "registry+https://github.com/rust-lang/crates.io-index" 691 | checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" 692 | 693 | [[package]] 694 | name = "futures-executor" 695 | version = "0.3.5" 696 | source = "registry+https://github.com/rust-lang/crates.io-index" 697 | checksum = "10d6bb888be1153d3abeb9006b11b02cf5e9b209fda28693c31ae1e4e012e314" 698 | dependencies = [ 699 | "futures-core", 700 | "futures-task", 701 | "futures-util", 702 | ] 703 | 704 | [[package]] 705 | name = "futures-io" 706 | version = "0.3.5" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "de27142b013a8e869c14957e6d2edeef89e97c289e69d042ee3a49acd8b51789" 709 | 710 | [[package]] 711 | name = "futures-macro" 712 | version = "0.3.5" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" 715 | dependencies = [ 716 | "proc-macro-hack", 717 | "proc-macro2", 718 | "quote", 719 | "syn", 720 | ] 721 | 722 | [[package]] 723 | name = "futures-sink" 724 | version = "0.3.5" 725 | source = "registry+https://github.com/rust-lang/crates.io-index" 726 | checksum = "3f2032893cb734c7a05d85ce0cc8b8c4075278e93b24b66f9de99d6eb0fa8acc" 727 | 728 | [[package]] 729 | name = "futures-task" 730 | version = "0.3.5" 731 | source = "registry+https://github.com/rust-lang/crates.io-index" 732 | checksum = "bdb66b5f09e22019b1ab0830f7785bcea8e7a42148683f99214f73f8ec21a626" 733 | dependencies = [ 734 | "once_cell", 735 | ] 736 | 737 | [[package]] 738 | name = "futures-util" 739 | version = "0.3.5" 740 | source = "registry+https://github.com/rust-lang/crates.io-index" 741 | checksum = "8764574ff08b701a084482c3c7031349104b07ac897393010494beaa18ce32c6" 742 | dependencies = [ 743 | "futures 0.1.29", 744 | "futures-channel", 745 | "futures-core", 746 | "futures-io", 747 | "futures-macro", 748 | "futures-sink", 749 | "futures-task", 750 | "memchr", 751 | "pin-project", 752 | "pin-utils", 753 | "proc-macro-hack", 754 | "proc-macro-nested", 755 | "slab", 756 | ] 757 | 758 | [[package]] 759 | name = "fxhash" 760 | version = "0.2.1" 761 | source = "registry+https://github.com/rust-lang/crates.io-index" 762 | checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" 763 | dependencies = [ 764 | "byteorder", 765 | ] 766 | 767 | [[package]] 768 | name = "getrandom" 769 | version = "0.1.14" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" 772 | dependencies = [ 773 | "cfg-if", 774 | "libc", 775 | "wasi", 776 | ] 777 | 778 | [[package]] 779 | name = "gimli" 780 | version = "0.21.0" 781 | source = "registry+https://github.com/rust-lang/crates.io-index" 782 | checksum = "bcc8e0c9bce37868955864dbecd2b1ab2bdf967e6f28066d65aaac620444b65c" 783 | 784 | [[package]] 785 | name = "h2" 786 | version = "0.2.5" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "79b7246d7e4b979c03fa093da39cfb3617a96bbeee6310af63991668d7e843ff" 789 | dependencies = [ 790 | "bytes", 791 | "fnv", 792 | "futures-core", 793 | "futures-sink", 794 | "futures-util", 795 | "http", 796 | "indexmap", 797 | "log", 798 | "slab", 799 | "tokio", 800 | "tokio-util 0.3.1", 801 | ] 802 | 803 | [[package]] 804 | name = "heck" 805 | version = "0.3.1" 806 | source = "registry+https://github.com/rust-lang/crates.io-index" 807 | checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" 808 | dependencies = [ 809 | "unicode-segmentation", 810 | ] 811 | 812 | [[package]] 813 | name = "hermit-abi" 814 | version = "0.1.13" 815 | source = "registry+https://github.com/rust-lang/crates.io-index" 816 | checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71" 817 | dependencies = [ 818 | "libc", 819 | ] 820 | 821 | [[package]] 822 | name = "hostname" 823 | version = "0.3.1" 824 | source = "registry+https://github.com/rust-lang/crates.io-index" 825 | checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" 826 | dependencies = [ 827 | "libc", 828 | "match_cfg", 829 | "winapi 0.3.8", 830 | ] 831 | 832 | [[package]] 833 | name = "http" 834 | version = "0.2.1" 835 | source = "registry+https://github.com/rust-lang/crates.io-index" 836 | checksum = "28d569972648b2c512421b5f2a405ad6ac9666547189d0c5477a3f200f3e02f9" 837 | dependencies = [ 838 | "bytes", 839 | "fnv", 840 | "itoa", 841 | ] 842 | 843 | [[package]] 844 | name = "httparse" 845 | version = "1.3.4" 846 | source = "registry+https://github.com/rust-lang/crates.io-index" 847 | checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" 848 | 849 | [[package]] 850 | name = "humantime" 851 | version = "1.3.0" 852 | source = "registry+https://github.com/rust-lang/crates.io-index" 853 | checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" 854 | dependencies = [ 855 | "quick-error", 856 | ] 857 | 858 | [[package]] 859 | name = "idna" 860 | version = "0.2.0" 861 | source = "registry+https://github.com/rust-lang/crates.io-index" 862 | checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" 863 | dependencies = [ 864 | "matches", 865 | "unicode-bidi", 866 | "unicode-normalization", 867 | ] 868 | 869 | [[package]] 870 | name = "indexmap" 871 | version = "1.4.0" 872 | source = "registry+https://github.com/rust-lang/crates.io-index" 873 | checksum = "c398b2b113b55809ceb9ee3e753fcbac793f1956663f3c36549c1346015c2afe" 874 | dependencies = [ 875 | "autocfg", 876 | ] 877 | 878 | [[package]] 879 | name = "iovec" 880 | version = "0.1.4" 881 | source = "registry+https://github.com/rust-lang/crates.io-index" 882 | checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" 883 | dependencies = [ 884 | "libc", 885 | ] 886 | 887 | [[package]] 888 | name = "ipconfig" 889 | version = "0.2.2" 890 | source = "registry+https://github.com/rust-lang/crates.io-index" 891 | checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" 892 | dependencies = [ 893 | "socket2", 894 | "widestring", 895 | "winapi 0.3.8", 896 | "winreg", 897 | ] 898 | 899 | [[package]] 900 | name = "itoa" 901 | version = "0.4.5" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" 904 | 905 | [[package]] 906 | name = "kernel32-sys" 907 | version = "0.2.2" 908 | source = "registry+https://github.com/rust-lang/crates.io-index" 909 | checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 910 | dependencies = [ 911 | "winapi 0.2.8", 912 | "winapi-build", 913 | ] 914 | 915 | [[package]] 916 | name = "language-tags" 917 | version = "0.2.2" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" 920 | 921 | [[package]] 922 | name = "lazy_static" 923 | version = "1.4.0" 924 | source = "registry+https://github.com/rust-lang/crates.io-index" 925 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 926 | 927 | [[package]] 928 | name = "libc" 929 | version = "0.2.71" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49" 932 | 933 | [[package]] 934 | name = "libz-sys" 935 | version = "1.0.25" 936 | source = "registry+https://github.com/rust-lang/crates.io-index" 937 | checksum = "2eb5e43362e38e2bca2fd5f5134c4d4564a23a5c28e9b95411652021a8675ebe" 938 | dependencies = [ 939 | "cc", 940 | "libc", 941 | "pkg-config", 942 | "vcpkg", 943 | ] 944 | 945 | [[package]] 946 | name = "linked-hash-map" 947 | version = "0.5.3" 948 | source = "registry+https://github.com/rust-lang/crates.io-index" 949 | checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" 950 | 951 | [[package]] 952 | name = "lock_api" 953 | version = "0.3.4" 954 | source = "registry+https://github.com/rust-lang/crates.io-index" 955 | checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" 956 | dependencies = [ 957 | "scopeguard", 958 | ] 959 | 960 | [[package]] 961 | name = "log" 962 | version = "0.4.8" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 965 | dependencies = [ 966 | "cfg-if", 967 | ] 968 | 969 | [[package]] 970 | name = "lru-cache" 971 | version = "0.1.2" 972 | source = "registry+https://github.com/rust-lang/crates.io-index" 973 | checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" 974 | dependencies = [ 975 | "linked-hash-map", 976 | ] 977 | 978 | [[package]] 979 | name = "match_cfg" 980 | version = "0.1.0" 981 | source = "registry+https://github.com/rust-lang/crates.io-index" 982 | checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" 983 | 984 | [[package]] 985 | name = "matches" 986 | version = "0.1.8" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" 989 | 990 | [[package]] 991 | name = "maybe-uninit" 992 | version = "2.0.0" 993 | source = "registry+https://github.com/rust-lang/crates.io-index" 994 | checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" 995 | 996 | [[package]] 997 | name = "memchr" 998 | version = "2.3.3" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" 1001 | 1002 | [[package]] 1003 | name = "mime" 1004 | version = "0.3.16" 1005 | source = "registry+https://github.com/rust-lang/crates.io-index" 1006 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 1007 | 1008 | [[package]] 1009 | name = "miniz_oxide" 1010 | version = "0.3.7" 1011 | source = "registry+https://github.com/rust-lang/crates.io-index" 1012 | checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" 1013 | dependencies = [ 1014 | "adler32", 1015 | ] 1016 | 1017 | [[package]] 1018 | name = "mio" 1019 | version = "0.6.22" 1020 | source = "registry+https://github.com/rust-lang/crates.io-index" 1021 | checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" 1022 | dependencies = [ 1023 | "cfg-if", 1024 | "fuchsia-zircon", 1025 | "fuchsia-zircon-sys", 1026 | "iovec", 1027 | "kernel32-sys", 1028 | "libc", 1029 | "log", 1030 | "miow 0.2.1", 1031 | "net2", 1032 | "slab", 1033 | "winapi 0.2.8", 1034 | ] 1035 | 1036 | [[package]] 1037 | name = "mio-named-pipes" 1038 | version = "0.1.6" 1039 | source = "registry+https://github.com/rust-lang/crates.io-index" 1040 | checksum = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" 1041 | dependencies = [ 1042 | "log", 1043 | "mio", 1044 | "miow 0.3.5", 1045 | "winapi 0.3.8", 1046 | ] 1047 | 1048 | [[package]] 1049 | name = "mio-uds" 1050 | version = "0.6.8" 1051 | source = "registry+https://github.com/rust-lang/crates.io-index" 1052 | checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" 1053 | dependencies = [ 1054 | "iovec", 1055 | "libc", 1056 | "mio", 1057 | ] 1058 | 1059 | [[package]] 1060 | name = "miow" 1061 | version = "0.2.1" 1062 | source = "registry+https://github.com/rust-lang/crates.io-index" 1063 | checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" 1064 | dependencies = [ 1065 | "kernel32-sys", 1066 | "net2", 1067 | "winapi 0.2.8", 1068 | "ws2_32-sys", 1069 | ] 1070 | 1071 | [[package]] 1072 | name = "miow" 1073 | version = "0.3.5" 1074 | source = "registry+https://github.com/rust-lang/crates.io-index" 1075 | checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e" 1076 | dependencies = [ 1077 | "socket2", 1078 | "winapi 0.3.8", 1079 | ] 1080 | 1081 | [[package]] 1082 | name = "net2" 1083 | version = "0.2.34" 1084 | source = "registry+https://github.com/rust-lang/crates.io-index" 1085 | checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7" 1086 | dependencies = [ 1087 | "cfg-if", 1088 | "libc", 1089 | "winapi 0.3.8", 1090 | ] 1091 | 1092 | [[package]] 1093 | name = "num-integer" 1094 | version = "0.1.43" 1095 | source = "registry+https://github.com/rust-lang/crates.io-index" 1096 | checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b" 1097 | dependencies = [ 1098 | "autocfg", 1099 | "num-traits", 1100 | ] 1101 | 1102 | [[package]] 1103 | name = "num-traits" 1104 | version = "0.2.12" 1105 | source = "registry+https://github.com/rust-lang/crates.io-index" 1106 | checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" 1107 | dependencies = [ 1108 | "autocfg", 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "num_cpus" 1113 | version = "1.13.0" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 1116 | dependencies = [ 1117 | "hermit-abi", 1118 | "libc", 1119 | ] 1120 | 1121 | [[package]] 1122 | name = "num_enum" 1123 | version = "0.4.3" 1124 | source = "registry+https://github.com/rust-lang/crates.io-index" 1125 | checksum = "ca565a7df06f3d4b485494f25ba05da1435950f4dc263440eda7a6fa9b8e36e4" 1126 | dependencies = [ 1127 | "derivative", 1128 | "num_enum_derive", 1129 | ] 1130 | 1131 | [[package]] 1132 | name = "num_enum_derive" 1133 | version = "0.4.3" 1134 | source = "registry+https://github.com/rust-lang/crates.io-index" 1135 | checksum = "ffa5a33ddddfee04c0283a7653987d634e880347e96b5b2ed64de07efb59db9d" 1136 | dependencies = [ 1137 | "proc-macro-crate", 1138 | "proc-macro2", 1139 | "quote", 1140 | "syn", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "object" 1145 | version = "0.19.0" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "9cbca9424c482ee628fa549d9c812e2cd22f1180b9222c9200fdfa6eb31aecb2" 1148 | 1149 | [[package]] 1150 | name = "once_cell" 1151 | version = "1.4.0" 1152 | source = "registry+https://github.com/rust-lang/crates.io-index" 1153 | checksum = "0b631f7e854af39a1739f401cf34a8a013dfe09eac4fa4dba91e9768bd28168d" 1154 | 1155 | [[package]] 1156 | name = "parking_lot" 1157 | version = "0.10.2" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" 1160 | dependencies = [ 1161 | "lock_api", 1162 | "parking_lot_core", 1163 | ] 1164 | 1165 | [[package]] 1166 | name = "parking_lot_core" 1167 | version = "0.7.2" 1168 | source = "registry+https://github.com/rust-lang/crates.io-index" 1169 | checksum = "d58c7c768d4ba344e3e8d72518ac13e259d7c7ade24167003b8488e10b6740a3" 1170 | dependencies = [ 1171 | "cfg-if", 1172 | "cloudabi", 1173 | "libc", 1174 | "redox_syscall", 1175 | "smallvec", 1176 | "winapi 0.3.8", 1177 | ] 1178 | 1179 | [[package]] 1180 | name = "percent-encoding" 1181 | version = "2.1.0" 1182 | source = "registry+https://github.com/rust-lang/crates.io-index" 1183 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 1184 | 1185 | [[package]] 1186 | name = "pin-project" 1187 | version = "0.4.21" 1188 | source = "registry+https://github.com/rust-lang/crates.io-index" 1189 | checksum = "b044170ce52ac41b78bdf855a045f6fe6ba72c293a33a2e3f654642127680563" 1190 | dependencies = [ 1191 | "pin-project-internal", 1192 | ] 1193 | 1194 | [[package]] 1195 | name = "pin-project-internal" 1196 | version = "0.4.21" 1197 | source = "registry+https://github.com/rust-lang/crates.io-index" 1198 | checksum = "babd76ce3c0d7c677fd01a3c3f9be24fa760adb73fd6db48f151662c1ec7eaba" 1199 | dependencies = [ 1200 | "proc-macro2", 1201 | "quote", 1202 | "syn", 1203 | ] 1204 | 1205 | [[package]] 1206 | name = "pin-project-lite" 1207 | version = "0.1.7" 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" 1209 | checksum = "282adbf10f2698a7a77f8e983a74b2d18176c19a7fd32a45446139ae7b02b715" 1210 | 1211 | [[package]] 1212 | name = "pin-utils" 1213 | version = "0.1.0" 1214 | source = "registry+https://github.com/rust-lang/crates.io-index" 1215 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 1216 | 1217 | [[package]] 1218 | name = "pkg-config" 1219 | version = "0.3.17" 1220 | source = "registry+https://github.com/rust-lang/crates.io-index" 1221 | checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" 1222 | 1223 | [[package]] 1224 | name = "ppv-lite86" 1225 | version = "0.2.8" 1226 | source = "registry+https://github.com/rust-lang/crates.io-index" 1227 | checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea" 1228 | 1229 | [[package]] 1230 | name = "proc-macro-crate" 1231 | version = "0.1.4" 1232 | source = "registry+https://github.com/rust-lang/crates.io-index" 1233 | checksum = "e10d4b51f154c8a7fb96fd6dad097cb74b863943ec010ac94b9fd1be8861fe1e" 1234 | dependencies = [ 1235 | "toml", 1236 | ] 1237 | 1238 | [[package]] 1239 | name = "proc-macro-hack" 1240 | version = "0.5.16" 1241 | source = "registry+https://github.com/rust-lang/crates.io-index" 1242 | checksum = "7e0456befd48169b9f13ef0f0ad46d492cf9d2dbb918bcf38e01eed4ce3ec5e4" 1243 | 1244 | [[package]] 1245 | name = "proc-macro-nested" 1246 | version = "0.1.5" 1247 | source = "registry+https://github.com/rust-lang/crates.io-index" 1248 | checksum = "0afe1bd463b9e9ed51d0e0f0b50b6b146aec855c56fd182bb242388710a9b6de" 1249 | 1250 | [[package]] 1251 | name = "proc-macro2" 1252 | version = "1.0.18" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "beae6331a816b1f65d04c45b078fd8e6c93e8071771f41b8163255bbd8d7c8fa" 1255 | dependencies = [ 1256 | "unicode-xid", 1257 | ] 1258 | 1259 | [[package]] 1260 | name = "quick-error" 1261 | version = "1.2.3" 1262 | source = "registry+https://github.com/rust-lang/crates.io-index" 1263 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 1264 | 1265 | [[package]] 1266 | name = "quote" 1267 | version = "1.0.7" 1268 | source = "registry+https://github.com/rust-lang/crates.io-index" 1269 | checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" 1270 | dependencies = [ 1271 | "proc-macro2", 1272 | ] 1273 | 1274 | [[package]] 1275 | name = "rand" 1276 | version = "0.7.3" 1277 | source = "registry+https://github.com/rust-lang/crates.io-index" 1278 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 1279 | dependencies = [ 1280 | "getrandom", 1281 | "libc", 1282 | "rand_chacha", 1283 | "rand_core", 1284 | "rand_hc", 1285 | ] 1286 | 1287 | [[package]] 1288 | name = "rand_chacha" 1289 | version = "0.2.2" 1290 | source = "registry+https://github.com/rust-lang/crates.io-index" 1291 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 1292 | dependencies = [ 1293 | "ppv-lite86", 1294 | "rand_core", 1295 | ] 1296 | 1297 | [[package]] 1298 | name = "rand_core" 1299 | version = "0.5.1" 1300 | source = "registry+https://github.com/rust-lang/crates.io-index" 1301 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 1302 | dependencies = [ 1303 | "getrandom", 1304 | ] 1305 | 1306 | [[package]] 1307 | name = "rand_hc" 1308 | version = "0.2.0" 1309 | source = "registry+https://github.com/rust-lang/crates.io-index" 1310 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 1311 | dependencies = [ 1312 | "rand_core", 1313 | ] 1314 | 1315 | [[package]] 1316 | name = "rdkafka" 1317 | version = "0.23.0" 1318 | source = "registry+https://github.com/rust-lang/crates.io-index" 1319 | checksum = "43c48f1689bcf33bdab14999e23f541cad54bacddd1233039237947781f659ca" 1320 | dependencies = [ 1321 | "futures 0.3.5", 1322 | "libc", 1323 | "log", 1324 | "rdkafka-sys", 1325 | "serde", 1326 | "serde_derive", 1327 | "serde_json", 1328 | ] 1329 | 1330 | [[package]] 1331 | name = "rdkafka-sys" 1332 | version = "1.3.0" 1333 | source = "registry+https://github.com/rust-lang/crates.io-index" 1334 | checksum = "b75ba3e82e0a009c79f311e87a27890e1288d06a3d979692aba1258858f00c94" 1335 | dependencies = [ 1336 | "libc", 1337 | "libz-sys", 1338 | "num_enum", 1339 | "pkg-config", 1340 | ] 1341 | 1342 | [[package]] 1343 | name = "redis" 1344 | version = "0.15.1" 1345 | source = "registry+https://github.com/rust-lang/crates.io-index" 1346 | checksum = "3eeb1fe3fc011cde97315f370bc88e4db3c23b08709a04915921e02b1d363b20" 1347 | dependencies = [ 1348 | "bytes", 1349 | "combine", 1350 | "dtoa", 1351 | "futures-executor", 1352 | "futures-util", 1353 | "itoa", 1354 | "percent-encoding", 1355 | "pin-project-lite", 1356 | "sha1", 1357 | "tokio", 1358 | "tokio-util 0.2.0", 1359 | "url", 1360 | ] 1361 | 1362 | [[package]] 1363 | name = "redox_syscall" 1364 | version = "0.1.56" 1365 | source = "registry+https://github.com/rust-lang/crates.io-index" 1366 | checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" 1367 | 1368 | [[package]] 1369 | name = "regex" 1370 | version = "1.3.9" 1371 | source = "registry+https://github.com/rust-lang/crates.io-index" 1372 | checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6" 1373 | dependencies = [ 1374 | "aho-corasick", 1375 | "memchr", 1376 | "regex-syntax", 1377 | "thread_local", 1378 | ] 1379 | 1380 | [[package]] 1381 | name = "regex-syntax" 1382 | version = "0.6.18" 1383 | source = "registry+https://github.com/rust-lang/crates.io-index" 1384 | checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" 1385 | 1386 | [[package]] 1387 | name = "resolv-conf" 1388 | version = "0.6.3" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "11834e137f3b14e309437a8276714eed3a80d1ef894869e510f2c0c0b98b9f4a" 1391 | dependencies = [ 1392 | "hostname", 1393 | "quick-error", 1394 | ] 1395 | 1396 | [[package]] 1397 | name = "rustc-demangle" 1398 | version = "0.1.16" 1399 | source = "registry+https://github.com/rust-lang/crates.io-index" 1400 | checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" 1401 | 1402 | [[package]] 1403 | name = "ryu" 1404 | version = "1.0.5" 1405 | source = "registry+https://github.com/rust-lang/crates.io-index" 1406 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 1407 | 1408 | [[package]] 1409 | name = "scopeguard" 1410 | version = "1.1.0" 1411 | source = "registry+https://github.com/rust-lang/crates.io-index" 1412 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 1413 | 1414 | [[package]] 1415 | name = "serde" 1416 | version = "1.0.111" 1417 | source = "registry+https://github.com/rust-lang/crates.io-index" 1418 | checksum = "c9124df5b40cbd380080b2cc6ab894c040a3070d995f5c9dc77e18c34a8ae37d" 1419 | dependencies = [ 1420 | "serde_derive", 1421 | ] 1422 | 1423 | [[package]] 1424 | name = "serde_derive" 1425 | version = "1.0.111" 1426 | source = "registry+https://github.com/rust-lang/crates.io-index" 1427 | checksum = "3f2c3ac8e6ca1e9c80b8be1023940162bf81ae3cffbb1809474152f2ce1eb250" 1428 | dependencies = [ 1429 | "proc-macro2", 1430 | "quote", 1431 | "syn", 1432 | ] 1433 | 1434 | [[package]] 1435 | name = "serde_json" 1436 | version = "1.0.55" 1437 | source = "registry+https://github.com/rust-lang/crates.io-index" 1438 | checksum = "ec2c5d7e739bc07a3e73381a39d61fdb5f671c60c1df26a130690665803d8226" 1439 | dependencies = [ 1440 | "itoa", 1441 | "ryu", 1442 | "serde", 1443 | ] 1444 | 1445 | [[package]] 1446 | name = "serde_urlencoded" 1447 | version = "0.6.1" 1448 | source = "registry+https://github.com/rust-lang/crates.io-index" 1449 | checksum = "9ec5d77e2d4c73717816afac02670d5c4f534ea95ed430442cad02e7a6e32c97" 1450 | dependencies = [ 1451 | "dtoa", 1452 | "itoa", 1453 | "serde", 1454 | "url", 1455 | ] 1456 | 1457 | [[package]] 1458 | name = "sha1" 1459 | version = "0.6.0" 1460 | source = "registry+https://github.com/rust-lang/crates.io-index" 1461 | checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" 1462 | 1463 | [[package]] 1464 | name = "signal-hook-registry" 1465 | version = "1.2.0" 1466 | source = "registry+https://github.com/rust-lang/crates.io-index" 1467 | checksum = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" 1468 | dependencies = [ 1469 | "arc-swap", 1470 | "libc", 1471 | ] 1472 | 1473 | [[package]] 1474 | name = "slab" 1475 | version = "0.4.2" 1476 | source = "registry+https://github.com/rust-lang/crates.io-index" 1477 | checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" 1478 | 1479 | [[package]] 1480 | name = "smallvec" 1481 | version = "1.4.0" 1482 | source = "registry+https://github.com/rust-lang/crates.io-index" 1483 | checksum = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4" 1484 | 1485 | [[package]] 1486 | name = "socket2" 1487 | version = "0.3.12" 1488 | source = "registry+https://github.com/rust-lang/crates.io-index" 1489 | checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918" 1490 | dependencies = [ 1491 | "cfg-if", 1492 | "libc", 1493 | "redox_syscall", 1494 | "winapi 0.3.8", 1495 | ] 1496 | 1497 | [[package]] 1498 | name = "syn" 1499 | version = "1.0.31" 1500 | source = "registry+https://github.com/rust-lang/crates.io-index" 1501 | checksum = "b5304cfdf27365b7585c25d4af91b35016ed21ef88f17ced89c7093b43dba8b6" 1502 | dependencies = [ 1503 | "proc-macro2", 1504 | "quote", 1505 | "unicode-xid", 1506 | ] 1507 | 1508 | [[package]] 1509 | name = "synstructure" 1510 | version = "0.12.4" 1511 | source = "registry+https://github.com/rust-lang/crates.io-index" 1512 | checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" 1513 | dependencies = [ 1514 | "proc-macro2", 1515 | "quote", 1516 | "syn", 1517 | "unicode-xid", 1518 | ] 1519 | 1520 | [[package]] 1521 | name = "termcolor" 1522 | version = "1.1.0" 1523 | source = "registry+https://github.com/rust-lang/crates.io-index" 1524 | checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" 1525 | dependencies = [ 1526 | "winapi-util", 1527 | ] 1528 | 1529 | [[package]] 1530 | name = "thread_local" 1531 | version = "1.0.1" 1532 | source = "registry+https://github.com/rust-lang/crates.io-index" 1533 | checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" 1534 | dependencies = [ 1535 | "lazy_static", 1536 | ] 1537 | 1538 | [[package]] 1539 | name = "threadpool" 1540 | version = "1.8.1" 1541 | source = "registry+https://github.com/rust-lang/crates.io-index" 1542 | checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" 1543 | dependencies = [ 1544 | "num_cpus", 1545 | ] 1546 | 1547 | [[package]] 1548 | name = "time" 1549 | version = "0.1.43" 1550 | source = "registry+https://github.com/rust-lang/crates.io-index" 1551 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 1552 | dependencies = [ 1553 | "libc", 1554 | "winapi 0.3.8", 1555 | ] 1556 | 1557 | [[package]] 1558 | name = "tokio" 1559 | version = "0.2.21" 1560 | source = "registry+https://github.com/rust-lang/crates.io-index" 1561 | checksum = "d099fa27b9702bed751524694adbe393e18b36b204da91eb1cbbbbb4a5ee2d58" 1562 | dependencies = [ 1563 | "bytes", 1564 | "fnv", 1565 | "futures-core", 1566 | "iovec", 1567 | "lazy_static", 1568 | "libc", 1569 | "memchr", 1570 | "mio", 1571 | "mio-named-pipes", 1572 | "mio-uds", 1573 | "num_cpus", 1574 | "pin-project-lite", 1575 | "signal-hook-registry", 1576 | "slab", 1577 | "tokio-macros", 1578 | "winapi 0.3.8", 1579 | ] 1580 | 1581 | [[package]] 1582 | name = "tokio-macros" 1583 | version = "0.2.5" 1584 | source = "registry+https://github.com/rust-lang/crates.io-index" 1585 | checksum = "f0c3acc6aa564495a0f2e1d59fab677cd7f81a19994cfc7f3ad0e64301560389" 1586 | dependencies = [ 1587 | "proc-macro2", 1588 | "quote", 1589 | "syn", 1590 | ] 1591 | 1592 | [[package]] 1593 | name = "tokio-util" 1594 | version = "0.2.0" 1595 | source = "registry+https://github.com/rust-lang/crates.io-index" 1596 | checksum = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" 1597 | dependencies = [ 1598 | "bytes", 1599 | "futures-core", 1600 | "futures-sink", 1601 | "log", 1602 | "pin-project-lite", 1603 | "tokio", 1604 | ] 1605 | 1606 | [[package]] 1607 | name = "tokio-util" 1608 | version = "0.3.1" 1609 | source = "registry+https://github.com/rust-lang/crates.io-index" 1610 | checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" 1611 | dependencies = [ 1612 | "bytes", 1613 | "futures-core", 1614 | "futures-sink", 1615 | "log", 1616 | "pin-project-lite", 1617 | "tokio", 1618 | ] 1619 | 1620 | [[package]] 1621 | name = "toml" 1622 | version = "0.5.6" 1623 | source = "registry+https://github.com/rust-lang/crates.io-index" 1624 | checksum = "ffc92d160b1eef40665be3a05630d003936a3bc7da7421277846c2613e92c71a" 1625 | dependencies = [ 1626 | "serde", 1627 | ] 1628 | 1629 | [[package]] 1630 | name = "trust-dns-proto" 1631 | version = "0.18.0-alpha.2" 1632 | source = "registry+https://github.com/rust-lang/crates.io-index" 1633 | checksum = "2a7f3a2ab8a919f5eca52a468866a67ed7d3efa265d48a652a9a3452272b413f" 1634 | dependencies = [ 1635 | "async-trait", 1636 | "enum-as-inner", 1637 | "failure", 1638 | "futures 0.3.5", 1639 | "idna", 1640 | "lazy_static", 1641 | "log", 1642 | "rand", 1643 | "smallvec", 1644 | "socket2", 1645 | "tokio", 1646 | "url", 1647 | ] 1648 | 1649 | [[package]] 1650 | name = "trust-dns-resolver" 1651 | version = "0.18.0-alpha.2" 1652 | source = "registry+https://github.com/rust-lang/crates.io-index" 1653 | checksum = "6f90b1502b226f8b2514c6d5b37bafa8c200d7ca4102d57dc36ee0f3b7a04a2f" 1654 | dependencies = [ 1655 | "cfg-if", 1656 | "failure", 1657 | "futures 0.3.5", 1658 | "ipconfig", 1659 | "lazy_static", 1660 | "log", 1661 | "lru-cache", 1662 | "resolv-conf", 1663 | "smallvec", 1664 | "tokio", 1665 | "trust-dns-proto", 1666 | ] 1667 | 1668 | [[package]] 1669 | name = "unicode-bidi" 1670 | version = "0.3.4" 1671 | source = "registry+https://github.com/rust-lang/crates.io-index" 1672 | checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" 1673 | dependencies = [ 1674 | "matches", 1675 | ] 1676 | 1677 | [[package]] 1678 | name = "unicode-normalization" 1679 | version = "0.1.12" 1680 | source = "registry+https://github.com/rust-lang/crates.io-index" 1681 | checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" 1682 | dependencies = [ 1683 | "smallvec", 1684 | ] 1685 | 1686 | [[package]] 1687 | name = "unicode-segmentation" 1688 | version = "1.6.0" 1689 | source = "registry+https://github.com/rust-lang/crates.io-index" 1690 | checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" 1691 | 1692 | [[package]] 1693 | name = "unicode-xid" 1694 | version = "0.2.0" 1695 | source = "registry+https://github.com/rust-lang/crates.io-index" 1696 | checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 1697 | 1698 | [[package]] 1699 | name = "unreachable" 1700 | version = "1.0.0" 1701 | source = "registry+https://github.com/rust-lang/crates.io-index" 1702 | checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 1703 | dependencies = [ 1704 | "void", 1705 | ] 1706 | 1707 | [[package]] 1708 | name = "url" 1709 | version = "2.1.1" 1710 | source = "registry+https://github.com/rust-lang/crates.io-index" 1711 | checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" 1712 | dependencies = [ 1713 | "idna", 1714 | "matches", 1715 | "percent-encoding", 1716 | ] 1717 | 1718 | [[package]] 1719 | name = "vcpkg" 1720 | version = "0.2.10" 1721 | source = "registry+https://github.com/rust-lang/crates.io-index" 1722 | checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" 1723 | 1724 | [[package]] 1725 | name = "void" 1726 | version = "1.0.2" 1727 | source = "registry+https://github.com/rust-lang/crates.io-index" 1728 | checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 1729 | 1730 | [[package]] 1731 | name = "wasi" 1732 | version = "0.9.0+wasi-snapshot-preview1" 1733 | source = "registry+https://github.com/rust-lang/crates.io-index" 1734 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 1735 | 1736 | [[package]] 1737 | name = "widestring" 1738 | version = "0.4.2" 1739 | source = "registry+https://github.com/rust-lang/crates.io-index" 1740 | checksum = "a763e303c0e0f23b0da40888724762e802a8ffefbc22de4127ef42493c2ea68c" 1741 | 1742 | [[package]] 1743 | name = "winapi" 1744 | version = "0.2.8" 1745 | source = "registry+https://github.com/rust-lang/crates.io-index" 1746 | checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 1747 | 1748 | [[package]] 1749 | name = "winapi" 1750 | version = "0.3.8" 1751 | source = "registry+https://github.com/rust-lang/crates.io-index" 1752 | checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" 1753 | dependencies = [ 1754 | "winapi-i686-pc-windows-gnu", 1755 | "winapi-x86_64-pc-windows-gnu", 1756 | ] 1757 | 1758 | [[package]] 1759 | name = "winapi-build" 1760 | version = "0.1.1" 1761 | source = "registry+https://github.com/rust-lang/crates.io-index" 1762 | checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 1763 | 1764 | [[package]] 1765 | name = "winapi-i686-pc-windows-gnu" 1766 | version = "0.4.0" 1767 | source = "registry+https://github.com/rust-lang/crates.io-index" 1768 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1769 | 1770 | [[package]] 1771 | name = "winapi-util" 1772 | version = "0.1.5" 1773 | source = "registry+https://github.com/rust-lang/crates.io-index" 1774 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1775 | dependencies = [ 1776 | "winapi 0.3.8", 1777 | ] 1778 | 1779 | [[package]] 1780 | name = "winapi-x86_64-pc-windows-gnu" 1781 | version = "0.4.0" 1782 | source = "registry+https://github.com/rust-lang/crates.io-index" 1783 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1784 | 1785 | [[package]] 1786 | name = "winreg" 1787 | version = "0.6.2" 1788 | source = "registry+https://github.com/rust-lang/crates.io-index" 1789 | checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" 1790 | dependencies = [ 1791 | "winapi 0.3.8", 1792 | ] 1793 | 1794 | [[package]] 1795 | name = "wordcount" 1796 | version = "0.2.0" 1797 | dependencies = [ 1798 | "actix", 1799 | "actix-rt", 1800 | "actix-web", 1801 | "env_logger", 1802 | "futures 0.3.5", 1803 | "log", 1804 | "rdkafka", 1805 | "rdkafka-sys", 1806 | "redis", 1807 | "serde", 1808 | "serde_derive", 1809 | "serde_json", 1810 | "tokio", 1811 | ] 1812 | 1813 | [[package]] 1814 | name = "ws2_32-sys" 1815 | version = "0.2.1" 1816 | source = "registry+https://github.com/rust-lang/crates.io-index" 1817 | checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" 1818 | dependencies = [ 1819 | "winapi 0.2.8", 1820 | "winapi-build", 1821 | ] 1822 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wordcount" 3 | version = "0.2.0" 4 | authors = ["Arthur Rand "] 5 | edition = "2018" 6 | 7 | [[bin]] 8 | name = "wordcount-server" 9 | path = "src/bin/server.rs" 10 | 11 | [[bin]] 12 | name = "wordcount-client" 13 | path = "src/bin/client.rs" 14 | 15 | 16 | [dependencies] 17 | actix = "0.9" 18 | actix-web = "2.0.0" 19 | actix-rt = "1.0.0" 20 | redis = "0.15.1" 21 | tokio = { version = "0.2", features = ["full"] } 22 | futures = { version = "0.3", features = ["compat"] } 23 | rdkafka = "0.23.0" 24 | rdkafka-sys = "=1.3.0" 25 | 26 | log = "*" 27 | env_logger = "*" 28 | serde_json = "1.0" 29 | serde = "1.0" 30 | serde_derive = "1.0" 31 | 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wordcount example with Actix, Kafka, and Redis 2 | 3 | The wordcount example is perhaps the "hello world" of data processing 4 | examples. The application here shows how to stream data from Kafka into 5 | Redis counting the individual tokens along the way. The `server` provides 6 | an endpoint for retrieving the counts for a specific topic. 7 | 8 | 9 | ```bash 10 | # starting the server (could also be cargo run --bin wordcount-server test 11 | $ wordcount-server test 12 | # start the client 13 | $ wordcount-client test-topic 14 | 15 | # you can also pipe from stdin 16 | # cat large-test.txt | wordcount-clinet epic-topic 17 | ``` 18 | 19 | Then you can get the counts of the words from the server like so: 20 | 21 | ```bash 22 | # assuming you have started wordcount-server 23 | $ curl http://127.0.0.1:8080/counts?topic=epic-topic 24 | # to get the top N (10 in this example) counts 25 | $ curl 'http://127.0.0.1:8080/counts?topic=epic-topic&n=10' 26 | ``` 27 | 28 | ## Setup 29 | The required services (Redis and Kafka) can be started with the included 30 | `docker-compose` file 31 | ```bash 32 | docker-compose up 33 | ``` 34 | 35 | The two executables can be built with `cargo` as you would expect 36 | ```bash 37 | $ cargo build <--release> 38 | ``` 39 | Then started accordingly 40 | ```bash 41 | $ target//wordcount-server .. 42 | $ target//wordcount-client 43 | ``` 44 | 45 | 46 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | redis: 4 | image: redis:6.0.1 5 | ports: 6 | - 6379:6379 7 | kafka: 8 | image: spotify/kafka 9 | environment: 10 | ADVERTISED_HOST: localhost 11 | ADVERTISED_PORT: 9092 12 | ports: 13 | - 9092:9092 -------------------------------------------------------------------------------- /src/bin/client.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate log; 3 | 4 | use log::error; 5 | use std::io::{self, BufRead}; 6 | use std::process::exit; 7 | 8 | use rdkafka::config::ClientConfig; 9 | use rdkafka::error::KafkaError; 10 | use rdkafka::producer::{FutureProducer, FutureRecord}; 11 | use wordcount::kafka::kafka_seed; 12 | 13 | fn kafka_producer(brokers: &str) -> Result { 14 | ClientConfig::new() 15 | .set("bootstrap.servers", brokers) 16 | .set("produce.offset.report", "true") 17 | .set("message.timeout.ms", "5000") 18 | .create() 19 | } 20 | 21 | async fn publish_line_to_topic(topic: String, line: String, producer: FutureProducer) { 22 | let rec = FutureRecord::to(topic.as_str()) 23 | .payload(line.as_str()) 24 | .key(""); 25 | match producer.clone().send(rec, 0).await { 26 | Ok(Ok(_)) => {} 27 | Ok(Err((kakfa_error, _))) => error!( 28 | "{}", 29 | format!("failed to publish to kafka, {}", kakfa_error.to_string()) 30 | ), 31 | Err(cancelled_err) => error!("{}", format!("cancelled, {}", cancelled_err.to_string())), 32 | } 33 | } 34 | 35 | #[tokio::main] 36 | async fn main() { 37 | std::env::set_var("RUST_LOG", "info"); 38 | env_logger::init(); 39 | let args = std::env::args().collect::>(); 40 | if args.len() != 2 { 41 | eprintln!("USAGE wordcount-client "); 42 | exit(1); 43 | } 44 | 45 | let topic = &args[1]; 46 | info!("producing to topic {}", topic); 47 | 48 | let kafka_host = kafka_seed(); 49 | let producer = kafka_producer(&kafka_host).expect("failed to create kafka producer"); 50 | 51 | let stdin = io::stdin(); 52 | for line in stdin.lock().lines() { 53 | match line { 54 | Ok(l) => { 55 | tokio::spawn(publish_line_to_topic(topic.clone(), l, producer.clone())); 56 | } 57 | Err(_) => error!("huh?"), 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/bin/server.rs: -------------------------------------------------------------------------------- 1 | use log::{info, warn}; 2 | 3 | use actix_web::web::Data; 4 | use actix_web::{middleware::Logger, web, App, HttpRequest, HttpResponse, HttpServer}; 5 | use redis::Client as RedisClient; 6 | use serde_json::json; 7 | use std::process::exit; 8 | use std::sync::Arc; 9 | 10 | use wordcount::cache::RedisCache; 11 | use wordcount::kafka::{kafka_seed, IngestConsumer}; 12 | 13 | #[derive(serde::Deserialize, Debug)] 14 | struct CountsQuery { 15 | topic: String, 16 | n: Option, 17 | } 18 | 19 | #[derive(Clone)] 20 | struct State { 21 | cache: RedisCache, 22 | } 23 | 24 | async fn health(_req: HttpRequest) -> HttpResponse { 25 | HttpResponse::Ok().json(json!("healthy")) 26 | } 27 | 28 | async fn counts(app_state: Data, counts_query: web::Query) -> HttpResponse { 29 | let topic = counts_query.0.topic; 30 | let top_n = counts_query.0.n.unwrap_or_else(|| -1); 31 | 32 | match app_state.cache.get_counts(&topic, top_n).await { 33 | Ok(token_counts) => { 34 | let serialized = serde_json::to_value(token_counts).unwrap(); 35 | HttpResponse::Ok().json(serialized) 36 | } 37 | Err(redis_error) => { 38 | let err = json!({ 39 | "redis-error": redis_error.to_string() 40 | }); 41 | HttpResponse::InternalServerError().json(err) 42 | } 43 | } 44 | } 45 | 46 | #[actix_rt::main] 47 | async fn main() { 48 | std::env::set_var("RUST_LOG", "info"); 49 | env_logger::init(); 50 | let args = std::env::args().collect::>(); 51 | if args.len() < 2 { 52 | eprintln!("USAGE wordcount-server ..."); 53 | exit(1); 54 | } 55 | let topics = &args[1..]; 56 | info!("listening on topics {:?}", &topics); 57 | 58 | let redis_host = std::env::var("REDIS_HOST").unwrap_or_else(|_| { 59 | let redis_host = "redis://localhost:6379".to_string(); 60 | warn!("using default redis connection, {}", redis_host); 61 | redis_host 62 | }); 63 | 64 | let redis_connection = 65 | RedisClient::open(redis_host.as_str()).expect("failed to make redis client"); 66 | let connection = Arc::new(redis_connection); 67 | let redis_cache = RedisCache::new(connection); 68 | 69 | let kafka_host = kafka_seed(); 70 | let ingest_consumer = IngestConsumer::new(kafka_host, topics, redis_cache.clone()) 71 | .expect("failed to make ingest consumer"); 72 | 73 | actix_rt::spawn(async move { ingest_consumer.run().await }); 74 | 75 | let app_state = State { cache: redis_cache }; 76 | 77 | let _ = HttpServer::new(move || { 78 | App::new() 79 | .data(app_state.clone()) 80 | .wrap(Logger::default()) 81 | .route("/health", web::get().to(health)) 82 | .route("/counts", web::get().to(counts)) 83 | }) 84 | .workers(2) 85 | .bind("localhost:8080".to_string()) 86 | .unwrap() 87 | .run() 88 | .await; 89 | } 90 | -------------------------------------------------------------------------------- /src/cache.rs: -------------------------------------------------------------------------------- 1 | use std::collections::HashMap; 2 | 3 | use redis::{Client as RedisClient, RedisError}; 4 | use std::sync::Arc; 5 | 6 | #[derive(Clone)] 7 | pub struct RedisCache { 8 | client: Arc, 9 | } 10 | 11 | impl RedisCache { 12 | pub fn new(connection: Arc) -> Self { 13 | Self { client: connection } 14 | } 15 | 16 | pub async fn get_counts( 17 | &self, 18 | topic: &str, 19 | top_n: i64, 20 | ) -> Result, RedisError> { 21 | let mut conn = self.client.get_async_connection().await?; 22 | let token_counts = redis::cmd("ZREVRANGE") 23 | .arg(topic) 24 | .arg("0") 25 | .arg(&format!("{:?}", top_n)) 26 | .arg("withscores") 27 | .query_async::<_, Vec>(&mut conn) 28 | .await?; 29 | Ok(Self::group_counts(token_counts)) 30 | } 31 | 32 | pub async fn persist_counts( 33 | &self, 34 | topic: String, 35 | counts: HashMap, 36 | ) -> Result<(), RedisError> { 37 | let mut conn = self.client.get_async_connection().await?; 38 | for (token, count) in counts { 39 | redis::cmd("ZINCRBY") 40 | .arg(&topic) 41 | .arg(count as i32) 42 | .arg(token) 43 | .query_async::<_, i64>(&mut conn) 44 | .await?; 45 | } 46 | Ok(()) 47 | } 48 | 49 | pub fn group_counts(counts: Vec) -> HashMap { 50 | counts 51 | .chunks(2) 52 | .map(|chunk| { 53 | let token = chunk.get(0).unwrap().to_owned(); 54 | let count = { 55 | let s = chunk.get(1).unwrap(); 56 | s.parse::().unwrap() 57 | }; 58 | (token, count) 59 | }) 60 | .collect::>() 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/kafka.rs: -------------------------------------------------------------------------------- 1 | use std::time::Duration; 2 | 3 | use rdkafka::config::ClientConfig; 4 | use rdkafka::config::RDKafkaLogLevel; 5 | use rdkafka::consumer::{Consumer, StreamConsumer}; 6 | use rdkafka::error::KafkaError; 7 | 8 | use crate::cache::RedisCache; 9 | use futures::StreamExt; 10 | use rdkafka::message::{BorrowedMessage, Message as KafkaMessage}; 11 | use std::collections::HashMap; 12 | 13 | #[derive(Debug, Clone)] 14 | pub struct MessagePayload(String); 15 | 16 | impl MessagePayload { 17 | pub fn as_str(&self) -> &str { 18 | self.0.as_str() 19 | } 20 | } 21 | 22 | /// generic way to turn a borrowed message into a (wrapped) string 23 | impl<'a> From<&'a BorrowedMessage<'a>> for MessagePayload { 24 | fn from(bm: &'a BorrowedMessage) -> Self { 25 | match bm.payload_view::() { 26 | Some(Ok(s)) => MessagePayload(String::from(s)), 27 | Some(Err(e)) => MessagePayload(format!("{:?}", e)), 28 | None => MessagePayload(String::from("")), 29 | } 30 | } 31 | } 32 | 33 | pub struct IngestConsumer { 34 | consumer: StreamConsumer, 35 | redis_cache: RedisCache, 36 | } 37 | 38 | impl IngestConsumer { 39 | pub fn new( 40 | kafka_seed: String, 41 | topics: &[String], 42 | redis_cache: RedisCache, 43 | ) -> Result { 44 | let consumer = new_consumer(kafka_seed, topics)?; 45 | Ok(IngestConsumer { 46 | consumer, 47 | redis_cache, 48 | }) 49 | } 50 | 51 | fn process_message(borrowed_message: BorrowedMessage) -> HashMap { 52 | let message_payload = MessagePayload::from(&borrowed_message); 53 | let splitted = message_payload 54 | .as_str() 55 | .split_whitespace() 56 | .map(|token| token.to_string()) 57 | .collect::>(); 58 | let mut counts: HashMap = HashMap::new(); 59 | for token in splitted { 60 | if let Some(count) = counts.get_mut(token.as_str()) { 61 | *count += 1; 62 | } else { 63 | counts.insert(token, 1); 64 | } 65 | } 66 | counts 67 | } 68 | 69 | pub async fn run(&self) { 70 | let mut stream = self.consumer.start_with(Duration::from_millis(50), false); 71 | loop { 72 | match stream.next().await { 73 | Some(Ok(borrowed_message)) => { 74 | let topic_name = borrowed_message.topic().to_owned(); 75 | let counts = Self::process_message(borrowed_message); 76 | match self.redis_cache.persist_counts(topic_name, counts).await { 77 | Ok(()) => {} 78 | Err(redis_err) => error!( 79 | "{}", 80 | &format!("failed to persist to redis, {}", redis_err.to_string()) 81 | ), 82 | } 83 | } 84 | Some(Err(kafka_error)) => match kafka_error { 85 | KafkaError::PartitionEOF(partition) => { 86 | info!("at end of partition {:?}", partition); 87 | } 88 | _ => error!( 89 | "{}", 90 | &format!("errors from kafka, {}", kafka_error.to_string()) 91 | ), 92 | }, 93 | None => {} 94 | } 95 | } 96 | } 97 | } 98 | 99 | pub fn kafka_seed() -> String { 100 | std::env::var("KAFKA_SEED").unwrap_or_else(|_| { 101 | let kafka_seed = "127.0.0.1:9092".to_string(); 102 | warn!("using default kafka seed, {}", kafka_seed); 103 | kafka_seed 104 | }) 105 | } 106 | 107 | fn new_consumer(brokers: String, topics: &[String]) -> Result { 108 | let msg = topics.join(" "); 109 | info!("subscribing to topics {}", msg); 110 | let stream_consumer: StreamConsumer = ClientConfig::new() 111 | .set("group.id", "test-group") 112 | .set("bootstrap.servers", &brokers) 113 | .set("auto.offset.reset", "latest") 114 | .set("enable.partition.eof", "true") 115 | .set("session.timeout.ms", "6000") 116 | .set("enable.auto.commit", "true") 117 | .set_log_level(RDKafkaLogLevel::Debug) 118 | .create()?; 119 | let topics = topics 120 | .iter() 121 | .map(|topic| topic.as_str()) 122 | .collect::>(); 123 | stream_consumer.subscribe(topics.as_slice())?; 124 | Ok(stream_consumer) 125 | } 126 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate log; 3 | 4 | pub mod kafka; 5 | 6 | pub mod cache; 7 | --------------------------------------------------------------------------------