feat(ingest): per-post body-capture + recapture diagnostics logging
CI / lint (push) Successful in 3s
CI / frontend-build (push) Successful in 20s
CI / backend-lint-and-test (push) Successful in 33s
CI / integration (push) Successful in 3m30s

Operator-flagged: a recapture 'caught nothing' for a post and there were no
logs explaining why. Three silent spots now log, so a recapture's per-post
outcome is diagnosable (retention bounds the volume):

- patreon_client.fetch_post_detail_content: the 200-OK-but-null-content branch
  was silent — now logs 'fetched N chars' on success AND 'empty/null content
  (tier-gated or no text)' on the empty case (the most common silent miss).
- patreon_downloader.write_post_record: logs each post's FINAL body outcome
  (captured N chars / NO body) read off the memoized attrs after detail-fetch.
- ingest_core summary: appends post-record + relinked counts to the run summary
  (surfaces on the event stdout the operator already reads).
- download_service phase3: logs how many on-disk images got source_filehash
  relinked (N/total) per recapture.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-14 22:10:59 -04:00
parent 65ec29ba9b
commit b999480db5
5 changed files with 43 additions and 6 deletions
+13 -2
View File
@@ -406,7 +406,9 @@ class DownloadService:
# their post-body inline <img src=CDN> remaps to the local copy. A
# SEPARATE non-deleting channel (NOT the import list — that would unlink
# the duplicate file). Empty outside recapture mode.
for rel_str, rel_url in getattr(dl_result, "relink_source_paths", None) or []:
relink_pairs = getattr(dl_result, "relink_source_paths", None) or []
relinked = 0
for rel_str, rel_url in relink_pairs:
rel_path = Path(rel_str)
if not rel_path.exists(): # noqa: ASYNC240
continue
@@ -414,7 +416,16 @@ class DownloadService:
def _relink(p=rel_path, u=rel_url):
return self.importer.relink_source_filehash(p, u, artist=artist)
await loop.run_in_executor(None, _relink)
if await loop.run_in_executor(None, _relink):
relinked += 1
if relink_pairs:
# recapture diagnostic: how many on-disk images got their
# source_filehash backfilled (inline-image localization). < total is
# normal — files already carrying a filehash are skipped (NULL-only).
log.info(
"recap: relinked source_filehash on %d/%d on-disk image(s)",
relinked, len(relink_pairs),
)
# Kick the off-platform file-host downloader for any links this run
# recorded (mega/gdrive/…). Global + idempotent (only claims pending/