[object Object]

← back to Beverlyhillsvideos

BHV IG poster: don't let a failed post consume a film's rotation slot

5d8bee28f5a09af24b2772dad945db387d124052 · 2026-08-08 07:52:54 -0700 · Steve Abrams

rankByLRU counted any non-dry-run ledger entry as 'recently posted', but a
FAILED live post also writes a non-dry-run entry (error, no mediaId). A
transient Graph API failure therefore benched that film to the back of the
LRU queue for a full pool cycle (weeks) instead of retrying it next slot.
Gate on mediaId (only a PUBLISHED post) so errored films stay front-of-queue.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 5d8bee28f5a09af24b2772dad945db387d124052
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Sat Aug 8 07:52:54 2026 -0700

    BHV IG poster: don't let a failed post consume a film's rotation slot
    
    rankByLRU counted any non-dry-run ledger entry as 'recently posted', but a
    FAILED live post also writes a non-dry-run entry (error, no mediaId). A
    transient Graph API failure therefore benched that film to the back of the
    LRU queue for a full pool cycle (weeks) instead of retrying it next slot.
    Gate on mediaId (only a PUBLISHED post) so errored films stay front-of-queue.
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 social/poster/post-daily.mjs | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/social/poster/post-daily.mjs b/social/poster/post-daily.mjs
index 9b8309d..c5e452e 100644
--- a/social/poster/post-daily.mjs
+++ b/social/poster/post-daily.mjs
@@ -34,11 +34,15 @@ function appendLedger(entry) {
 
 // Order films least-recently-posted first so the library cycles without repeats.
 function rankByLRU(films, ledger) {
-  const lastPosted = new Map(); // slug -> ts of most recent REAL (live) post
+  const lastPosted = new Map(); // slug -> ts of most recent REAL (published) post
   for (const e of ledger) {
-    // Dry-run entries must NOT influence the live rotation, or a dry-tested film
-    // gets skipped on its real turn (and the calendar projection diverges).
-    if (e.slug && !e.dryRun) lastPosted.set(e.slug, e.ts);
+    // Only a SUCCESSFULLY PUBLISHED post (has a mediaId) consumes a film's rotation
+    // slot. Dry-run entries (no mediaId) must not influence rotation, or a dry-tested
+    // film gets skipped on its real turn. A FAILED live post also writes a !dryRun
+    // entry (with `error`, no mediaId) — it must NOT count either, or a transient API
+    // failure silently benches that film for a full pool cycle (weeks) instead of
+    // retrying it next slot.
+    if (e.slug && e.mediaId) lastPosted.set(e.slug, e.ts);
   }
   return films
     .map((f) => ({ film: f, last: lastPosted.get(f.slug) || '' }))

← 1edcf5b auto-data-snapshot: 2026-08-08T06:23:20 (1 data files) — soc  ·  back to Beverlyhillsvideos  ·  auto-data-snapshot: 2026-08-08T08:25:55 (1 data files) — soc 30eed3b →