← back to Dw Slideshow Gen
auto-save: 2026-06-29T14:53:15 (2 files) — index.js lib/postiz.js
d018d37b5f28e01bb0536d60240cb53587afc5f6 · 2026-06-29 14:53:38 -0700 · Steve Abrams
Files touched
M index.jsM lib/postiz.js
Diff
commit d018d37b5f28e01bb0536d60240cb53587afc5f6
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jun 29 14:53:38 2026 -0700
auto-save: 2026-06-29T14:53:15 (2 files) — index.js lib/postiz.js
---
index.js | 8 +++++++-
lib/postiz.js | 24 ++++++++++++++++++------
2 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/index.js b/index.js
index a62d698..471eb00 100644
--- a/index.js
+++ b/index.js
@@ -112,7 +112,13 @@ if (cmd === 'post') {
const marker = path.join(dir, 'posted.json')
const id = path.basename(dir)
if (!a.restage && fs.existsSync(marker)) { skipped++; continue } // idempotent: already staged
- const r = await stageToPostiz(dir, process.env, { confirm: a.confirm, channel: a.channel, schedule: a.schedule })
+ let r
+ try {
+ r = await stageToPostiz(dir, process.env, { confirm: a.confirm, channel: a.channel, schedule: a.schedule })
+ } catch (e) { // never let one item kill the whole batch
+ failed++; console.error(` [post ${i}/${dirs.length}] FAIL ${id}: ${e.message}`)
+ continue
+ }
const chNames = (r.channels || []).map(c => c.identifier).join('+')
if (r.staged) {
staged++
diff --git a/lib/postiz.js b/lib/postiz.js
index 13bd90a..a54671a 100644
--- a/lib/postiz.js
+++ b/lib/postiz.js
@@ -21,12 +21,24 @@ export class Postiz {
this.key = apiKey; this.base = base
}
async #json(p, init = {}) {
- const res = await fetch(`${this.base}/public/v1${p}`, {
- ...init, headers: { Authorization: this.key, ...(init.headers || {}) },
- })
- const text = await res.text()
- if (!res.ok) throw new Error(`Postiz ${init.method || 'GET'} ${p} -> ${res.status}: ${text.slice(0, 300)}`)
- try { return text ? JSON.parse(text) : {} } catch { return text }
+ const sleep = ms => new Promise(r => setTimeout(r, ms))
+ const MAX = 6 // retries on throttle / transient 5xx
+ for (let attempt = 0; ; attempt++) {
+ const res = await fetch(`${this.base}/public/v1${p}`, {
+ ...init, headers: { Authorization: this.key, ...(init.headers || {}) },
+ })
+ const text = await res.text()
+ if (res.ok) { try { return text ? JSON.parse(text) : {} } catch { return text } }
+ // retry on 429 (Postiz ThrottlerException) and transient 5xx, honoring Retry-After
+ const retriable = res.status === 429 || res.status === 502 || res.status === 503 || res.status === 504
+ if (retriable && attempt < MAX) {
+ const ra = parseFloat(res.headers.get('retry-after') || '')
+ const wait = Number.isFinite(ra) ? ra * 1000 : Math.min(30000, 1000 * 2 ** attempt) // exp backoff, cap 30s
+ await sleep(wait)
+ continue
+ }
+ throw new Error(`Postiz ${init.method || 'GET'} ${p} -> ${res.status}: ${text.slice(0, 300)}`)
+ }
}
// GET connected channels: [{id, name, identifier, picture, disabled, profile}]
← 0479a3f RESUME.md: render complete (500/500) — resume is now a singl
·
back to Dw Slideshow Gen
·
postiz: unattended drip-resume watcher (throttle-gated, 12s/ a213767 →