[object Object]

← back to Dw Slideshow Gen

postiz: unattended drip-resume watcher (throttle-gated, 12s/item, launchd reboot-survivable) to finish the 500-SKU batch

a2137677807bacc04fa4f6cf016c006cf384fd54 · 2026-06-29 15:45:43 -0700 · steve@designerwallcoverings.com

Files touched

Diff

commit a2137677807bacc04fa4f6cf016c006cf384fd54
Author: steve@designerwallcoverings.com <steve@designerwallcoverings.com>
Date:   Mon Jun 29 15:45:43 2026 -0700

    postiz: unattended drip-resume watcher (throttle-gated, 12s/item, launchd reboot-survivable) to finish the 500-SKU batch
---
 drip-resume.sh | 44 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/drip-resume.sh b/drip-resume.sh
new file mode 100755
index 0000000..7e337ea
--- /dev/null
+++ b/drip-resume.sh
@@ -0,0 +1,44 @@
+#!/bin/zsh
+# drip-resume.sh — finish staging the DW 500-SKU carousel batch to Postiz, slowly.
+# Postiz cloud throttles WRITES on a long window; a burst trips a quota that even a
+# single write 429s against. So we (a) gate on a cheap write-probe and wait the window
+# out, then (b) stage ONE carousel at a time with a 12s gap — a sustained rate well
+# under what tripped the quota. Idempotent (per-dir posted.json) so it resumes after
+# any reboot/kill. Self-exits when all 500 are staged.
+setopt NO_NOMATCH
+cd "$HOME/Projects/dw-slideshow-gen" || exit 1
+LOG=output/postiz-drip.log
+CH="tiktok,instagram-standalone"
+KEY=$(grep '^POSTIZ_API_KEY=' .env | cut -d= -f2 | tr -d ' \r')
+count() { find output/renders -name posted.json | wc -l | tr -d ' '; }
+probe() { curl -s -o /dev/null -w "%{http_code}" -X POST https://api.postiz.com/public/v1/posts \
+            -H "Authorization: $KEY" -H "Content-Type: application/json" -d '{"probe":true}'; }
+
+echo "$(date '+%F %T') drip start — $(count)/500 staged" >> $LOG
+while true; do
+  # next unstaged carousel
+  next=""
+  for m in output/renders/*/render-manifest.json; do
+    d=${m:h}; [[ -f "$d/posted.json" ]] || { next=$d; break; }
+  done
+  if [[ -z "$next" ]]; then
+    echo "$(date '+%F %T') ALL 500 STAGED — done" >> $LOG
+    touch output/.drip-done
+    break
+  fi
+  # gate: is the write throttle window open?
+  st=$(probe)
+  if [[ "$st" == "429" ]]; then
+    echo "$(date '+%F %T') throttle hot (429) — waiting 90s [$(count)/500]" >> $LOG
+    sleep 90; continue
+  fi
+  # window open — stage one carousel
+  node index.js post --postiz --channel $CH --confirm "$next" >> $LOG 2>&1
+  if [[ -f "$next/posted.json" ]]; then
+    echo "$(date '+%F %T') OK [$(count)/500] ${next:t}" >> $LOG
+    sleep 12
+  else
+    echo "$(date '+%F %T') FAIL ${next:t} — backoff 60s" >> $LOG
+    sleep 60
+  fi
+done

← d018d37 auto-save: 2026-06-29T14:53:15 (2 files) — index.js lib/post  ·  back to Dw Slideshow Gen  ·  fix(drip): export PATH so launchd run finds node/curl (was s 324ce36 →