Appearance
Historical snapshot archived 2026-09-25. This records an earlier review or plan, not current implementation or live ticket state. For current work, follow root AGENTS.md, the relevant BloxClips skill, and owning repository source/tests. Preserve approved decisions as evidence; verify their present authority before acting.
Background Jobs
Execution model
There is no Redis-backed or durable job queue. Background work runs as timers or setImmediate callbacks inside a Node process. Payloads are generally database IDs captured by closures; concurrency is not centrally configured. Process restarts lose pending timer callbacks, and multiple API replicas would each start their own timers.
Job inventory
| Job | Trigger / cadence | Reads and writes | Retry/failure behavior |
|---|---|---|---|
| Payout request processing | setImmediate after creator request; startup resume | Rescrapes accepted submissions; creates PayoutItems; transitions payout | Durable status allows startup recovery for REQUESTED/SCRAPING; individual scrape outcomes become evidence/failures |
| TIN match drain | API scheduler; initial ~1 minute, then every 15 minutes | Pending Tax1099 submissions/transitions | Poll/retry metadata lives in DB; errors are logged and next tick continues |
| W-8BEN expiry/reminders | initial ~5 minutes, then every 6 hours | Tax forms and reminder timestamps; sends email | Milestone timestamps provide idempotency; failures logged |
| Tax PDF tamper detection | initial ~30 minutes, then every 24 hours | Stored PDFs/hashes and audit state | Reports missing/mismatch; no repair |
| PV autosync | API startup; configurable initial delay/interval (default 24h) | File-backed creators/accounts/videos/snapshots; YouTube/Apify | In-memory running guard; sync state records failures; not durable/cluster-safe |
| Submission view tracking | intended initial 30s, every 30m | Accepted submissions, external metrics, snapshots, campaign freeze state | Per-submission failure count; auto-FLAGGED/stopped after 3 failures |
| Campaign deadline/expiry | intended every minute | Active campaigns; closes, sends reports, edits Discord messages | Per-tick catch/log behavior |
The last two jobs are defined by src/scheduler.ts, but startScheduler(client) has no caller in current TypeScript entrypoints. They are therefore not confirmed running. The payment/tax scheduler and PV autosync are explicitly called from src/api/index.ts.
Payout job chain
mermaid
flowchart TD
Request[POST /api/payouts/request] --> Row[Payout REQUESTED]
Row --> Immediate[setImmediate processPayoutRequest]
Restart[API startup] --> Resume[resumeStuckPayouts]
Resume --> Immediate
Immediate --> Scrape[Payout SCRAPING; rescrape eligible submissions]
Scrape --> Items[Create PayoutItems + badges]
Items --> Review[READY_FOR_REVIEW]
Items --> Low[BELOW_THRESHOLD]
Items --> Fail[FAILED]
Review --> Decision[Admin item decisions]
Decision --> Await[Approve bookkeeping → AWAITING_SEND]
Await --> Send[TOTP-protected explicit send]
Send --> Complete[COMPLETED]
Send --> RailFail[FAILED + bookkeeping reversal when terminal]The request worker has no explicit queue name, concurrency pool, or timeout wrapper. Daily item count and per-user request rate provide some load control. The open-payout partial unique index prevents duplicate concurrent workflows per user.
Submission metric tracking
src/utils/tracking/runTrackingTick.ts selects due ACCEPTED submissions whose campaigns remain eligible. computeNextPollAt uses approximately 12-hour polling during the first 48 hours and 24-hour polling afterward, stopping at the campaign’s trackingDurationDays. Successful scrapes update views/likes/comments, add a ViewSnapshot, and apply budget clamps/freezing. Three consecutive failures flag and stop a submission.
text
Submission accepted
→ acceptedAt/nextPollAt set
→ scheduler selects due row
→ YouTube or Apify scrape
→ metrics and snapshot stored
→ budget clamp/freeze evaluated
→ nextPollAt advanced or trackingStoppedAt setThis flow is implemented but dormant under the visible entrypoints. Administrators and payout requests can still update/rescrape metrics through other paths, which may obscure the missing periodic worker.
PV tracker autosync
The PV tracker is separate from campaign submissions. src/utils/pvTracker.ts reads/writes assets/pv-tracker-state.json (or PV_TRACKER_DATA_PATH), discovers videos for configured social accounts, records snapshots/sync runs, and exposes admin analytics. It uses a module-level running flag rather than a cross-process lock. Back up this file and confirm single-process ownership before operational changes.
Email, webhooks, and SSE
- Email is generally sent inline or fire-and-forget from route/service flows; there is no email queue.
- Payment webhooks are HTTP handlers, not queued consumers. They validate provider signatures and mutate payment state/audit logs.
- Live updates use database polling plus Server-Sent Event heartbeats; SSE is not a background queue and does not use Redis pub/sub. Support chat realtime is provided by Whop ChatElement.
Operational cautions
- Do not run multiple API replicas without accounting for duplicate timer execution and file-backed PV writes.
- Do not rely on in-memory rate limits/caches across instances.
- Payout recovery covers only early processing statuses; review/send operations rely on durable DB state and human action.
- There is a retention timestamp for tax records, but the schema comment explicitly says the deletion job is not implemented.