962f7bf05c
Replace the one-shot SSE chat stream with an async dispatch + reconnectable
replay flow so the mobile client survives backgrounding, network blips, and
OS-killed sockets without losing an in-flight agentic turn.
- TurnRegistry/TurnEntry: in-memory per-turn event buffer (cap 500, front
eviction) shared by the agentic loop (writer) and SSE replay readers.
ReplayOutcome + replay_from/next_batch distinguish Events/CaughtUp/Gone;
next_batch registers the Notify before reading state (no lost wakeup) and
drains every buffered event before signaling terminal, so the final
Done/Error is never dropped and the stream closes cleanly.
- Endpoints: POST /insights/chat/turn (202 + turn_id), GET
/insights/chat/turn/{id} (SSE replay, ?skip_before= resume, per-event seq,
410 on eviction), DELETE /insights/chat/turn/{id} (real task abort +
cooperative is_running() check at each loop boundary).
- Cancellation actually stops the task (AbortHandle stored on the entry) and
emits a Done{cancelled:true}; callers skip persistence on cancel.
- Background sweeper drops stale turns; interval clamped to <=300s.
- OpenTelemetry spans: ai.chat.turn.execute/replay/cancel.
- Legacy POST /insights/chat/stream path preserved unchanged.
Tests: registry coverage for terminal delivery (race guard), waiting, Gone,
abort, eviction; handler integration tests for 404/410, skip_before, seq
stamping, completed replay, and cancel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
75 lines
2.2 KiB
TOML
75 lines
2.2 KiB
TOML
[package]
|
|
name = "image-api"
|
|
version = "1.2.0"
|
|
authors = ["Cameron Cordes <cameronc.dev@gmail.com>"]
|
|
edition = "2024"
|
|
|
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
|
|
[profile.release]
|
|
lto = "thin"
|
|
|
|
[profile.dev]
|
|
debug = "line-tables-only"
|
|
|
|
[dependencies]
|
|
actix = "0.13.1"
|
|
actix-web = "4"
|
|
actix-rt = "2.6"
|
|
tokio = { version = "1.42.0", features = ["default", "process", "sync", "macros", "rt-multi-thread"] }
|
|
actix-files = "0.6"
|
|
actix-cors = "0.7"
|
|
actix-multipart = "0.7.2"
|
|
actix-governor = "0.5"
|
|
futures = "0.3.5"
|
|
jsonwebtoken = "9.3.0"
|
|
serde = "1"
|
|
serde_json = "1"
|
|
diesel = { version = "2.2.10", features = ["sqlite"] }
|
|
libsqlite3-sys = "0.35"
|
|
diesel_migrations = "2.2.0"
|
|
chrono = "0.4"
|
|
clap = { version = "4.5", features = ["derive"] }
|
|
dotenv = "0.15"
|
|
bcrypt = "0.17.1"
|
|
image = { version = "0.25.5", default-features = false, features = ["jpeg", "png", "rayon", "webp", "tiff", "avif"] }
|
|
infer = "0.16"
|
|
walkdir = "2.4.0"
|
|
rayon = "1.5"
|
|
path-absolutize = "3.1"
|
|
log = "0.4"
|
|
env_logger = "0.11.5"
|
|
actix-web-prom = "0.9.0"
|
|
prometheus = "0.13"
|
|
lazy_static = "1.5"
|
|
anyhow = "1.0"
|
|
rand = "0.8.5"
|
|
opentelemetry = { version = "0.31.0", features = ["default", "metrics", "tracing"] }
|
|
opentelemetry_sdk = { version = "0.31.0", features = ["default", "rt-tokio-current-thread", "metrics"] }
|
|
opentelemetry-otlp = { version = "0.31.0", features = ["default", "metrics", "tracing", "grpc-tonic"] }
|
|
opentelemetry-stdout = "0.31.0"
|
|
opentelemetry-appender-log = "0.31.0"
|
|
tempfile = "3.20.0"
|
|
regex = "1.11.1"
|
|
exif = { package = "kamadak-exif", version = "0.6.1" }
|
|
reqwest = { version = "0.12", features = ["json", "stream", "multipart"] }
|
|
async-stream = "0.3"
|
|
tokio-util = { version = "0.7", features = ["io"] }
|
|
bytes = "1"
|
|
urlencoding = "2.1"
|
|
zerocopy = "0.8"
|
|
ical = "0.11"
|
|
scraper = "0.20"
|
|
base64 = "0.22"
|
|
blake3 = "1.5"
|
|
image_hasher = "3.0"
|
|
bk-tree = "0.5"
|
|
async-trait = "0.1"
|
|
indicatif = "0.17"
|
|
uuid = { version = "1.10", features = ["v4", "serde"] }
|
|
|
|
# Windows lacks system sqlite3, so re-enable the bundled C build there.
|
|
# Linux/macOS use the system library (faster builds, smaller binary).
|
|
[target.'cfg(windows)'.dependencies]
|
|
libsqlite3-sys = { version = "0.35", features = ["bundled"] }
|