Skip to content

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 ​

JobTrigger / cadenceReads and writesRetry/failure behavior
Payout request processingsetImmediate after creator request; startup resumeRescrapes accepted submissions; creates PayoutItems; transitions payoutDurable status allows startup recovery for REQUESTED/SCRAPING; individual scrape outcomes become evidence/failures
TIN match drainAPI scheduler; initial ~1 minute, then every 15 minutesPending Tax1099 submissions/transitionsPoll/retry metadata lives in DB; errors are logged and next tick continues
W-8BEN expiry/remindersinitial ~5 minutes, then every 6 hoursTax forms and reminder timestamps; sends emailMilestone timestamps provide idempotency; failures logged
Tax PDF tamper detectioninitial ~30 minutes, then every 24 hoursStored PDFs/hashes and audit stateReports missing/mismatch; no repair
PV autosyncAPI startup; configurable initial delay/interval (default 24h)File-backed creators/accounts/videos/snapshots; YouTube/ApifyIn-memory running guard; sync state records failures; not durable/cluster-safe
Submission view trackingintended initial 30s, every 30mAccepted submissions, external metrics, snapshots, campaign freeze statePer-submission failure count; auto-FLAGGED/stopped after 3 failures
Campaign deadline/expiryintended every minuteActive campaigns; closes, sends reports, edits Discord messagesPer-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 set

This 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.