Chapter 6

Testing & Reliability

A Discord-first financial surface fails in ways a typical web app does not. Background workers close abandoned sessions, reconciliation recovers stuck locks, and Vitest covers the math and ledger paths both apps share. CI gates merges, the shared package auto-publishes to npm, and the bot redeploys to a VPS under PM2 so production does not stay down.

Worker schedule and reliability checks
Worker schedule and reliability checks from the ops tooling.

CI, release & VPS deploy

Ops reliability is not only workers and tests. The three-repo split has an explicit ship path: quality gates on every PR, automatic npm publish for shared, and SSH deploy of the Discord bot to a VPS under PM2. (The admin panel is a separate web deploy and is not the focus here.)

  • gambling-bot-discord PRs: GitHub Actions runs coverage, Prettier, ESLint, tsc, build, and Vitest before merge.
  • Push to main triggers deploy: Actions opens SSH to the VPS (retries on flaky connections) and runs the host deploy script as a dedicated deploy user.
  • Production process is PM2 (ecosystem.config.cjs): fork mode, autorestart, 300M memory restart, logs under /var/log/gambling-bot, env loaded from a path outside the app tree.
  • Deploy updates the app and reloads the supervised process so the bot does not stay offline - PM2 keeps it alive and brings it back under the same service definition.
  • gambling-bot-shared: version bump → merge main → release workflow runs checks, builds, and publishes to npm (skips if that version is already on the registry). Consumers bump the dependency when ready.
  • Shared bump script (pnpm bump) + CI release keeps Discord and admin on the same published package instead of drifting private copies.
Why this belongs in the case study

A casino bot that is correct in tests but dies for minutes on every release still loses money and trust. Supervised VPS deploys and an npm release train are part of the reliability story, not side chores.

Background workers

Long-running Discord bots cannot rely on players to finish every session. A shared runWorkerLoop scheduler starts on clientReady and runs idempotent jobs on intervals defined in workerDefinitions.ts. Optional worker-log channels surface what ran. The full schedule is cataloged in docs/WORKERS_STRUCTURE.txt.

Economy & engagement

  • VIP expiry warning + expiration (~1 min).
  • Prediction autolock (~1 min).
  • Raffle auto-draw (~1 min) with reschedule.
  • Guild settings sync (~6h) - normalize configs.
  • Ban role sync (~6h) - Discord roles vs DB.
  • Guild orphan cleanup (~1d) - left guilds.

Session recovery

  • In-flight recovery (~1 min) - finish or refund after crash.
  • Idle nudge / close for table games (~3h / ~24h).
  • Blackjack autostand on stalled hands.
  • Mines auto-resolve: cash out or forfeit.
  • Hi-Lo idle: nudge, cash-out, or auto-guess.
  • Lock reconciliation (~15m) - clear stuck locks.

Command & worker catalogs

The Discord repo keeps machine-readable docs next to the code so the player/mod surface and the background schedule stay reviewable without spelunking folders.

  • docs/COMMANDS_STRUCTURE.txt - full slash-command tree: player (misc) ATM / casino / utils vs mod auth, setup-*, events, and ops tools (ban, history, manage-balance, money-manager, …).
  • docs/WORKERS_STRUCTURE.txt - every job with interval, start delay, and a one-line purpose (from VIP expiry to plinko idle close).
  • Generated / updated from the live CommandKit command tree and workerDefinitions so docs do not quietly drift from production behavior.
  • Dev helpers (/mock-db, /mock-worker-db, /clear-mock-db) seed users, MockUserProfile avatars, and intentionally broken state for admin UI and workers.

Testing & quality

Correctness is part of the product. All three repos run Vitest (unit + integration where relevant), ESLint, Prettier, and tsc --noEmit via pnpm check.

  • Unit: blackjack/baccarat/mines/hilo engines (incl. continuous streak settle), European roulette planSpin/infer, plinko path/render, RTP helpers (incl. side bets), bet validation, cooldowns, slip merge helpers.
  • Integration: casinoBet sessions, plinko session DB + recovery, daily bonus claims, prediction bets, raffle DB, VIP DB, workers (autolock, raffle draw, blackjack autostand, idle resolve).
  • mongodb-memory-server for hermetic database tests.
  • Shared package tests cover domain math used by both bot and admin (incl. roulette win/RTP over the European wheel).
  • Moderator simulate / audit scripts for economy stress and jackpot-style math checks.

Hard problems

Building a Discord-first financial surface forces trade-offs a typical web app does not hit as hard.

  • Concurrency - MongoDB transactions + unique betId indexes prevent double-spend and duplicate settlement when users spam interactions.
  • Dual balance - bonus-first bet consumption and locked balance keep withdrawable cash honest while still rewarding streak/quest play.
  • Abandoned sessions - multi-step Discord UIs (blackjack splits, baccarat slips, mines boards, plinko drop batches, hi-lo streaks) need idle workers, in-flight recovery, and lock reconciliation.
  • Config drift - central package + Zod schemas + guild sync worker keep bot memory and dashboard writes aligned.
  • Permission model - dashboard distinguishes Discord Administrator vs configured manager role; settings UI hidden from limited managers.
  • RP safety - gated ATM and audited staff actions document every sensitive balance change for moderator review.
  • Multi-bet complexity - slips and multi-hand blackjack must lock the right totals, settle line-by-line, and still refund cleanly on cancel/idle close.

Repos & community

Scope

The platform is complete for its current product surface. New games or dashboard panels can still be added, but the multi-repo architecture, economy, casino sessions, engagement systems, workers, and admin ops are in place.