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.
| Property | Value |
|---|---|
| Inngest ID | scheduled-token-recheck |
| Trigger event | recheck/schedule.created |
| Retries | 3 |
Flow:
step.sleep(gapMinutes)— waits for the configured interval- Loads the
RecheckSchedulefrom the database - Early exit if the schedule is disabled or the
scheduleVersionhas changed (user edited or deleted it) - Claims an optimistic lock —
lockedUntil = now + 10min. If the row is already locked (another job beat us), exit silently. step.run('run-recheck')— callsrunAnalysis(token)- Advances
nextRunAtand clears the lock - Sends
recheck/schedule.createdagain to re-queue the next run
alertTriggerCheck
Evaluates alert conditions after re-analysing a token on a user's configured schedule.
| Property | Value |
|---|---|
| Inngest ID | alert-trigger-check |
| Trigger events | alerts/trigger.scheduled, alerts/trigger.deleted |
| Retries | 3 |
Flow:
- On
alerts/trigger.deleted— exits immediately (cancels the sleeping job) step.sleep(gapMinutes)— waits for the configured interval- Loads
AlertTriggerfrom the database - Early exit if disabled, deleted, or
scheduleVersionchanged - Checks day-of-week against
activeDaysMask - Checks time-of-day against
windowStartMin/windowEndMin(UTC) - Claims optimistic lock (
lockedUntil = now + 10min) - Snapshots the previous consensus for this token
step.run('run-analysis')— callsrunAnalysis(token)- Loads the new consensus for this token
- Calls
evaluateConditions(conditions, logic, previousSnapshot, newSnapshot) - Creates a
TriggerCheckrecord (fired = conditions.length > 0) - For each fired condition, creates a
TriggerEventrecord - If
notifyEmailand the 1-hour cooldown has elapsed →sendAlertEmail() - Updates
lastCheckedAtandlastEmailSentAt - 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 inngestThe Inngest dev runner replays and introspects all function invocations locally without needing real cron infrastructure.