Gegenstück zum subscribeRepos-Endpoint: WebSocket-Consumer mit persistiertem seq-Cursor, Reconnect-Backoff und Behandlung von #info/OutdatedCursor. Eigene Cursor-Tabelle statt einer Zeile in jetstream_cursor: dort steht ein time_us in der Größenordnung 1.7e15, die seq ist ein kleiner Zähler ab 1. Geteilt hätte GREATEST den PDS-Cursor sofort in eine Zukunft geschoben, die die PDS nie erreicht. Kein neuer Indexer-Pfad — jede Op wird in die Single-Op-Form übersetzt, die apply_commit schon vom Jetstream kennt. Push und Firehose liefern denselben Commit doppelt; das ist unkritisch, weil die Schreibpfade Upserts sind und der Dedupe-Index der Notifications den Rest abfängt. Mit einem Test festgehalten statt vorausgesetzt. Der CAR-Reader ist neu (es gab nur einen Writer, und der liegt in einem Binary-Crate ohne lib-Target). Der CBOR-Reader arbeitet mit explizitem Offset, weil ein Frame zwei hintereinander geschriebene Werte sind, und akzeptiert CID-Links in beiden Schreibweisen — die Blöcke tragen Strings. /healthz meldet beide Ströme getrennt; sie fallen unabhängig voneinander aus. Verifiziert mit totem Push-Ziel: der Post kam trotzdem an. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013HC9HLrUU1LNwkzp8nkDLX
62 lines
1.9 KiB
TOML
62 lines
1.9 KiB
TOML
[package]
|
|
name = "appview"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
license.workspace = true
|
|
authors.workspace = true
|
|
description = "maarcadetweet AppView (bin)"
|
|
|
|
[lints.rust]
|
|
unsafe_code = "forbid"
|
|
|
|
[lib]
|
|
name = "appview"
|
|
path = "src/lib.rs"
|
|
|
|
[[bin]]
|
|
name = "appview"
|
|
path = "src/main.rs"
|
|
|
|
[dependencies]
|
|
tokio = { workspace = true }
|
|
dotenvy = { workspace = true }
|
|
axum = { workspace = true }
|
|
tower = { workspace = true }
|
|
tower-http = { workspace = true }
|
|
serde = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
tracing = { workspace = true }
|
|
tracing-subscriber = { workspace = true }
|
|
anyhow = { workspace = true }
|
|
sqlx = { workspace = true }
|
|
chrono = { workspace = true }
|
|
async-trait = { workspace = true }
|
|
at-shared = { workspace = true }
|
|
at-firehose = { workspace = true }
|
|
at-crypto = { workspace = true }
|
|
at-identity = { workspace = true }
|
|
reqwest = { workspace = true }
|
|
uuid = { workspace = true }
|
|
rustls = { version = "0.23", default-features = false, features = ["ring", "std", "logging", "tls12"] }
|
|
base64 = { workspace = true }
|
|
futures = { workspace = true }
|
|
# The local PDS firehose (`src/pds_firehose.rs`): a WebSocket carrying
|
|
# DAG-CBOR frames whose `blocks` field is a CAR of record blocks.
|
|
# `tokio-tungstenite` for the socket, `cid` for the block addresses,
|
|
# `ciborium` for the record blocks themselves (they are written with
|
|
# `ciborium::into_writer` on the PDS side, so it is their exact inverse).
|
|
# The frame envelope is decoded by `src/cbor.rs`, which needs no crate.
|
|
tokio-tungstenite = { workspace = true }
|
|
cid = { workspace = true }
|
|
ciborium = { workspace = true }
|
|
|
|
[dev-dependencies]
|
|
tokio = { workspace = true }
|
|
reqwest = { workspace = true }
|
|
serde_json = { workspace = true }
|
|
uuid = { workspace = true }
|
|
# Unit tests in `src/auth.rs` build a P-256 verification key in the
|
|
# same `0x8012 + uncompressed point` encoding the PDS publishes, which
|
|
# needs the curve's `ToEncodedPoint`.
|
|
p256 = { workspace = true }
|