mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-09-23 23:32:05 +00:00
`PREP_SLOTS` caps how many items are prepared at once (6) but says nothing about what they hold: one photo's decode buffer can be up to `MAX_DECODE_BYTES` (512 MiB) and that guard is *per photo*, so six of them — an album of large scans, two chats at once — could peak near 3 GiB on a host sized for a fraction of it. The upload fallback is the only path that allocates like this; nothing downstream notices until the kernel does. Photo preparation now charges a process-wide memory budget (`MEMORY_UNITS` × 64 MiB = 512 MiB) for what it actually holds: the downloaded bytes plus the decode buffer the *header* predicts — the same prediction the per-photo guards apply, now shared (`decode_bytes`, `decode_budget_bytes`) so the reservation and the guard cannot drift. A photo that is already within Telegram's limits is billed only its download, so an ordinary 10-image album still runs several at a time; two photos near the per-photo cap serialize (each takes the whole budget). The request is clamped to the budget so a single huge photo runs alone instead of waiting for permits that cannot exist. Verified with a throwaway harness against a locally served 9999x9999 PNG (126 KB on the wire, ~100 MB decoded) driven through the real `prepare_upload_item`: with the budget held the preparation waits — "after 1516ms the prep is still waiting on the budget" — and finishes in 11.8s the moment it is released, so the accounting binds in the real path and not just in the semaphore. Kept as permanent tests instead: the unit math (rounding, clamp, and that a max-size photo still gets the whole budget rather than waiting forever), the budget sharing (huge decodes cannot overlap, ordinary ones do not queue), and the prediction agreeing with the processing decision (over-sized PNG/JPEG charged, within-limits and unknown formats free). `cargo fmt --check`, `cargo clippy --workspace --all-targets --locked -- -D warnings` and `cargo test --workspace --locked` clean (122 bot + 91 x-media).