Background Jobs
All background jobs use the SafeInterval pattern — a crash-resilient wrapper around setInterval that prevents overlapping executions, catches errors, and sends admin alerts via Telegram.
SafeInterval Features
Crash-resilient: If a job throws, the error is caught and logged — the interval continues
Overlap-safe: If a previous run hasn't finished, the next one is skipped
Admin alerts: All errors automatically sent to admin Telegram DM (rate-limited: 1/min per error type)
Idle-aware: Jobs gate on
activityGate.isActive()to skip when no users are connected (server sleep mode)
Job Schedule
pricePush
30s
Broadcast live token prices to connected WebSocket clients
stuckTrades
5m
Resolve PENDING/SUBMITTED trades stuck > 10 min via on-chain check
premiumExpiration
1h
Downgrade expired premium users, send Telegram notification
escrowRefund
24h
Refund expired escrow tips (30-day claim window)
autoSell
30s
Check TP/SL triggers on premium users' portfolio holdings
queueStats
1m
Log trade queue metrics when queue is non-empty
Job Details
Price Push (30s)
For each connected WebSocket user:
Fetch their wallet token holdings (Alchemy for Base, RPC for Solana)
Get live prices from DEXScreener
Push
prices:updateevent with all token prices + valuesSkips users with no active WebSocket connection
Stuck Trade Resolver (5m)
Catches trades that fell through the cracks:
Query database for trades in
PENDINGorSUBMITTEDstatus > 10 minutes oldFor each stuck trade:
Solana: Query transaction status via RPC
getTransaction()Base: Query transaction receipt via
provider.getTransactionReceipt()
Update trade status to
CONFIRMEDorFAILEDbased on on-chain resultNotify user via WebSocket if status changed
Premium Expiration (1h)
Downgrades users whose premium subscription has expired:
Find users where
isPremium = trueANDpremiumUntil < now()Set
isPremium = falseSend Telegram notification: "Your premium has expired"
Auto-sell monitoring stops for these users on next cycle
Auto-Sell Monitor (30s) — Premium Only
Monitors portfolio positions against take-profit and stop-loss thresholds:
Find all premium users with
autoSellEnabled = trueFor each user, get their open portfolio positions
Fetch current token prices
Check each position:
Take profit: Current price >= buy price * (1 + takeProfitPct / 100)
Stop loss: Current price <= buy price * (1 - stopLossPct / 100)
If triggered, execute a sell-all trade via the trade orchestrator
Send
auto-sell:executedorauto-sell:failedWebSocket event
Queue Stats (1m)
Logs trade queue health metrics when the queue is not empty:
Current queue length
Active (executing) trade count
Pending trade count
Average wait time
Activity Gate (Server Sleep Mode)
To conserve resources on the 512 MB Render instance:
activityGate.isActive()returnstrueonly when at least one WebSocket client is connectedWhen no users are connected, all background jobs skip their execution
The server effectively "sleeps" until a user connects
This prevents unnecessary API calls, RPC queries, and database load during idle periods
Last updated
Was this helpful?