Firehose event processing & storing in stupid db :3 #2

closed
opened by lewis.moe targeting main
  • Add firehose.rs that processes events
  • Add postgres db connection that saves the events (can turn to timescale or something silly later)
+1
.gitignore
···
/target
+
/.sqlx
+1291 -52
Cargo.lock
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+
[[package]]
+
name = "ahash"
+
version = "0.8.12"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
+
dependencies = [
+
"cfg-if",
+
"getrandom 0.3.3",
+
"once_cell",
+
"version_check",
+
"zerocopy",
+
]
+
+
[[package]]
+
name = "allocator-api2"
+
version = "0.2.21"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
+
+
[[package]]
+
name = "android_system_properties"
+
version = "0.1.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+
dependencies = [
+
"libc",
+
]
+
+
[[package]]
+
name = "arrayref"
+
version = "0.3.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
+
+
[[package]]
+
name = "arrayvec"
+
version = "0.7.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
+
+
[[package]]
+
name = "async-stream"
+
version = "0.3.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
+
dependencies = [
+
"async-stream-impl",
+
"futures-core",
+
"pin-project-lite",
+
]
+
+
[[package]]
+
name = "async-stream-impl"
+
version = "0.3.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn 2.0.106",
+
]
+
+
[[package]]
+
name = "atoi"
+
version = "2.0.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
+
dependencies = [
+
"num-traits",
+
]
+
[[package]]
name = "atomic-waker"
version = "1.1.2"
···
"miniz_oxide",
"object",
"rustc-demangle",
-
"windows-targets",
+
"windows-targets 0.52.6",
]
+
[[package]]
+
name = "base-x"
+
version = "0.2.11"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
+
+
[[package]]
+
name = "base256emoji"
+
version = "1.0.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c"
+
dependencies = [
+
"const-str",
+
"match-lookup",
+
]
+
+
[[package]]
+
name = "base64"
+
version = "0.21.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
+
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+
[[package]]
+
name = "base64ct"
+
version = "1.8.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
+
[[package]]
name = "bitflags"
version = "2.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
+
dependencies = [
+
"serde",
+
]
+
+
[[package]]
+
name = "blake2b_simd"
+
version = "1.0.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "06e903a20b159e944f91ec8499fe1e55651480c541ea0a584f5d967c49ad9d99"
+
dependencies = [
+
"arrayref",
+
"arrayvec",
+
"constant_time_eq",
+
]
[[package]]
name = "block-buffer"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
[[package]]
+
name = "byteorder"
+
version = "1.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
+
[[package]]
name = "bytes"
version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+
[[package]]
+
name = "cbor4ii"
+
version = "0.2.14"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b544cf8c89359205f4f990d0e6f3828db42df85b5dac95d09157a250eb0749c4"
+
dependencies = [
+
"serde",
+
]
+
[[package]]
name = "cc"
version = "1.2.39"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+
[[package]]
+
name = "chrono"
+
version = "0.4.42"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+
dependencies = [
+
"iana-time-zone",
+
"js-sys",
+
"num-traits",
+
"wasm-bindgen",
+
"windows-link 0.2.0",
+
]
+
+
[[package]]
+
name = "cid"
+
version = "0.11.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a"
+
dependencies = [
+
"core2",
+
"multibase",
+
"multihash",
+
"serde",
+
"serde_bytes",
+
"unsigned-varint",
+
]
+
+
[[package]]
+
name = "const-oid"
+
version = "0.9.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+
[[package]]
+
name = "const-str"
+
version = "0.4.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3"
+
+
[[package]]
+
name = "constant_time_eq"
+
version = "0.3.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6"
+
[[package]]
name = "core-foundation"
version = "0.9.4"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
[[package]]
+
name = "core2"
+
version = "0.4.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
+
dependencies = [
+
"memchr",
+
]
+
[[package]]
name = "cpufeatures"
version = "0.2.17"
···
"libc",
]
+
[[package]]
+
name = "crc"
+
version = "3.3.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
+
dependencies = [
+
"crc-catalog",
+
]
+
+
[[package]]
+
name = "crc-catalog"
+
version = "2.4.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
+
+
[[package]]
+
name = "crossbeam-queue"
+
version = "0.3.12"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
+
dependencies = [
+
"crossbeam-utils",
+
]
+
+
[[package]]
+
name = "crossbeam-utils"
+
version = "0.8.21"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
+
[[package]]
name = "crypto-common"
version = "0.1.6"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
+
[[package]]
+
name = "data-encoding-macro"
+
version = "0.1.18"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d"
+
dependencies = [
+
"data-encoding",
+
"data-encoding-macro-internal",
+
]
+
+
[[package]]
+
name = "data-encoding-macro-internal"
+
version = "0.1.16"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976"
+
dependencies = [
+
"data-encoding",
+
"syn 2.0.106",
+
]
+
+
[[package]]
+
name = "der"
+
version = "0.7.10"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
+
dependencies = [
+
"const-oid",
+
"pem-rfc7468",
+
"zeroize",
+
]
+
[[package]]
name = "digest"
version = "0.10.7"
···
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
+
"const-oid",
"crypto-common",
+
"subtle",
]
[[package]]
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
+
]
+
+
[[package]]
+
name = "dotenvy"
+
version = "0.15.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
+
+
[[package]]
+
name = "either"
+
version = "1.15.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
+
dependencies = [
+
"serde",
]
[[package]]
···
"windows-sys 0.61.1",
]
+
[[package]]
+
name = "etcetera"
+
version = "0.8.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
+
dependencies = [
+
"cfg-if",
+
"home",
+
"windows-sys 0.48.0",
+
]
+
+
[[package]]
+
name = "event-listener"
+
version = "2.5.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
+
[[package]]
name = "fastrand"
version = "2.3.0"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
+
[[package]]
+
name = "flume"
+
version = "0.11.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
+
dependencies = [
+
"futures-core",
+
"futures-sink",
+
"spin",
+
]
+
[[package]]
name = "fnv"
version = "1.0.7"
···
"futures-util",
]
+
[[package]]
+
name = "futures-intrusive"
+
version = "0.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
+
dependencies = [
+
"futures-core",
+
"lock_api",
+
"parking_lot",
+
]
+
[[package]]
name = "futures-io"
version = "0.3.31"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
]
[[package]]
···
"tracing",
]
+
[[package]]
+
name = "half"
+
version = "1.8.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403"
+
+
[[package]]
+
name = "hashbrown"
+
version = "0.14.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+
dependencies = [
+
"ahash",
+
"allocator-api2",
+
]
+
[[package]]
name = "hashbrown"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
+
[[package]]
+
name = "hashlink"
+
version = "0.8.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
+
dependencies = [
+
"hashbrown 0.14.5",
+
]
+
+
[[package]]
+
name = "heck"
+
version = "0.4.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
dependencies = [
+
"unicode-segmentation",
+
]
+
+
[[package]]
+
name = "hex"
+
version = "0.4.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
+
[[package]]
+
name = "hkdf"
+
version = "0.12.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
+
dependencies = [
+
"hmac",
+
]
+
+
[[package]]
+
name = "hmac"
+
version = "0.12.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+
dependencies = [
+
"digest",
+
]
+
+
[[package]]
+
name = "home"
+
version = "0.5.11"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
+
dependencies = [
+
"windows-sys 0.59.0",
+
]
+
[[package]]
name = "http"
version = "1.3.1"
···
"http",
"hyper",
"hyper-util",
-
"rustls",
+
"rustls 0.23.32",
"rustls-pki-types",
"tokio",
"tokio-rustls",
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
dependencies = [
-
"base64",
+
"base64 0.22.1",
"bytes",
"futures-channel",
"futures-core",
···
"windows-registry",
]
+
[[package]]
+
name = "iana-time-zone"
+
version = "0.1.64"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
+
dependencies = [
+
"android_system_properties",
+
"core-foundation-sys",
+
"iana-time-zone-haiku",
+
"js-sys",
+
"log",
+
"wasm-bindgen",
+
"windows-core",
+
]
+
+
[[package]]
+
name = "iana-time-zone-haiku"
+
version = "0.1.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+
dependencies = [
+
"cc",
+
]
+
[[package]]
name = "icu_collections"
version = "2.0.0"
···
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
dependencies = [
"equivalent",
-
"hashbrown",
+
"hashbrown 0.16.0",
]
[[package]]
···
"libc",
]
+
[[package]]
+
name = "ipld-core"
+
version = "0.4.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "104718b1cc124d92a6d01ca9c9258a7df311405debb3408c445a36452f9bf8db"
+
dependencies = [
+
"cid",
+
"serde",
+
"serde_bytes",
+
]
+
[[package]]
name = "ipnet"
version = "2.11.0"
···
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
+
dependencies = [
+
"spin",
+
]
[[package]]
name = "libc"
···
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
-
name = "linux-raw-sys"
-
version = "0.11.0"
+
name = "libm"
+
version = "0.2.15"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
+
+
[[package]]
+
name = "libredox"
+
version = "0.1.10"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
+
dependencies = [
+
"bitflags",
+
"libc",
+
"redox_syscall",
+
]
+
+
[[package]]
+
name = "libsqlite3-sys"
+
version = "0.27.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716"
+
dependencies = [
+
"cc",
+
"pkg-config",
+
"vcpkg",
+
]
+
+
[[package]]
+
name = "linux-raw-sys"
+
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
+
[[package]]
+
name = "match-lookup"
+
version = "0.1.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn 1.0.109",
+
]
+
[[package]]
name = "matchit"
version = "0.8.4"
···
"proc-macro2",
"proc-macro2-diagnostics",
"quote",
-
"syn",
+
"syn 2.0.106",
+
]
+
+
[[package]]
+
name = "md-5"
+
version = "0.10.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
+
dependencies = [
+
"cfg-if",
+
"digest",
]
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
+
[[package]]
+
name = "minimal-lexical"
+
version = "0.2.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
[[package]]
name = "miniz_oxide"
version = "0.8.9"
···
"windows-sys 0.59.0",
]
+
[[package]]
+
name = "multibase"
+
version = "0.9.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77"
+
dependencies = [
+
"base-x",
+
"base256emoji",
+
"data-encoding",
+
"data-encoding-macro",
+
]
+
+
[[package]]
+
name = "multihash"
+
version = "0.19.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d"
+
dependencies = [
+
"core2",
+
"serde",
+
"unsigned-varint",
+
]
+
[[package]]
name = "native-tls"
version = "0.2.14"
···
"tempfile",
]
+
[[package]]
+
name = "nom"
+
version = "7.1.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+
dependencies = [
+
"memchr",
+
"minimal-lexical",
+
]
+
[[package]]
name = "nu-ansi-term"
version = "0.50.1"
···
"windows-sys 0.52.0",
]
+
[[package]]
+
name = "num-bigint-dig"
+
version = "0.8.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
+
dependencies = [
+
"byteorder",
+
"lazy_static",
+
"libm",
+
"num-integer",
+
"num-iter",
+
"num-traits",
+
"rand 0.8.5",
+
"smallvec",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "num-integer"
+
version = "0.1.46"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+
dependencies = [
+
"num-traits",
+
]
+
+
[[package]]
+
name = "num-iter"
+
version = "0.1.45"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
+
dependencies = [
+
"autocfg",
+
"num-integer",
+
"num-traits",
+
]
+
+
[[package]]
+
name = "num-traits"
+
version = "0.2.19"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+
dependencies = [
+
"autocfg",
+
"libm",
+
]
+
[[package]]
name = "object"
version = "0.36.7"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
]
[[package]]
···
"libc",
"redox_syscall",
"smallvec",
-
"windows-targets",
+
"windows-targets 0.52.6",
+
]
+
+
[[package]]
+
name = "paste"
+
version = "1.0.15"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
+
+
[[package]]
+
name = "pem-rfc7468"
+
version = "0.7.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
+
dependencies = [
+
"base64ct",
]
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
[[package]]
+
name = "pkcs1"
+
version = "0.7.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
+
dependencies = [
+
"der",
+
"pkcs8",
+
"spki",
+
]
+
+
[[package]]
+
name = "pkcs8"
+
version = "0.10.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+
dependencies = [
+
"der",
+
"spki",
+
]
+
[[package]]
name = "pkg-config"
version = "0.3.32"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
"version_check",
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
+
[[package]]
+
name = "rand"
+
version = "0.8.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+
dependencies = [
+
"libc",
+
"rand_chacha 0.3.1",
+
"rand_core 0.6.4",
+
]
+
[[package]]
name = "rand"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
-
"rand_chacha",
-
"rand_core",
+
"rand_chacha 0.9.0",
+
"rand_core 0.9.3",
+
]
+
+
[[package]]
+
name = "rand_chacha"
+
version = "0.3.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+
dependencies = [
+
"ppv-lite86",
+
"rand_core 0.6.4",
[[package]]
···
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
-
"rand_core",
+
"rand_core 0.9.3",
+
]
+
+
[[package]]
+
name = "rand_core"
+
version = "0.6.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
dependencies = [
+
"getrandom 0.2.16",
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
dependencies = [
-
"base64",
+
"base64 0.22.1",
"bytes",
"encoding_rs",
"futures-core",
···
"windows-sys 0.52.0",
+
[[package]]
+
name = "rs-car"
+
version = "0.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "660d1576a918f8ccab9a98025367f6c1996e7551d5059833ddf0995e2f444cbf"
+
dependencies = [
+
"blake2b_simd",
+
"futures",
+
"ipld-core",
+
"serde_ipld_dagcbor",
+
"sha2",
+
]
+
+
[[package]]
+
name = "rsa"
+
version = "0.9.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b"
+
dependencies = [
+
"const-oid",
+
"digest",
+
"num-bigint-dig",
+
"num-integer",
+
"num-traits",
+
"pkcs1",
+
"pkcs8",
+
"rand_core 0.6.4",
+
"signature",
+
"spki",
+
"subtle",
+
"zeroize",
+
]
+
[[package]]
name = "rustc-demangle"
version = "0.1.26"
···
"windows-sys 0.61.1",
+
[[package]]
+
name = "rustls"
+
version = "0.21.12"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
+
dependencies = [
+
"ring",
+
"rustls-webpki 0.101.7",
+
"sct",
+
]
+
[[package]]
name = "rustls"
version = "0.23.32"
···
dependencies = [
"once_cell",
"rustls-pki-types",
-
"rustls-webpki",
+
"rustls-webpki 0.103.6",
"subtle",
"zeroize",
+
[[package]]
+
name = "rustls-pemfile"
+
version = "1.0.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
+
dependencies = [
+
"base64 0.21.7",
+
]
+
[[package]]
name = "rustls-pki-types"
version = "1.12.0"
···
"zeroize",
+
[[package]]
+
name = "rustls-webpki"
+
version = "0.101.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
+
dependencies = [
+
"ring",
+
"untrusted",
+
]
+
[[package]]
name = "rustls-webpki"
version = "0.103.6"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
[[package]]
+
name = "sct"
+
version = "0.7.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
+
dependencies = [
+
"ring",
+
"untrusted",
+
]
+
[[package]]
name = "security-framework"
version = "2.11.1"
···
[[package]]
name = "serde"
-
version = "1.0.219"
+
version = "1.0.228"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
+
dependencies = [
+
"serde_core",
+
"serde_derive",
+
]
+
+
[[package]]
+
name = "serde_bytes"
+
version = "0.11.19"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
+
dependencies = [
+
"serde",
+
"serde_core",
+
]
+
+
[[package]]
+
name = "serde_cbor"
+
version = "0.11.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
+
dependencies = [
+
"half",
+
"serde",
+
]
+
+
[[package]]
+
name = "serde_core"
+
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
dependencies = [
"serde_derive",
[[package]]
name = "serde_derive"
-
version = "1.0.219"
+
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
+
]
+
+
[[package]]
+
name = "serde_ipld_dagcbor"
+
version = "0.6.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "46182f4f08349a02b45c998ba3215d3f9de826246ba02bb9dddfe9a2a2100778"
+
dependencies = [
+
"cbor4ii",
+
"ipld-core",
+
"scopeguard",
+
"serde",
[[package]]
···
"digest",
+
[[package]]
+
name = "sha2"
+
version = "0.10.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
+
dependencies = [
+
"cfg-if",
+
"cpufeatures",
+
"digest",
+
]
+
[[package]]
name = "sharded-slab"
version = "0.1.7"
···
name = "shitsky"
version = "0.1.0"
dependencies = [
+
"async-stream",
"axum",
-
"base64",
+
"chrono",
+
"cid",
+
"dotenvy",
"futures",
+
"futures-util",
"listenfd",
"maud",
"reqwest",
+
"rs-car",
+
"serde",
+
"serde_bytes",
+
"serde_cbor",
+
"serde_ipld_dagcbor",
+
"serde_json",
+
"sha2",
+
"sqlx",
+
"thiserror 2.0.17",
"tokio",
"tokio-tungstenite",
"tower-http",
"tracing",
"tracing-subscriber",
+
"url",
[[package]]
···
"libc",
+
[[package]]
+
name = "signature"
+
version = "2.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+
dependencies = [
+
"digest",
+
"rand_core 0.6.4",
+
]
+
[[package]]
name = "slab"
version = "0.4.11"
···
"windows-sys 0.59.0",
+
[[package]]
+
name = "spin"
+
version = "0.9.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
+
dependencies = [
+
"lock_api",
+
]
+
+
[[package]]
+
name = "spki"
+
version = "0.7.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+
dependencies = [
+
"base64ct",
+
"der",
+
]
+
+
[[package]]
+
name = "sqlformat"
+
version = "0.2.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790"
+
dependencies = [
+
"nom",
+
"unicode_categories",
+
]
+
+
[[package]]
+
name = "sqlx"
+
version = "0.7.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa"
+
dependencies = [
+
"sqlx-core",
+
"sqlx-macros",
+
"sqlx-mysql",
+
"sqlx-postgres",
+
"sqlx-sqlite",
+
]
+
+
[[package]]
+
name = "sqlx-core"
+
version = "0.7.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6"
+
dependencies = [
+
"ahash",
+
"atoi",
+
"byteorder",
+
"bytes",
+
"chrono",
+
"crc",
+
"crossbeam-queue",
+
"either",
+
"event-listener",
+
"futures-channel",
+
"futures-core",
+
"futures-intrusive",
+
"futures-io",
+
"futures-util",
+
"hashlink",
+
"hex",
+
"indexmap",
+
"log",
+
"memchr",
+
"once_cell",
+
"paste",
+
"percent-encoding",
+
"rustls 0.21.12",
+
"rustls-pemfile",
+
"serde",
+
"serde_json",
+
"sha2",
+
"smallvec",
+
"sqlformat",
+
"thiserror 1.0.69",
+
"tokio",
+
"tokio-stream",
+
"tracing",
+
"url",
+
"webpki-roots",
+
]
+
+
[[package]]
+
name = "sqlx-macros"
+
version = "0.7.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"sqlx-core",
+
"sqlx-macros-core",
+
"syn 1.0.109",
+
]
+
+
[[package]]
+
name = "sqlx-macros-core"
+
version = "0.7.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8"
+
dependencies = [
+
"dotenvy",
+
"either",
+
"heck",
+
"hex",
+
"once_cell",
+
"proc-macro2",
+
"quote",
+
"serde",
+
"serde_json",
+
"sha2",
+
"sqlx-core",
+
"sqlx-mysql",
+
"sqlx-postgres",
+
"sqlx-sqlite",
+
"syn 1.0.109",
+
"tempfile",
+
"tokio",
+
"url",
+
]
+
+
[[package]]
+
name = "sqlx-mysql"
+
version = "0.7.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
+
dependencies = [
+
"atoi",
+
"base64 0.21.7",
+
"bitflags",
+
"byteorder",
+
"bytes",
+
"chrono",
+
"crc",
+
"digest",
+
"dotenvy",
+
"either",
+
"futures-channel",
+
"futures-core",
+
"futures-io",
+
"futures-util",
+
"generic-array",
+
"hex",
+
"hkdf",
+
"hmac",
+
"itoa",
+
"log",
+
"md-5",
+
"memchr",
+
"once_cell",
+
"percent-encoding",
+
"rand 0.8.5",
+
"rsa",
+
"serde",
+
"sha1",
+
"sha2",
+
"smallvec",
+
"sqlx-core",
+
"stringprep",
+
"thiserror 1.0.69",
+
"tracing",
+
"whoami",
+
]
+
+
[[package]]
+
name = "sqlx-postgres"
+
version = "0.7.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
+
dependencies = [
+
"atoi",
+
"base64 0.21.7",
+
"bitflags",
+
"byteorder",
+
"chrono",
+
"crc",
+
"dotenvy",
+
"etcetera",
+
"futures-channel",
+
"futures-core",
+
"futures-io",
+
"futures-util",
+
"hex",
+
"hkdf",
+
"hmac",
+
"home",
+
"itoa",
+
"log",
+
"md-5",
+
"memchr",
+
"once_cell",
+
"rand 0.8.5",
+
"serde",
+
"serde_json",
+
"sha2",
+
"smallvec",
+
"sqlx-core",
+
"stringprep",
+
"thiserror 1.0.69",
+
"tracing",
+
"whoami",
+
]
+
+
[[package]]
+
name = "sqlx-sqlite"
+
version = "0.7.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa"
+
dependencies = [
+
"atoi",
+
"chrono",
+
"flume",
+
"futures-channel",
+
"futures-core",
+
"futures-executor",
+
"futures-intrusive",
+
"futures-util",
+
"libsqlite3-sys",
+
"log",
+
"percent-encoding",
+
"serde",
+
"sqlx-core",
+
"tracing",
+
"url",
+
"urlencoding",
+
]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
[[package]]
+
name = "stringprep"
+
version = "0.1.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
+
dependencies = [
+
"unicode-bidi",
+
"unicode-normalization",
+
"unicode-properties",
+
]
+
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+
[[package]]
+
name = "syn"
+
version = "1.0.109"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"unicode-ident",
+
]
+
[[package]]
name = "syn"
version = "2.0.106"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
[[package]]
···
[[package]]
name = "thiserror"
-
version = "2.0.16"
+
version = "1.0.69"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
+
dependencies = [
+
"thiserror-impl 1.0.69",
+
]
+
+
[[package]]
+
name = "thiserror"
+
version = "2.0.17"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
+
dependencies = [
+
"thiserror-impl 2.0.17",
+
]
+
+
[[package]]
+
name = "thiserror-impl"
+
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
+
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
-
"thiserror-impl",
+
"proc-macro2",
+
"quote",
+
"syn 2.0.106",
[[package]]
name = "thiserror-impl"
-
version = "2.0.16"
+
version = "2.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
+
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
[[package]]
···
"zerovec",
+
[[package]]
+
name = "tinyvec"
+
version = "1.10.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
+
dependencies = [
+
"tinyvec_macros",
+
]
+
+
[[package]]
+
name = "tinyvec_macros"
+
version = "0.1.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+
[[package]]
name = "tokio"
version = "1.47.1"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
dependencies = [
-
"rustls",
+
"rustls 0.23.32",
+
"tokio",
+
]
+
+
[[package]]
+
name = "tokio-stream"
+
version = "0.1.17"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
+
dependencies = [
+
"futures-core",
+
"pin-project-lite",
"tokio",
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
[[package]]
···
"httparse",
"log",
"native-tls",
-
"rand",
+
"rand 0.9.2",
"sha1",
-
"thiserror",
+
"thiserror 2.0.17",
"utf-8",
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+
[[package]]
+
name = "unicode-bidi"
+
version = "0.3.18"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
+
[[package]]
name = "unicode-ident"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+
[[package]]
+
name = "unicode-normalization"
+
version = "0.1.24"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
+
dependencies = [
+
"tinyvec",
+
]
+
+
[[package]]
+
name = "unicode-properties"
+
version = "0.1.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
+
+
[[package]]
+
name = "unicode-segmentation"
+
version = "1.12.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+
+
[[package]]
+
name = "unicode_categories"
+
version = "0.1.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
+
+
[[package]]
+
name = "unsigned-varint"
+
version = "0.8.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06"
+
[[package]]
name = "untrusted"
version = "0.9.0"
···
"serde",
+
[[package]]
+
name = "urlencoding"
+
version = "2.1.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
+
[[package]]
name = "utf-8"
version = "0.7.6"
···
"wit-bindgen",
+
[[package]]
+
name = "wasite"
+
version = "0.1.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
+
[[package]]
name = "wasm-bindgen"
version = "0.2.101"
···
"log",
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
"wasm-bindgen-shared",
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
···
"wasm-bindgen",
+
[[package]]
+
name = "webpki-roots"
+
version = "0.25.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
+
+
[[package]]
+
name = "whoami"
+
version = "1.6.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
+
dependencies = [
+
"libredox",
+
"wasite",
+
]
+
[[package]]
name = "winapi"
version = "0.3.9"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
[[package]]
+
name = "windows-core"
+
version = "0.62.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9"
+
dependencies = [
+
"windows-implement",
+
"windows-interface",
+
"windows-link 0.2.0",
+
"windows-result 0.4.0",
+
"windows-strings 0.5.0",
+
]
+
+
[[package]]
+
name = "windows-implement"
+
version = "0.60.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn 2.0.106",
+
]
+
+
[[package]]
+
name = "windows-interface"
+
version = "0.59.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn 2.0.106",
+
]
+
[[package]]
name = "windows-link"
version = "0.1.3"
···
checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e"
dependencies = [
"windows-link 0.1.3",
-
"windows-result",
-
"windows-strings",
+
"windows-result 0.3.4",
+
"windows-strings 0.4.2",
[[package]]
···
"windows-link 0.1.3",
+
[[package]]
+
name = "windows-result"
+
version = "0.4.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
+
dependencies = [
+
"windows-link 0.2.0",
+
]
+
[[package]]
name = "windows-strings"
version = "0.4.2"
···
"windows-link 0.1.3",
+
[[package]]
+
name = "windows-strings"
+
version = "0.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
+
dependencies = [
+
"windows-link 0.2.0",
+
]
+
+
[[package]]
+
name = "windows-sys"
+
version = "0.48.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+
dependencies = [
+
"windows-targets 0.48.5",
+
]
+
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
-
"windows-targets",
+
"windows-targets 0.52.6",
[[package]]
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
-
"windows-targets",
+
"windows-targets 0.52.6",
[[package]]
···
"windows-link 0.2.0",
+
[[package]]
+
name = "windows-targets"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
+
dependencies = [
+
"windows_aarch64_gnullvm 0.48.5",
+
"windows_aarch64_msvc 0.48.5",
+
"windows_i686_gnu 0.48.5",
+
"windows_i686_msvc 0.48.5",
+
"windows_x86_64_gnu 0.48.5",
+
"windows_x86_64_gnullvm 0.48.5",
+
"windows_x86_64_msvc 0.48.5",
+
]
+
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
-
"windows_aarch64_gnullvm",
-
"windows_aarch64_msvc",
-
"windows_i686_gnu",
+
"windows_aarch64_gnullvm 0.52.6",
+
"windows_aarch64_msvc 0.52.6",
+
"windows_i686_gnu 0.52.6",
"windows_i686_gnullvm",
-
"windows_i686_msvc",
-
"windows_x86_64_gnu",
-
"windows_x86_64_gnullvm",
-
"windows_x86_64_msvc",
+
"windows_i686_msvc 0.52.6",
+
"windows_x86_64_gnu 0.52.6",
+
"windows_x86_64_gnullvm 0.52.6",
+
"windows_x86_64_msvc 0.52.6",
+
[[package]]
+
name = "windows_aarch64_gnullvm"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
+
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
[[package]]
+
name = "windows_aarch64_msvc"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
[[package]]
+
name = "windows_i686_gnu"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
+
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
[[package]]
+
name = "windows_i686_msvc"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
+
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
[[package]]
+
name = "windows_x86_64_gnu"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
[[package]]
+
name = "windows_x86_64_gnullvm"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
[[package]]
+
name = "windows_x86_64_msvc"
+
version = "0.48.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
"synstructure",
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
[[package]]
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
"synstructure",
···
dependencies = [
"proc-macro2",
"quote",
-
"syn",
+
"syn 2.0.106",
+15 -1
Cargo.toml
···
edition = "2024"
[dependencies]
+
async-stream = "0.3.6"
axum = "0.8"
-
base64 = "0.22.1"
+
chrono = "0.4.42"
+
cid = { version = "0.11", features = ["serde-codec"] }
+
dotenvy = "0.15.7"
futures = "0.3.31"
+
futures-util = "0.3.31"
listenfd = "1.0.2"
maud = { version = "0.27", features = ["axum"] }
reqwest = "0.12.23"
+
rs-car = "0.5.0"
+
serde = { version = "1.0", features = ["derive"] }
+
serde_bytes = "0.11.19"
+
serde_cbor = "0.11"
+
serde_ipld_dagcbor = "0.6.4"
+
serde_json = "1.0"
+
sha2 = "0.10"
+
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres", "macros", "json", "chrono"] }
+
thiserror = "2.0.17"
tokio = { version = "1.0", features = ["full"] }
tokio-tungstenite = { version = "0.28.0", features = ["native-tls"] }
tower-http = { version = "0.6", features = ["trace"] }
tracing = "0.1"
tracing-subscriber = "0.3"
+
url = "2.5.7"
+283
src/firehose.rs
···
+
use async_stream::try_stream;
+
use cid::Cid;
+
use futures_util::{
+
TryStreamExt,
+
stream::{Stream, StreamExt},
+
};
+
use serde::{Deserialize, Serialize};
+
use serde_json::Value as JsonValue;
+
use std::collections::HashMap;
+
use std::time::Duration;
+
use thiserror::Error;
+
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
+
+
#[derive(Error, Debug)]
+
pub enum FirehoseError {
+
#[error("WebSocket connection error: {0}")]
+
WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
+
#[error("URL parsing error: {0}")]
+
Url(#[from] url::ParseError),
+
#[error("Failed to deserialize CBOR data: {0}")]
+
Cbor(#[from] std::io::Error),
+
#[error("Failed to read CAR file: {0}")]
+
CarRead(#[from] rs_car::CarDecodeError),
+
#[error("Invalid message frame received from relay")]
+
InvalidFrame,
+
#[error("Received an error message from the relay: {name} - {message}")]
+
RelayError { name: String, message: String },
+
#[error("Unknown message type received: {0}")]
+
UnknownMessageType(String),
+
#[error("Connection timed out after {0:?} without receiving a message")]
+
Timeout(Duration),
+
}
+
+
#[derive(Debug, Clone, Serialize, Deserialize)]
+
#[serde(tag = "action", rename_all = "camelCase")]
+
pub enum RepoOp {
+
Create {
+
path: String,
+
cid: Cid,
+
record: JsonValue,
+
},
+
Update {
+
path: String,
+
cid: Cid,
+
record: JsonValue,
+
},
+
Delete {
+
path: String,
+
},
+
}
+
+
#[derive(Debug, Clone, Serialize, Deserialize)]
+
pub struct CommitEvent {
+
#[serde(rename = "seq")]
+
pub sequence: i64,
+
pub repo: String,
+
pub commit: Cid,
+
pub rev: String,
+
pub since: Option<String>,
+
pub ops: Vec<RepoOp>,
+
#[serde(rename = "time")]
+
pub timestamp: String,
+
}
+
+
#[derive(Debug, Clone, Serialize)]
+
#[serde(untagged)]
+
pub enum FirehoseEvent {
+
Commit(CommitEvent),
+
Info(JsonValue),
+
Account(JsonValue),
+
Identity(JsonValue),
+
Unknown(JsonValue),
+
}
+
+
#[derive(Debug, Clone)]
+
pub struct FirehoseOptions {
+
pub relay_url: String,
+
pub cursor: Option<i64>,
+
pub auto_reconnect: bool,
+
}
+
+
impl Default for FirehoseOptions {
+
fn default() -> Self {
+
Self {
+
relay_url: "wss://relay.upcloud.world".to_string(),
+
cursor: None,
+
auto_reconnect: true,
+
}
+
}
+
}
+
+
#[derive(Deserialize, Debug)]
+
pub struct FrameHeader {
+
#[serde(rename = "op")]
+
operation: i64,
+
#[serde(rename = "t")]
+
message_type: String,
+
}
+
+
#[derive(Deserialize, Debug)]
+
struct ErrorBody {
+
error: String,
+
message: String,
+
}
+
+
#[derive(Deserialize, Debug, Clone)]
+
struct RawRepoOp {
+
action: String,
+
path: String,
+
cid: Option<Cid>,
+
}
+
+
#[derive(Deserialize, Debug)]
+
struct RawCommitEvent {
+
seq: i64,
+
repo: String,
+
commit: Cid,
+
rev: String,
+
since: Option<String>,
+
blocks: serde_bytes::ByteBuf,
+
ops: Vec<RawRepoOp>,
+
time: String,
+
}
+
+
pub fn subscribe_repos(
+
options: FirehoseOptions,
+
) -> impl Stream<Item = Result<FirehoseEvent, FirehoseError>> {
+
let mut last_cursor = options.cursor;
+
+
try_stream! {
+
loop {
+
let mut url_str = format!(
+
"{}/xrpc/com.atproto.sync.subscribeRepos",
+
options.relay_url
+
);
+
if let Some(cursor_val) = last_cursor {
+
url_str.push_str(&format!("?cursor={}", cursor_val));
+
}
+
+
tracing::info!("Connecting to {}...", url_str);
+
+
let (mut ws_stream, _) = connect_async(&url_str).await?;
+
+
tracing::info!("Successfully connected to firehose.");
+
+
loop {
+
let next_message = tokio::time::timeout(
+
Duration::from_secs(15),
+
ws_stream.next()
+
);
+
+
match next_message.await {
+
Err(_) => {
+
tracing::info!("Connection timed out. Attempting to reconnect...");
+
ws_stream.close(None).await?;
+
break;
+
},
+
Ok(Some(Ok(msg))) => {
+
if let Message::Binary(data) = msg {
+
let mut deserializer = serde_ipld_dagcbor::de::Deserializer::from_slice(&data);
+
let map_cbor_err = |e: serde_ipld_dagcbor::DecodeError<std::convert::Infallible>| {
+
std::io::Error::other(e.to_string())
+
};
+
+
let header: FrameHeader = match serde::Deserialize::deserialize(&mut deserializer).map_err(map_cbor_err) {
+
Ok(h) => h,
+
Err(e) => {
+
tracing::error!("Failed to deserialize frame header: {}. Skipping message.", e);
+
continue;
+
}
+
};
+
+
if header.operation == -1 {
+
let body: ErrorBody = match serde::Deserialize::deserialize(&mut deserializer).map_err(map_cbor_err) {
+
Ok(b) => b,
+
Err(e) => {
+
tracing::error!("Failed to deserialize relay error body: {}. Skipping message.", e);
+
continue;
+
}
+
};
+
Err(FirehoseError::RelayError { name: body.error, message: body.message })?;
+
}
+
+
let event = match header.message_type.as_str() {
+
"#commit" => {
+
let raw_commit: RawCommitEvent = match serde::Deserialize::deserialize(&mut deserializer).map_err(map_cbor_err) {
+
Ok(c) => c,
+
Err(e) => {
+
tracing::error!("Failed to deserialize commit body: {}. Skipping message.", e);
+
continue;
+
}
+
};
+
last_cursor = Some(raw_commit.seq);
+
let commit_event = process_commit_event(raw_commit).await?;
+
FirehoseEvent::Commit(commit_event)
+
}
+
t => {
+
let body: JsonValue = match serde::Deserialize::deserialize(&mut deserializer).map_err(map_cbor_err) {
+
Ok(b) => b,
+
Err(e) => {
+
tracing::error!("Failed to deserialize event body for type '{}': {}. Skipping message.", t, e);
+
continue;
+
}
+
};
+
if let Some(seq) = body.get("seq").and_then(|v| v.as_i64()) {
+
last_cursor = Some(seq);
+
}
+
match t {
+
"#info" => FirehoseEvent::Info(body),
+
"#account" => FirehoseEvent::Account(body),
+
"#identity" => FirehoseEvent::Identity(body),
+
_ => FirehoseEvent::Unknown(body)
+
}
+
}
+
};
+
yield event;
+
}
+
}
+
Ok(Some(Err(e))) => {
+
tracing::info!("WebSocket error: {}", e);
+
break;
+
}
+
Ok(None) => {
+
tracing::info!("WebSocket stream closed by server.");
+
break;
+
}
+
}
+
}
+
+
if !options.auto_reconnect {
+
tracing::info!("Auto-reconnect is disabled. Exiting.");
+
break;
+
}
+
tokio::time::sleep(Duration::from_secs(1)).await;
+
}
+
}
+
}
+
+
async fn process_commit_event(raw: RawCommitEvent) -> Result<CommitEvent, FirehoseError> {
+
let mut blocks_reader = raw.blocks.as_ref();
+
let car_reader = rs_car::CarReader::new(&mut blocks_reader, false).await?;
+
+
let records_map: HashMap<Cid, Vec<u8>> = car_reader.try_collect::<HashMap<_, _>>().await?;
+
+
let mut ops = Vec::new();
+
for op in raw.ops {
+
let repo_op = match op.action.as_str() {
+
"create" | "update" => {
+
let cid = op.cid.expect("Create/Update operation must have a CID");
+
let record_bytes = records_map.get(&cid).cloned().unwrap_or_default();
+
let record: JsonValue =
+
serde_ipld_dagcbor::from_slice(&record_bytes).unwrap_or(JsonValue::Null);
+
+
if op.action == "create" {
+
RepoOp::Create {
+
path: op.path,
+
cid,
+
record,
+
}
+
} else {
+
RepoOp::Update {
+
path: op.path,
+
cid,
+
record,
+
}
+
}
+
}
+
"delete" => RepoOp::Delete { path: op.path },
+
_ => continue,
+
};
+
ops.push(repo_op);
+
}
+
+
Ok(CommitEvent {
+
sequence: raw.seq,
+
repo: raw.repo,
+
commit: raw.commit,
+
rev: raw.rev,
+
since: raw.since,
+
ops,
+
timestamp: raw.time,
+
})
+
}
+109 -40
src/main.rs
···
-
use std::sync::Arc;
-
-
use axum::{Extension, Router, routing::get};
-
use base64::{Engine, prelude::BASE64_STANDARD};
-
use futures::{StreamExt as _, lock::Mutex};
+
use axum::{Router, extract::State, routing::get};
+
use chrono::{DateTime, NaiveDateTime, Utc};
+
use futures::StreamExt as _;
use listenfd::ListenFd;
use maud::{DOCTYPE, Markup, html};
-
use reqwest::Url;
+
use serde_json::Value as JsonValue;
+
use sqlx::postgres::PgPoolOptions;
+
use sqlx::{Error, PgPool};
use tokio::net::TcpListener;
-
use tokio_tungstenite::tungstenite::Message;
use tower_http::trace::TraceLayer;
-
type Db = Arc<Mutex<Vec<String>>>;
+
pub mod firehose;
+
use firehose::{FirehoseEvent, FirehoseOptions, subscribe_repos};
+
+
type Db = PgPool;
#[tokio::main]
-
async fn main() {
+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt::init();
+
dotenvy::dotenv().ok();
-
let db = Arc::new(Mutex::new(Vec::new()));
+
let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
+
let pool = PgPoolOptions::new()
+
.max_connections(5)
+
.connect(&db_url)
+
.await?;
-
let web_server_db = db.clone();
-
tokio::spawn(async move { web_server(web_server_db).await });
+
sqlx::migrate!("./migrations").run(&pool).await?;
-
let jetstream_db = db.clone();
-
firehose_subscriber(jetstream_db).await
-
}
+
tracing::info!("Database connected and migrations are up to date.");
-
async fn firehose_subscriber(db: Db) {
-
tracing::info!("Connecting to firehose...");
+
let web_server_pool = pool.clone();
+
tokio::spawn(async move { web_server(web_server_pool).await });
-
let (mut socket, response) = tokio_tungstenite::connect_async(
-
// Url::parse("wss://relay.upcloud.world/xrpc/com.atproto.sync.subscribeRepos")
-
Url::parse("wss://bsky.network/xrpc/com.atproto.sync.subscribeRepos")
-
.unwrap()
-
.as_str(),
-
)
-
.await
-
.unwrap();
+
firehose_subscriber(pool).await;
-
tracing::info!("{:?}", response);
+
Ok(())
+
}
-
tracing::info!("Connected to firehose!");
+
async fn firehose_subscriber(db: Db) {
+
tracing::info!("Starting firehose subscriber...");
+
+
let options = FirehoseOptions {
+
relay_url: "wss://relay.upcloud.world".to_string(),
+
..Default::default()
+
};
-
loop {
-
while let Some(Ok(Message::Binary(message))) = socket.next().await {
-
let msg = BASE64_STANDARD.encode(message);
-
let mut database = db.lock().await;
-
database.push(msg);
+
let mut stream = Box::pin(subscribe_repos(options));
+
+
while let Some(event_result) = stream.next().await {
+
match event_result {
+
Ok(FirehoseEvent::Commit(commit)) => {
+
tracing::debug!(
+
"Received a commit from {} with {} ops",
+
commit.repo,
+
commit.ops.len()
+
);
+
+
match serde_json::to_value(&commit) {
+
Ok(json_value) => {
+
if let Err(e) = create_firehose_record(&db, &json_value).await {
+
tracing::error!("Failed to write record to DB: {}", e);
+
}
+
}
+
Err(e) => {
+
tracing::error!("Failed to serialize commit to JSON: {}", e);
+
}
+
}
+
}
+
Ok(event) => {
+
tracing::info!("Received other event: {:?}", event);
+
}
+
Err(e) => {
+
tracing::error!("Firehose stream error: {}", e);
+
}
}
}
}
···
let app = Router::new()
.route("/", get(index))
-
.layer(Extension(db))
+
.with_state(db)
.layer(TraceLayer::new_for_http());
let mut listenfd = ListenFd::from_env();
···
TcpListener::from_std(listener).unwrap()
}
// otherwise fall back to local listening
-
None => TcpListener::bind("127.0.0.1:3000").await.unwrap(),
+
_none => TcpListener::bind("127.0.0.1:3000").await.unwrap(),
};
-
let server = axum::serve(listener, app);
tracing::info!("Web server started!");
+
axum::serve(listener, app).await.unwrap();
+
}
-
server.await.unwrap();
+
struct FirehoseMessage {
+
message: JsonValue,
}
-
async fn index(Extension(db): Extension<Db>) -> Markup {
-
let borrowed_db = db.lock().await;
-
let items = borrowed_db.iter().rev().take(100).collect::<Vec<&String>>();
+
async fn index(State(db): State<Db>) -> Markup {
+
let query_result = sqlx::query_as!(
+
FirehoseMessage,
+
"SELECT message FROM firehose_messages ORDER BY created_at DESC LIMIT 100"
+
)
+
.fetch_all(&db)
+
.await;
+
+
let items = match query_result {
+
Ok(messages) => messages,
+
Err(e) => {
+
tracing::error!("Failed to fetch messages from DB: {}", e);
+
vec![]
+
}
+
};
page(
"ShitSky",
···
p { "Hello from ShitSky" }
@for item in &items {
pre {
-
(item)
+
(serde_json::to_string_pretty(&item.message).unwrap_or_default())
}
}
},
···
}
}
}
+
+
async fn create_firehose_record(db: &PgPool, record: &JsonValue) -> Result<(), Error> {
+
let created_at_opt: Option<NaiveDateTime> = record
+
.get("time")
+
.and_then(|val| val.as_str())
+
.filter(|s| !s.is_empty())
+
.and_then(|s| s.parse::<DateTime<Utc>>().ok())
+
.map(|dt_utc| dt_utc.naive_utc());
+
+
if let Some(created_at) = created_at_opt {
+
sqlx::query!(
+
"INSERT INTO firehose_messages (message, created_at) VALUES ($1, $2)",
+
record,
+
created_at
+
)
+
.execute(db)
+
.await?;
+
} else {
+
sqlx::query!(
+
"INSERT INTO firehose_messages (message) VALUES ($1)",
+
record,
+
)
+
.execute(db)
+
.await?;
+
}
+
+
Ok(())
+
}