mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-10-06 01:22:16 +00:00
fix: re-fetch queued retries whose local media did not survive a restart
A queued retry that holds a local file — the ugoira MP4, a bsky remux, or a temp file the reupload fallback downloaded — could never succeed after a restart: those files live in the system temp dir and `send::KEEP_ALIVE`, the registry that keeps them alive for the retry, is in memory. The row retried into an upload error, said nothing about why, and dead-lettered the user's link even though the payload carries the `source_url`. `handlers::repair_lost_local_media` now runs in `main` before any worker starts (so no row can be leased while it writes payloads, which is why it can replace them without the lease guard a worker's write-back carries): - `Task::local_media_paths` decides which rows are affected: any local path that is gone. A partially delivered album is left alone — its remaining batches cannot be reconciled with a fresh media list without risking a second copy of what the user already received. - The post is re-fetched from `source_url` through the ordinary `site::fetch`, so a repaired task looks like a first send: fresh media, the chat's caption format, a fresh link-cache snapshot, and a new keep-alive entry when the re-fetch produced another local file. - The delivery envelope (chat, reply, forward/edit settings, notify targets) is kept, the attempt budget restarts, and nothing counts as sent. - A post that cannot be fetched again (gone, withheld, site down) notifies the user with that reason instead of letting the retry die on a missing file. New queue plumbing: `runnable_rows()` (pending + in-progress rows, read before the workers exist) and `replace_payload()` (rewrites the payload, resets `attempts`, marks the row pending). Verified: 5 new offline tests (the two decisions above against a real temp file, the queue scan/replace, and the envelope-preserving rewrite) plus `a_lost_local_media_row_is_refetched_from_its_post`, a live test that seeds a row pointing at a missing file with a real bsky post as its source and asserts the row now carries http(s) media and that nothing was sent — run against the live API here. `cargo fmt`, `cargo clippy --workspace --all-targets --locked -- -D warnings` and `cargo test --workspace --locked` (187 passed, 15 ignored) are clean.
This commit is contained in:
@@ -29,7 +29,7 @@ use upload::{FallbackError, PreparedItem, prepare_upload_item, send_batch_via_up
|
||||
// parts other modules use so call sites stay `send::x`.
|
||||
pub(crate) use post_send::{
|
||||
EDIT_PROMPT_EXPIRED_TEXT, KEEP_ALIVE, Settled, dead_letter_notify, enqueue_retry, handle_task,
|
||||
post_send_actions, settle_task,
|
||||
notify_failure, post_send_actions, settle_task,
|
||||
};
|
||||
|
||||
/// One process-wide Bot for queue workers. Building a fresh Bot (and its HTTP
|
||||
@@ -143,7 +143,7 @@ impl Task {
|
||||
}
|
||||
}
|
||||
|
||||
fn source_url(&self) -> Option<&str> {
|
||||
pub(crate) fn source_url(&self) -> Option<&str> {
|
||||
match self {
|
||||
Task::SendMediaSequence { source_url, .. } | Task::SendAnimation { source_url, .. } => {
|
||||
Some(source_url)
|
||||
@@ -173,9 +173,42 @@ impl Task {
|
||||
}
|
||||
}
|
||||
|
||||
/// The chat this task delivers media to (`None` for a channel copy, which
|
||||
/// names two chats instead).
|
||||
pub(crate) fn chat_id(&self) -> Option<i64> {
|
||||
match self {
|
||||
Task::SendMediaSequence { chat_id, .. } | Task::SendAnimation { chat_id, .. } => {
|
||||
Some(*chat_id)
|
||||
}
|
||||
Task::ForwardMessages { .. } => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Where a failure notice for this task goes (both `None` for a copy with
|
||||
/// nothing to notify).
|
||||
pub(crate) fn notify_target(&self) -> (Option<i64>, Option<i64>) {
|
||||
match self {
|
||||
Task::SendMediaSequence {
|
||||
notify_chat_id,
|
||||
notify_message_id,
|
||||
..
|
||||
}
|
||||
| Task::SendAnimation {
|
||||
notify_chat_id,
|
||||
notify_message_id,
|
||||
..
|
||||
}
|
||||
| Task::ForwardMessages {
|
||||
notify_chat_id,
|
||||
notify_message_id,
|
||||
..
|
||||
} => (*notify_chat_id, *notify_message_id),
|
||||
}
|
||||
}
|
||||
|
||||
/// Local file paths referenced by this task's media (ugoira / bsky remux
|
||||
/// MP4 and the like); empty for URL or Telegram file-id sends.
|
||||
fn local_media_paths(&self) -> Vec<std::path::PathBuf> {
|
||||
pub(crate) fn local_media_paths(&self) -> Vec<std::path::PathBuf> {
|
||||
let mut out = Vec::new();
|
||||
for item in self.media_items() {
|
||||
let is_file_id = match item {
|
||||
|
||||
Reference in New Issue
Block a user