RYO ARENA DOCS
Developer Reference

Inngest Functions

Background job definitions, scheduling logic, and concurrency control.

RYO Arena uses Inngest for durable serverless background jobs. The Inngest webhook is served at /api/inngest. All functions are defined in src/server/inngest/functions.ts.

Functions

scheduledRecheck

Re-analyses a specific token on a recurring schedule.

PropertyValue
Inngest IDscheduled-token-recheck
Trigger eventrecheck/schedule.created
Retries3

Flow:

  1. step.sleep(gapMinutes) — waits for the configured interval
  2. Loads the RecheckSchedule from the database
  3. Early exit if the schedule is disabled or the scheduleVersion has changed (user edited or deleted it)
  4. Claims an optimistic locklockedUntil = now + 10min. If the row is already locked (another job beat us), exit silently.
  5. step.run('run-recheck') — calls runAnalysis(token)
  6. Advances nextRunAt and clears the lock
  7. Sends recheck/schedule.created again to re-queue the next run

alertTriggerCheck

Evaluates alert conditions after re-analysing a token on a user's configured schedule.

PropertyValue
Inngest IDalert-trigger-check
Trigger eventsalerts/trigger.scheduled, alerts/trigger.deleted
Retries3

Flow:

  1. On alerts/trigger.deleted — exits immediately (cancels the sleeping job)
  2. step.sleep(gapMinutes) — waits for the configured interval
  3. Loads AlertTrigger from the database
  4. Early exit if disabled, deleted, or scheduleVersion changed
  5. Checks day-of-week against activeDaysMask
  6. Checks time-of-day against windowStartMin/windowEndMin (UTC)
  7. Claims optimistic lock (lockedUntil = now + 10min)
  8. Snapshots the previous consensus for this token
  9. step.run('run-analysis') — calls runAnalysis(token)
  10. Loads the new consensus for this token
  11. Calls evaluateConditions(conditions, logic, previousSnapshot, newSnapshot)
  12. Creates a TriggerCheck record (fired = conditions.length > 0)
  13. For each fired condition, creates a TriggerEvent record
  14. If notifyEmail and the 1-hour cooldown has elapsed → sendAlertEmail()
  15. Updates lastCheckedAt and lastEmailSentAt
  16. Releases lock, re-queues next run

Concurrency Control

Both functions use optimistic locking via the lockedUntil field on the schedule/trigger row. The lock is claimed with updateMany({ where: { lockedUntil: null OR expired } }). If count !== 1, another job already claimed this run and the current one exits silently.

The scheduleVersion integer provides version-based cancellation: when a user edits, pauses, or deletes a trigger, the version increments. Any sleeping Inngest job that wakes up and finds a mismatched version exits without running the analysis.

Running Locally

# Terminal 1: Next.js dev server
npm run dev

# Terminal 2: Inngest dev server (inspects jobs at http://localhost:8288)
npm run inngest

The Inngest dev runner replays and introspects all function invocations locally without needing real cron infrastructure.

On this page