mirror of
https://github.com/TheFunny/TelegramTwitterMediaBot.git
synced 2026-10-05 01:12:06 +00:00
fix(retry): fence the queue lease, clean up after a kill, name dead-lettered posts
P2 (hardening) of the retry audit, closing the report's remaining findings. - Lease fencing. `lease_next` now stamps a random `lease_token`, and every write-back a worker makes (the 30s heartbeat, `delete_row`, `reschedule`, `mark_done`) is guarded by it. A lease that expired while its holder was stalled and was then re-leased used to let *both* holders write the same row: one duplicated the send, the other silently discarded the new holder's retry (a 0-row update was not even logged). Now a worker that no longer holds the lease drops its attempt at the next heartbeat and writes nothing. Reaching existing databases needed a migration chain, which `db.rs` had been pre-committed to: `MIGRATIONS` + `migrate` track `PRAGMA user_version`, with `schema_init` as the version-0 baseline. Verified on a database created before this change: user_version 0 -> 1, column added, rows intact. - Dead-letter notifications no longer mislabel an unparsable payload. A row whose payload no longer deserializes as a `Task` (an older version's shape, corruption) used to skip the cache invalidation *and* report "Forward failed permanently" for a send task, because both were derived from the parsed value. The identity now comes off the raw JSON, so the stale link-cache entry is dropped and the message names the post. - Temp files are marked and swept. Every temp file/dir the project creates now carries `x_media::TEMP_FILE_PREFIX`, and startup removes entries with that prefix older than an hour — a killed process leaves its downloads (up to hundreds of MB) behind because no destructor runs, and the age gate keeps the sweep away from a second instance's in-flight files. Verified live: the log reports the sweep, an aged leftover goes, a fresh prefixed file and an unrelated file stay.
This commit is contained in:
@@ -899,7 +899,7 @@ mod tests {
|
||||
// A send failure names the post (the cache key) and the cause, so the
|
||||
// user knows which of their links died.
|
||||
let task = sequence_task("https://x.com/u/status/1");
|
||||
let text = super::post_send::failure_text(Some(&task), "retries exhausted");
|
||||
let text = super::post_send::failure_text(task.source_url(), "retries exhausted");
|
||||
assert!(text.contains("twitter:1"), "{text}");
|
||||
assert!(text.contains("retries exhausted"), "{text}");
|
||||
|
||||
@@ -912,7 +912,7 @@ mod tests {
|
||||
notify_chat_id: None,
|
||||
notify_message_id: None,
|
||||
};
|
||||
let text = super::post_send::failure_text(Some(&forward), "chat not found");
|
||||
let text = super::post_send::failure_text(forward.source_url(), "chat not found");
|
||||
assert!(text.starts_with("Forward failed permanently"), "{text}");
|
||||
assert!(text.contains("chat not found"), "{text}");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user