← back to New Import Viewer
cadence: hourly wrapper (run-cadence.sh, --limit 42 live+publish) + launchd plist (staged, not bootstrapped)
c345dc3cb3aa183862b02841061141bee322dcda · 2026-06-19 09:28:13 -0700 · SteveStudio2
Files touched
A com.steve.dw-cadence.plistA run-cadence.sh
Diff
commit c345dc3cb3aa183862b02841061141bee322dcda
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Fri Jun 19 09:28:13 2026 -0700
cadence: hourly wrapper (run-cadence.sh, --limit 42 live+publish) + launchd plist (staged, not bootstrapped)
---
com.steve.dw-cadence.plist | 52 ++++++++++++++++++++++++++++++++++++++++++++++
run-cadence.sh | 38 +++++++++++++++++++++++++++++++++
2 files changed, 90 insertions(+)
diff --git a/com.steve.dw-cadence.plist b/com.steve.dw-cadence.plist
new file mode 100644
index 0000000..0ae5736
--- /dev/null
+++ b/com.steve.dw-cadence.plist
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+ DW publish cadence — runs run-cadence.sh once per hour (StartInterval 3600),
+ draining 42 published SKUs/tick → ~1,008/day on a staggered schedule.
+
+ ENABLE (Steve pastes):
+ launchctl bootstrap gui/$(id -u) ~/Projects/new-import-viewer/com.steve.dw-cadence.plist
+ DISABLE:
+ launchctl bootout gui/$(id -u)/com.steve.dw-cadence
+
+ The LIVE ceiling lives in EnvironmentVariables below (LAUNCH_CONSUMER_LIVE=1).
+ To pause cadence WITHOUT unloading, flip it to 0 and kickstart — the wrapper
+ then runs dry (safe no-op). NOT KeepAlive: this is a periodic tick, not a daemon,
+ so a finished tick must NOT be respawned immediately.
+-->
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>com.steve.dw-cadence</string>
+
+ <key>ProgramArguments</key>
+ <array>
+ <string>/bin/zsh</string>
+ <string>/Users/stevestudio2/Projects/new-import-viewer/run-cadence.sh</string>
+ </array>
+
+ <key>EnvironmentVariables</key>
+ <dict>
+ <key>LAUNCH_CONSUMER_LIVE</key>
+ <string>1</string>
+ <key>CADENCE_LIMIT</key>
+ <string>42</string>
+ <key>PATH</key>
+ <string>/opt/homebrew/bin:/usr/bin:/bin:/usr/local/bin</string>
+ </dict>
+
+ <key>StartInterval</key>
+ <integer>3600</integer>
+
+ <key>RunAtLoad</key>
+ <false/>
+
+ <key>StandardOutPath</key>
+ <string>/Users/stevestudio2/Projects/new-import-viewer/data/cadence-launchd.out.log</string>
+ <key>StandardErrorPath</key>
+ <string>/Users/stevestudio2/Projects/new-import-viewer/data/cadence-launchd.err.log</string>
+
+ <key>WorkingDirectory</key>
+ <string>/Users/stevestudio2/Projects/new-import-viewer</string>
+</dict>
+</plist>
diff --git a/run-cadence.sh b/run-cadence.sh
new file mode 100755
index 0000000..eb3eaa9
--- /dev/null
+++ b/run-cadence.sh
@@ -0,0 +1,38 @@
+#!/bin/zsh
+# CADENCE WRAPPER — one hourly tick of the staggered 1,000-published-SKUs/24h plan.
+# Drains exactly ONE batch worth (42) of cadence manifests through consumer.js LIVE,
+# creating + publishing 42 PUBLISHED SKUs to the Online Store, then exits.
+#
+# 42/hr × 24h ≈ 1,008/day. consumer.js dedups by id across manifests + is ledgered,
+# so this is idempotent and resumable — a missed hour just means the next tick picks
+# up the same oldest unprocessed rows.
+#
+# GATES (Steve-owned): goes LIVE only when BOTH are present —
+# • env LAUNCH_CONSUMER_LIVE=1 (the Steve ceiling; the plist sets it)
+# • --live + --allow-active (this script passes them so products PUBLISH)
+# Without the env it stays dry-run (safe no-op), so enabling/disabling the cadence
+# is a single env flip in the plist.
+#
+# Daily VARIANT-creation limit: if Shopify returns 429 "Daily variant creation
+# limit", consumer.js retries then fails the row; the ledger records it and the
+# next hour re-attempts. We do NOT hammer — one 42-row tick per hour.
+set -euo pipefail
+
+cd "$(dirname "$0")"
+export PATH="/opt/homebrew/bin:/usr/bin:/bin:/usr/local/bin:$PATH"
+
+LIMIT="${CADENCE_LIMIT:-42}"
+LOG="data/cadence-$(date +%Y%m%d).log"
+TS="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
+
+echo "[$TS] cadence tick start (limit=$LIMIT, live=${LAUNCH_CONSUMER_LIVE:-unset})" >> "$LOG"
+
+# --allow-active makes products ACTIVE; consumer.js then publishablePublish'es each
+# to the Online Store (the 2026-06-19 publish-gap fix). Dry by default unless the
+# env ceiling is set.
+node consumer.js --live --allow-active --limit "$LIMIT" >> "$LOG" 2>&1 || {
+ echo "[$TS] cadence tick exited non-zero (likely dry-refusal or 429) — see log" >> "$LOG"
+ exit 0 # never crash-loop the launchd job; a bad tick is logged, next hour retries
+}
+
+echo "[$(date -u +%Y-%m-%dT%H:%M:%SZ)] cadence tick done" >> "$LOG"
← fb73edf cadence: manifest generator (42/batch, oldest-first round-ro
·
back to New Import Viewer
·
phase8-fix: real create+publish module (mirrors consumer.js b4ec23e →