This application is being created to run a wrestling tournament.
License: MIT License
Public Production Url: https://wrestlingdev.com
App Info
- Ruby 3.2.0
- Rails 8.0.2
- DB MySQL/MariaDB
- Solid Cache -> MySQL/MariaDB for html partial caching
- Solid Queue -> MySQL/MariaDB for background job processing
- Solid Cable -> MySQL/MariaDB for websocket channels
- Hotwired Stimulus for client-side JavaScript
All dependencies are wrapped in docker. Tests can be run with bash bin/run-tests-with-docker.sh. That is the same command used in CI.
If you want to run a full rails environment shell in docker run: bash bin/rails-dev-run.sh wrestlingdev-dev
From here, you can run the normal rails commands.
Special rake tasks:
tournament:assign_random_winswill complete all matches for tournament 204 from seed data. This task takes a while since it waits for the worker to complete tasks. In my testing, it takes about 3.5 hours to complete.rake tournament:assign_random_winsto run locallydocker-compose -f deploy/docker-compose-test.yml exec -T app rails tournament:assign_random_winsto run on the dev server
To deploy a full local version of the app bash deploy/deploy-test.sh (this requires docker-compose to be installed). This deploys a full version of the app including Rails app, Solid Queue background workers, Memcached, and MariaDB. Now, you can open http://localhost.
In development environments, background jobs run inline (synchronously) by default. In production and staging environments, jobs are processed asynchronously by separate worker processes.
To run a single test file:
- Get a shell with ruby and rails:
bash bin/rails-dev-run.sh wrestlingdev-development rake test TEST=test/models/match_test.rb
To run a single test inside a file:
- Get a shell with ruby and rails:
bash bin/rails-dev-run.sh wrestlingdev-development rake test TEST=test/models/match_test.rb TESTOPTS="--name='/test_Match_should_not_be_valid_if_an_incorrect_win_type_is_given/'"
With rvm installed, run rvm install ruby-3.2.0
Then, cd ../; cd wrestlingApp. This will load the gemset file in this repo.
You can run one-off Rails commands without installing Rails locally by using the development Docker image:
# Build the development image
docker build -t wrestlingdev-dev -f deploy/rails-dev-Dockerfile .
# Run a specific Rails command
docker run -it -v $(pwd):/rails wrestlingdev-dev rails db:migrate
# Run the Rails console
docker run -it -v $(pwd):/rails wrestlingdev-dev rails console
# Run a custom Rake task
docker run -it -v $(pwd):/rails wrestlingdev-dev rake jobs:create_runningThis approach is useful for quick commands without the need to set up a full development environment. The image contains all required dependencies for the application.
For a more convenient experience with a persistent shell, use the included wrapper script:
bash bin/rails-dev-run.sh wrestlingdev-devWhether you have a shell from docker or are using rvm you can now run normal rails commands:
bundle config set --local without 'production'bundle installrake db:seedDevelopment login email from seed data:test@test.compassword:passwordrake testrails generate blah blah blahrails s -b 0.0.0.0port 3000 is exposed. You can open http://localhost:3000 after running that command- etc.
rake finish_seed_tournamentswill complete all matches from the seed data. This command takes about 5 minutes to executerake assets:clobber- removes previously compiled assets stored inpublic/assetsforcing Rails to recompile them from scratch the next time they are requested.
To help with testing the job status display in the UI, several rake tasks are provided:
# Create a test "Running" job for the first tournament
rails jobs:create_running
# Create a test "Completed" job for the first tournament
rails jobs:create_completed
# Create a test "Error" job for the first tournament
rails jobs:create_failedSee SOLID_QUEUE.md for more details about the job system.
bash bin/rails-dev-run.sh wrestlingdev-devto open a contianer with a rails shell availablebundle config --delete withoutto remove the bundle config that ignores production gemsbundle updatebundle config set --local without 'production'to reset your without locally
Note: If updating rails, do not change the version in Gemfile until after you run bash bin/rails-dev-run.sh wrestlingdev-dev. Creating the container will fail due to a mismatch in Gemfile and Gemfile.lock.
Then run rails app:update to update rails.
The application uses Hotwired Stimulus for client-side JavaScript interactivity. Controllers can be found in app/asssets/javascripts/controllers
The Stimulus controllers are tested using Cypress end-to-end tests:
# Run Cypress tests in headless mode
bash cypress-tests/run-cypress-tests.shThe production version of this is currently deployed in Kubernetes (via K3s). See Deploying with Kubernetes
I'm using a Hetzner dedicated server with an i7-8700, 500GB NVME (RAID1), and 64GB ECC RAM. I have a hot standby (SQL read only replication) in my homelab.
The application uses an intelligent auto-scaling configuration for Puma (the web server) and SolidQueue (background job processing):
- Auto Detection: The server automatically detects available CPU cores and memory, and scales accordingly.
- Worker Scaling: In production, the number of Puma workers is calculated based on available memory (assuming ~400MB per worker) and CPU cores.
- Thread Configuration: Each Puma worker uses 5-12 threads by default, optimized for mixed I/O and CPU workloads.
- SolidQueue Integration: When
SOLID_QUEUE_IN_PUMA=true, background jobs run within the Puma process. - Database Connection Pool: Automatically sized based on the maximum number of threads across all workers.
All of these settings can be overridden with environment variables if needed.
To see the current configuration in the logs, look for these lines on startup:
Puma starting with X worker(s), Y-Z threads per worker
Available system resources: X CPU(s), YMMMB RAM
SolidQueue plugin enabled in Puma
I have deployed Mission Control as a UI for SolidQueue. The uri for mission control is /jobs.
For the development environment, the user/password is dev/secret. For the production environment, it is defined by environment variables WRESTLINGDEV_MISSION_CONTROL_USER/WRESTLINGDEV_MISSION_CONTROL_PASSWORD. You can see this in config/environments/production.rb and config/environments/development.rb.
WRESTLINGDEV_DB_NAME- Database name for the main applicationWRESTLINGDEV_DB_USR- Database usernameWRESTLINGDEV_DB_PWD- Database passwordWRESTLINGDEV_DB_HOST- Database hostnameWRESTLINGDEV_DB_PORT- Database portWRESTLINGDEV_DEVISE_SECRET_KEY- Secret key for Devise (can be generated withrake secret)WRESTLINGDEV_SECRET_KEY_BASE- Rails application secret key (can be generated withrake secret)WRESTLINGDEV_EMAIL- Email address (currently must be a Gmail account)WRESTLINGDEV_EMAIL_PWD- Email passwordWRESTLINGDEV_MISSION_CONTROL_USER- mission control usernameWRESTLINGDEV_MISSION_CONTROL_PASSWORD- mission control password
SOLID_QUEUE_IN_PUMA- Set to "true" to run Solid Queue workers inside Puma (default in development)WEB_CONCURRENCY- Number of Puma workers (auto-detected based on CPU/memory if not specified)RAILS_MIN_THREADS- Minimum number of threads per Puma worker (defaults to 5)RAILS_MAX_THREADS- Maximum number of threads per Puma worker (defaults to 12)DATABASE_POOL_SIZE- Database connection pool size (auto-calculated if not specified)SOLID_QUEUE_WORKERS- Number of SolidQueue workers (auto-calculated if not specified)SOLID_QUEUE_THREADS- Number of threads per SolidQueue worker (auto-calculated if not specified)PORT- Port for Puma server to listen on (defaults to 3000)RAILS_LOG_LEVEL- Log level for Rails in production (defaults to "info")PIDFILE- PID file location for PumaRAILS_SSL_TERMINATION- Set to "true" to enable force_ssl in production (HTTPS enforcement)REVERSE_PROXY_SSL_TERMINATION- Set to "true" if the app is behind a SSL-terminating reverse proxyCI- Set in CI environments to enable eager loading in test environmentWRESTLINGDEV_NEW_RELIC_LICENSE_KEY- New Relic license key for monitoring
WRESTLINGDEV_INFLUXDB_DATABASE- InfluxDB database nameWRESTLINGDEV_INFLUXDB_HOST- InfluxDB hostnameWRESTLINGDEV_INFLUXDB_PORT- InfluxDB portWRESTLINGDEV_INFLUXDB_USERNAME- InfluxDB username (optional)WRESTLINGDEV_INFLUXDB_PASSWORD- InfluxDB password (optional)
This project provides multiple ways to develop and deploy, with Docker being the primary method.
- Propshaft will automatically include in its search paths the folders vendor/assets, lib/assets and app/assets of your project and of all the gems in your Gemfile. You can see all included files by using the reveal rake task:
rake assets:reveal. When importing you'll use the relative path from this command. - All css files are imported via
app/assets/stylesheets/application.css. This is imported onapp/views/layouts/application.html.erb.- Bootstrap and fontawesome have been downloaded locally to
vendor/
- Bootstrap and fontawesome have been downloaded locally to
- All js files are imported with a combination of "pinning" with
config/importmaps.rbandapp/assets/javascript/application.jsand imported toapp/views/layouts/application.html.erb- Jquery, bootstrap, datatables have been downloaded locally to
vendor/ - Turbo and action cable are gems and get pathed properly by propshaft.
- Jquery, bootstrap, datatables have been downloaded locally to
- development is "nobuild" with
config.assets.build_assets = falseinconfig/environments/development.rb - production needs to run rake assets:precompile. This is done in the
deploy/rails-prod-Dockerfile.
The application has been migrated from using vanilla JavaScript to Hotwired Stimulus. The Stimulus controllers are organized in:
app/assets/javascripts/controllers/- Contains all Stimulus controllersapp/assets/javascripts/application.js- Registers and loads all controllers
The importmap configuration in config/importmap.rb handles the loading of all JavaScript dependencies including Stimulus controllers.
npx repomix app test