├── .github └── workflows │ ├── judoscale-delayed_job-test.yml │ ├── judoscale-good_job-test.yml │ ├── judoscale-que-test.yml │ ├── judoscale-rack-test.yml │ ├── judoscale-rails-test.yml │ ├── judoscale-resque-test.yml │ ├── judoscale-ruby-test.yml │ ├── judoscale-shoryuken-test.yml │ ├── judoscale-sidekiq-benchmarks.yml │ ├── judoscale-sidekiq-test.yml │ ├── judoscale-solid_queue-test.yml │ ├── lint.yml │ └── release.yml ├── .gitignore ├── .standard.yml ├── .vscode └── tasks.json ├── CHANGELOG.md ├── LICENSE.txt ├── README.md ├── bin ├── console ├── foreach ├── release ├── test ├── update-dev-deps └── update-sample-deps ├── judoscale-delayed_job ├── Gemfile ├── Gemfile-activerecord-6 ├── Gemfile-activerecord-7 ├── Gemfile.lock ├── Rakefile ├── judoscale-delayed_job.gemspec ├── lib │ ├── judoscale-delayed_job.rb │ ├── judoscale │ │ ├── delayed_job.rb │ │ └── delayed_job │ │ │ └── metrics_collector.rb │ └── rails-autoscale-delayed_job.rb ├── rails-autoscale-delayed_job.gemspec └── test │ ├── adapter_test.rb │ ├── metrics_collector_test.rb │ └── test_helper.rb ├── judoscale-good_job ├── Gemfile ├── Gemfile-activerecord-6 ├── Gemfile-activerecord-7 ├── Gemfile.lock ├── Rakefile ├── judoscale-good_job.gemspec ├── lib │ ├── judoscale-good_job.rb │ ├── judoscale │ │ ├── good_job.rb │ │ └── good_job │ │ │ └── metrics_collector.rb │ └── rails-autoscale-good_job.rb ├── rails-autoscale-good_job.gemspec └── test │ ├── adapter_test.rb │ ├── metrics_collector_test.rb │ └── test_helper.rb ├── judoscale-que ├── Gemfile ├── Gemfile-activerecord-6 ├── Gemfile-activerecord-7 ├── Gemfile-que-1 ├── Gemfile.lock ├── Rakefile ├── judoscale-que.gemspec ├── lib │ ├── judoscale-que.rb │ ├── judoscale │ │ ├── que.rb │ │ └── que │ │ │ └── metrics_collector.rb │ └── rails-autoscale-que.rb ├── rails-autoscale-que.gemspec └── test │ ├── adapter_test.rb │ ├── metrics_collector_test.rb │ └── test_helper.rb ├── judoscale-rack ├── Gemfile ├── Gemfile-rack-2 ├── Gemfile.lock ├── Rakefile ├── judoscale-rack.gemspec ├── lib │ ├── judoscale-rack.rb │ ├── judoscale │ │ └── rack.rb │ └── rails-autoscale-rack.rb ├── rails-autoscale-rack.gemspec └── test │ ├── adapter_test.rb │ ├── app_test.rb │ └── test_helper.rb ├── judoscale-rails ├── Gemfile ├── Gemfile-rails-6-1 ├── Gemfile-rails-7-0 ├── Gemfile-rails-7-1 ├── Gemfile-rails-7-2 ├── Gemfile.lock ├── Rakefile ├── judoscale-rails.gemspec ├── lib │ ├── judoscale-rails.rb │ ├── judoscale │ │ ├── rails.rb │ │ └── rails │ │ │ ├── config.rb │ │ │ ├── railtie.rb │ │ │ └── utilization_middleware.rb │ └── rails-autoscale-web.rb ├── rails-autoscale-web.gemspec └── test │ ├── adapter_test.rb │ ├── app_test.rb │ ├── config_test.rb │ ├── railtie_test.rb │ ├── test_helper.rb │ └── utilization_middleware_test.rb ├── judoscale-resque ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── judoscale-resque.gemspec ├── lib │ ├── judoscale-resque.rb │ ├── judoscale │ │ ├── resque.rb │ │ └── resque │ │ │ ├── latency_extension.rb │ │ │ └── metrics_collector.rb │ └── rails-autoscale-resque.rb ├── rails-autoscale-resque.gemspec └── test │ ├── adapter_test.rb │ ├── latency_extension_test.rb │ ├── metrics_collector_test.rb │ └── test_helper.rb ├── judoscale-ruby ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── judoscale-ruby.gemspec ├── lib │ ├── judoscale-ruby.rb │ ├── judoscale │ │ ├── adapter_api.rb │ │ ├── config.rb │ │ ├── job_metrics_collector.rb │ │ ├── job_metrics_collector │ │ │ └── active_record_helper.rb │ │ ├── logger.rb │ │ ├── metric.rb │ │ ├── metrics_collector.rb │ │ ├── metrics_store.rb │ │ ├── report.rb │ │ ├── reporter.rb │ │ ├── request_metrics.rb │ │ ├── request_middleware.rb │ │ ├── version.rb │ │ └── web_metrics_collector.rb │ └── rails-autoscale-core.rb ├── rails-autoscale-core.gemspec └── test │ ├── adapter_api_test.rb │ ├── adapter_test.rb │ ├── config_test.rb │ ├── job_metrics_collector_test.rb │ ├── logger_test.rb │ ├── metric_test.rb │ ├── metrics_store_test.rb │ ├── reporter_test.rb │ ├── request_metrics_test.rb │ ├── request_middleware_test.rb │ ├── support │ ├── config_helpers.rb │ ├── env_helpers.rb │ ├── log_helpers.rb │ └── time_helpers.rb │ ├── test_helper.rb │ └── web_metrics_collector_test.rb ├── judoscale-shoryuken ├── Gemfile ├── Gemfile.lock ├── Rakefile ├── judoscale-shoryuken.gemspec ├── lib │ ├── judoscale-shoryuken.rb │ ├── judoscale │ │ ├── shoryuken.rb │ │ └── shoryuken │ │ │ └── metrics_collector.rb │ └── rails-autoscale-shoryuken.rb ├── rails-autoscale-shoryuken.gemspec └── test │ ├── adapter_test.rb │ ├── metrics_collector_test.rb │ └── test_helper.rb ├── judoscale-sidekiq ├── Gemfile ├── Gemfile-sidekiq-5 ├── Gemfile-sidekiq-6 ├── Gemfile-sidekiq-7 ├── Gemfile.lock ├── Rakefile ├── judoscale-sidekiq.gemspec ├── lib │ ├── judoscale-sidekiq.rb │ ├── judoscale │ │ ├── sidekiq.rb │ │ └── sidekiq │ │ │ └── metrics_collector.rb │ └── rails-autoscale-sidekiq.rb ├── rails-autoscale-sidekiq.gemspec └── test │ ├── adapter_test.rb │ ├── benchmarks │ └── collect_with_large_queues_benchmark.rb │ ├── metrics_collector_test.rb │ └── test_helper.rb ├── judoscale-solid_queue ├── Gemfile ├── Gemfile-solid_queue-0-3 ├── Gemfile.lock ├── Rakefile ├── judoscale-solid_queue.gemspec ├── lib │ ├── judoscale-solid_queue.rb │ ├── judoscale │ │ ├── solid_queue.rb │ │ └── solid_queue │ │ │ └── metrics_collector.rb │ └── rails-autoscale-solid_queue.rb ├── rails-autoscale-solid_queue.gemspec └── test │ ├── adapter_test.rb │ ├── metrics_collector_test.rb │ └── test_helper.rb └── sample-apps ├── .gitattributes ├── .gitignore ├── delayed_job-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── jobs_controller.rb │ ├── jobs │ │ └── sample_job.rb │ └── views │ │ ├── jobs │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── delayed_job │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── credentials.yml.enc │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ └── judoscale.rb │ ├── puma.rb │ └── routes.rb ├── db │ ├── migrate │ │ └── 20220405002624_create_delayed_jobs.rb │ └── schema.rb └── log │ └── .keep ├── good_job-multi-db-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── jobs_controller.rb │ ├── jobs │ │ ├── application_job.rb │ │ └── sample_job.rb │ └── views │ │ ├── jobs │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── credentials.yml.enc │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ ├── good_job.rb │ │ └── judoscale.rb │ ├── puma.rb │ └── routes.rb ├── db │ ├── good_job_db_migrate │ │ └── 20240708144259_create_good_jobs.rb │ ├── good_job_db_schema.rb │ └── schema.rb └── log │ └── .keep ├── good_job-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── jobs_controller.rb │ ├── jobs │ │ ├── application_job.rb │ │ └── sample_job.rb │ └── views │ │ ├── jobs │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── credentials.yml.enc │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ └── judoscale.rb │ ├── puma.rb │ └── routes.rb ├── db │ ├── migrate │ │ └── 20240708143542_create_good_jobs.rb │ └── schema.rb └── log │ └── .keep ├── que-2-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── jobs_controller.rb │ ├── jobs │ │ └── sample_job.rb │ └── views │ │ ├── jobs │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── credentials.yml.enc │ ├── database.yml │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ └── judoscale.rb │ ├── puma.rb │ └── routes.rb ├── db │ ├── migrate │ │ └── 20220405005248_create_que_schema.rb │ └── structure.sql └── log │ └── .keep ├── rails-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── home_controller.rb │ └── views │ │ ├── home │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── credentials.yml.enc │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ └── judoscale.rb │ ├── puma.rb │ └── routes.rb └── log │ └── .keep ├── resque-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── jobs_controller.rb │ ├── jobs │ │ └── sample_job.rb │ └── views │ │ ├── jobs │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── credentials.yml.enc │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ └── judoscale.rb │ ├── puma.rb │ └── routes.rb └── log │ └── .keep ├── shoryuken-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── jobs_controller.rb │ ├── jobs │ │ ├── application_job.rb │ │ └── sample_job.rb │ └── views │ │ ├── jobs │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ └── judoscale.rb │ ├── puma.rb │ ├── routes.rb │ └── shoryuken.yml └── log │ └── .keep ├── sidekiq-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app │ ├── controllers │ │ ├── application_controller.rb │ │ └── jobs_controller.rb │ ├── jobs │ │ └── sample_job.rb │ └── views │ │ ├── jobs │ │ └── index.html.erb │ │ └── layouts │ │ └── application.html.erb ├── bin │ ├── bundle │ ├── dev │ ├── rails │ ├── rake │ └── setup ├── config.ru ├── config │ ├── application.rb │ ├── boot.rb │ ├── credentials.yml.enc │ ├── environment.rb │ ├── environments │ │ └── development.rb │ ├── initializers │ │ └── judoscale.rb │ ├── puma.rb │ └── routes.rb └── log │ └── .keep ├── sinatra-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── bin │ └── dev ├── config.ru └── hello.rb └── solid_queue-sample ├── Gemfile ├── Gemfile.lock ├── Procfile ├── README.md ├── Rakefile ├── app ├── assets │ └── config │ │ └── manifest.js ├── controllers │ ├── application_controller.rb │ └── jobs_controller.rb ├── jobs │ ├── application_job.rb │ └── sample_job.rb └── views │ ├── jobs │ └── index.html.erb │ └── layouts │ └── application.html.erb ├── bin ├── bundle ├── dev ├── jobs ├── rails ├── rake └── setup ├── config.ru ├── config ├── application.rb ├── boot.rb ├── credentials.yml.enc ├── database.yml ├── environment.rb ├── environments │ └── development.rb ├── initializers │ └── judoscale.rb ├── puma.rb ├── queue.yml ├── recurring.yml └── routes.rb ├── db ├── migrate │ └── 20241016134500_create_solid_queue_tables.rb └── schema.rb └── log └── .keep /.github/workflows/judoscale-rack-test.yml: -------------------------------------------------------------------------------- 1 | name: judoscale-rack tests 2 | defaults: 3 | run: 4 | working-directory: judoscale-rack 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | jobs: 11 | test: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | gemfile: 16 | - Gemfile 17 | - Gemfile-rack-2 18 | ruby: 19 | - "2.6" 20 | - "2.7" 21 | - "3.0" 22 | - "3.1" 23 | - "3.2" 24 | - "3.3" 25 | - "3.4" 26 | exclude: 27 | # Sinatra + rack-protection used for testing require Ruby 2.7+ 28 | - gemfile: Gemfile 29 | ruby: "2.6" 30 | runs-on: ubuntu-latest 31 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 32 | BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-rack/${{ matrix.gemfile }} 33 | steps: 34 | - uses: actions/checkout@v4 35 | - name: Setup default Bundler for Ruby <= 3.0 36 | if: ${{ matrix.ruby <= '3.0' }} 37 | run: echo "BUNDLER_VERSION=2.4.22" >> $GITHUB_ENV 38 | - uses: ruby/setup-ruby@v1 39 | with: 40 | ruby-version: ${{ matrix.ruby }} 41 | bundler-cache: true # runs bundle install and caches installed gems automatically 42 | bundler: ${{ env.BUNDLER_VERSION || 'Gemfile.lock' }} 43 | - run: bundle exec rake 44 | -------------------------------------------------------------------------------- /.github/workflows/judoscale-resque-test.yml: -------------------------------------------------------------------------------- 1 | name: judoscale-resque tests 2 | defaults: 3 | run: 4 | working-directory: judoscale-resque 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | jobs: 11 | test: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | gemfile: 16 | - Gemfile 17 | ruby: 18 | - "2.6" 19 | - "2.7" 20 | - "3.0" 21 | - "3.1" 22 | - "3.2" 23 | - "3.3" 24 | - "3.4" 25 | runs-on: ubuntu-latest 26 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 27 | BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-resque/${{ matrix.gemfile }} 28 | steps: 29 | - uses: actions/checkout@v4 30 | - name: Setup default Bundler for Ruby <= 3.0 31 | if: ${{ matrix.ruby <= '3.0' }} 32 | run: echo "BUNDLER_VERSION=2.4.22" >> $GITHUB_ENV 33 | - uses: ruby/setup-ruby@v1 34 | with: 35 | ruby-version: ${{ matrix.ruby }} 36 | bundler-cache: true # runs bundle install and caches installed gems automatically 37 | bundler: ${{ env.BUNDLER_VERSION || 'Gemfile.lock' }} 38 | - run: bundle exec rake 39 | -------------------------------------------------------------------------------- /.github/workflows/judoscale-ruby-test.yml: -------------------------------------------------------------------------------- 1 | name: judoscale-ruby tests 2 | defaults: 3 | run: 4 | working-directory: judoscale-ruby 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | jobs: 11 | test: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | gemfile: 16 | - Gemfile 17 | ruby: 18 | - "2.6" 19 | - "2.7" 20 | - "3.0" 21 | - "3.1" 22 | - "3.2" 23 | - "3.3" 24 | - "3.4" 25 | runs-on: ubuntu-latest 26 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 27 | BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-ruby/${{ matrix.gemfile }} 28 | steps: 29 | - uses: actions/checkout@v4 30 | - name: Setup default Bundler for Ruby <= 3.0 31 | if: ${{ matrix.ruby <= '3.0' }} 32 | run: echo "BUNDLER_VERSION=2.4.22" >> $GITHUB_ENV 33 | - uses: ruby/setup-ruby@v1 34 | with: 35 | ruby-version: ${{ matrix.ruby }} 36 | bundler-cache: true # runs bundle install and caches installed gems automatically 37 | bundler: ${{ env.BUNDLER_VERSION || 'Gemfile.lock' }} 38 | - run: bundle exec rake 39 | -------------------------------------------------------------------------------- /.github/workflows/judoscale-shoryuken-test.yml: -------------------------------------------------------------------------------- 1 | name: judoscale-shoryuken tests 2 | defaults: 3 | run: 4 | working-directory: judoscale-shoryuken 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | jobs: 11 | test: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | gemfile: 16 | - Gemfile 17 | ruby: 18 | - "2.6" 19 | - "2.7" 20 | - "3.0" 21 | - "3.1" 22 | - "3.2" 23 | - "3.3" 24 | - "3.4" 25 | runs-on: ubuntu-latest 26 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 27 | BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-shoryuken/${{ matrix.gemfile }} 28 | steps: 29 | - uses: actions/checkout@v4 30 | - name: Setup default Bundler for Ruby <= 3.0 31 | if: ${{ matrix.ruby <= '3.0' }} 32 | run: echo "BUNDLER_VERSION=2.4.22" >> $GITHUB_ENV 33 | - uses: ruby/setup-ruby@v1 34 | with: 35 | ruby-version: ${{ matrix.ruby }} 36 | bundler-cache: true # runs bundle install and caches installed gems automatically 37 | bundler: ${{ env.BUNDLER_VERSION || 'Gemfile.lock' }} 38 | - run: bundle exec rake 39 | -------------------------------------------------------------------------------- /.github/workflows/judoscale-sidekiq-benchmarks.yml: -------------------------------------------------------------------------------- 1 | name: judoscale-sidekiq benchmarks 2 | defaults: 3 | run: 4 | working-directory: judoscale-sidekiq 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | jobs: 11 | benchmarks: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | gemfile: 16 | - Gemfile 17 | - Gemfile-sidekiq-7 18 | - Gemfile-sidekiq-6 19 | - Gemfile-sidekiq-5 20 | ruby: 21 | - "2.7" 22 | - "3.1" 23 | - "3.4" 24 | redis: 25 | - "5.0" 26 | - "6.0" 27 | - "7.0" 28 | exclude: 29 | # Recent redis-client requires Redis 6+ 30 | - gemfile: Gemfile 31 | redis: "5.0" 32 | - gemfile: Gemfile-sidekiq-7 33 | redis: "5.0" 34 | # Sidekiq 8.0 requires Ruby 3.2 35 | - gemfile: Gemfile 36 | ruby: "3.1" 37 | - gemfile: Gemfile 38 | ruby: "2.7" 39 | 40 | runs-on: ubuntu-latest 41 | 42 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 43 | BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-sidekiq/${{ matrix.gemfile }} 44 | 45 | services: 46 | redis: 47 | image: redis:${{ matrix.redis }} 48 | ports: 49 | - 6379:6379 50 | 51 | steps: 52 | - uses: actions/checkout@v4 53 | - uses: ruby/setup-ruby@v1 54 | with: 55 | ruby-version: ${{ matrix.ruby }} 56 | bundler-cache: true # runs bundle install and caches installed gems automatically 57 | - run: bundle exec rake bench 58 | -------------------------------------------------------------------------------- /.github/workflows/judoscale-sidekiq-test.yml: -------------------------------------------------------------------------------- 1 | name: judoscale-sidekiq tests 2 | defaults: 3 | run: 4 | working-directory: judoscale-sidekiq 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | jobs: 11 | test: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | gemfile: 16 | - Gemfile 17 | - Gemfile-sidekiq-7 18 | - Gemfile-sidekiq-6 19 | - Gemfile-sidekiq-5 20 | ruby: 21 | - "2.6" 22 | - "2.7" 23 | - "3.0" 24 | - "3.1" 25 | - "3.2" 26 | - "3.3" 27 | - "3.4" 28 | exclude: 29 | # Sidekiq 8.0 requires Ruby 3.2 30 | - gemfile: Gemfile 31 | ruby: "3.1" 32 | - gemfile: Gemfile 33 | ruby: "3.0" 34 | - gemfile: Gemfile 35 | ruby: "2.7" 36 | - gemfile: Gemfile 37 | ruby: "2.6" 38 | # Sidekiq 7.0 requires Ruby 2.7 39 | - gemfile: Gemfile-sidekiq-7 40 | ruby: "2.6" 41 | runs-on: ubuntu-latest 42 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 43 | BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-sidekiq/${{ matrix.gemfile }} 44 | steps: 45 | - uses: actions/checkout@v4 46 | - uses: ruby/setup-ruby@v1 47 | with: 48 | ruby-version: ${{ matrix.ruby }} 49 | bundler-cache: true # runs bundle install and caches installed gems automatically 50 | - run: bundle exec rake 51 | -------------------------------------------------------------------------------- /.github/workflows/judoscale-solid_queue-test.yml: -------------------------------------------------------------------------------- 1 | name: judoscale-solid_queue tests 2 | defaults: 3 | run: 4 | working-directory: judoscale-solid_queue 5 | on: 6 | push: 7 | branches: 8 | - main 9 | pull_request: 10 | jobs: 11 | test: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | gemfile: 16 | - Gemfile 17 | - Gemfile-solid_queue-0-3 18 | ruby: 19 | - "2.7" 20 | - "3.0" 21 | - "3.1" 22 | - "3.2" 23 | - "3.3" 24 | - "3.4" 25 | exclude: 26 | - gemfile: Gemfile 27 | ruby: "3.1" 28 | - gemfile: Gemfile 29 | ruby: "3.0" 30 | - gemfile: Gemfile 31 | ruby: "2.7" 32 | runs-on: ubuntu-latest 33 | env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps 34 | BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-solid_queue/${{ matrix.gemfile }} 35 | services: 36 | db: 37 | image: postgres:latest 38 | env: 39 | POSTGRES_HOST_AUTH_METHOD: trust 40 | ports: ["5432:5432"] 41 | options: >- 42 | --health-cmd pg_isready 43 | --health-interval 10s 44 | --health-timeout 5s 45 | --health-retries 5 46 | steps: 47 | - uses: actions/checkout@v4 48 | - uses: ruby/setup-ruby@v1 49 | with: 50 | ruby-version: ${{ matrix.ruby }} 51 | bundler-cache: true # runs bundle install and caches installed gems automatically 52 | - run: bundle exec rake 53 | -------------------------------------------------------------------------------- /.github/workflows/lint.yml: -------------------------------------------------------------------------------- 1 | name: Lint 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | jobs: 8 | lint: 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | ruby: 13 | - "3.3" 14 | runs-on: ubuntu-latest 15 | steps: 16 | - uses: actions/checkout@v4 17 | - uses: ruby/setup-ruby@v1 18 | with: 19 | ruby-version: ${{ matrix.ruby }} 20 | - run: gem install standard -v '~> 1.40.0' 21 | - run: standardrb 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle/ 2 | /.yardoc 3 | /_yardoc/ 4 | /coverage/ 5 | /doc/ 6 | **/pkg/ 7 | /spec/reports/ 8 | /tmp/ 9 | /log/ 10 | /judoscale-*/Gemfile*.lock 11 | *.gem 12 | .env* 13 | -------------------------------------------------------------------------------- /.standard.yml: -------------------------------------------------------------------------------- 1 | ruby_version: 3.0 2 | 3 | ignore: 4 | - "sample-apps/**/*" 5 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "label": "test current gem", 8 | "command": "bundle exec rake test", 9 | "options": { 10 | "cwd": "${fileDirname}" 11 | }, 12 | "group": { 13 | "kind": "test" 14 | }, 15 | "runOptions": { 16 | "reevaluateOnRerun": false 17 | } 18 | }, 19 | { 20 | "label": "test current file", 21 | "command": "bundle", 22 | "args": ["exec", "ruby", "-I", ".", "${fileBasename}"], 23 | "options": { 24 | "cwd": "${fileDirname}" 25 | }, 26 | "group": { 27 | "kind": "test", 28 | "isDefault": true 29 | }, 30 | "runOptions": { 31 | "reevaluateOnRerun": false 32 | } 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Adam McCrea 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # Loads an IRB console/session within `judoscale-ruby` context by default. 5 | # Pass a different library to load the console within its context. 6 | # 7 | # Examples: 8 | # bin/console 9 | # bin/console judoscale-rails 10 | 11 | library = ARGV.shift || "judoscale-ruby" 12 | puts "Console: #{library}" 13 | 14 | require "fileutils" 15 | FileUtils.cd(library) do 16 | require "bundler/setup" 17 | require library 18 | 19 | require "irb" 20 | IRB.start(__FILE__) 21 | end 22 | -------------------------------------------------------------------------------- /bin/foreach: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | require "fileutils" 5 | 6 | puts "Running foreach: #{ARGV.inspect}" 7 | puts 8 | 9 | Dir[ENV["DIR"] || "judoscale-*"].each do |dir| 10 | FileUtils.cd(dir) do 11 | puts "Running: #{dir}" 12 | system(*ARGV) 13 | puts 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /bin/release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'rubygems' 4 | require 'fileutils' 5 | 6 | Dir.glob('./judoscale-*').each do |folder| 7 | puts 8 | puts "-> #{folder}" 9 | puts 10 | 11 | Dir.chdir(folder) do 12 | # We publish each gem as "judoscale-*" and "rails-autoscale-*" 13 | Dir.glob('*.gemspec').each do |gemspec| 14 | spec = Gem::Specification.load(gemspec) 15 | 16 | # Build the gem 17 | system "gem", "build", gemspec 18 | 19 | # Push the gem 20 | gem_file = "#{spec.name}-#{spec.version}.gem" 21 | system "gem", "push", gem_file 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /bin/test: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bin/foreach bundle exec rake test 4 | -------------------------------------------------------------------------------- /bin/update-dev-deps: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | bin/foreach bundle update 4 | -------------------------------------------------------------------------------- /bin/update-sample-deps: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DIR="sample-apps/*" bin/foreach bundle update 4 | -------------------------------------------------------------------------------- /judoscale-delayed_job/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-delayed_job" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord" 7 | gem "pg" 8 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-delayed_job/Gemfile-activerecord-6: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-delayed_job" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord", "~> 6.1" 7 | gem "pg" 8 | gem "minitest" 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-delayed_job/Gemfile-activerecord-7: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-delayed_job" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord", "~> 7.0" 7 | gem "pg" 8 | gem "minitest" 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-delayed_job/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-delayed_job/judoscale-delayed_job.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-delayed_job" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Delayed Job workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "delayed_job_active_record", ">= 4.0" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-delayed_job/lib/judoscale-delayed_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/delayed_job" 4 | -------------------------------------------------------------------------------- /judoscale-delayed_job/lib/judoscale/delayed_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | require "judoscale/config" 5 | require "judoscale/version" 6 | require "judoscale/delayed_job/metrics_collector" 7 | require "delayed_job_active_record" 8 | 9 | Judoscale.add_adapter :"judoscale-delayed_job", 10 | { 11 | adapter_version: Judoscale::VERSION, 12 | framework_version: Gem.loaded_specs["delayed_job_active_record"].version.to_s # DJ doesn't have a `VERSION` constant 13 | }, 14 | metrics_collector: Judoscale::DelayedJob::MetricsCollector, 15 | expose_config: Judoscale::Config::JobAdapterConfig.new(:delayed_job) 16 | -------------------------------------------------------------------------------- /judoscale-delayed_job/lib/rails-autoscale-delayed_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-delayed_job" 4 | -------------------------------------------------------------------------------- /judoscale-delayed_job/rails-autoscale-delayed_job.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-delayed_job" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Delayed Job workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-delayed_job", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-delayed_job/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe DelayedJob do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-delayed_job" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::DelayedJob::MetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-delayed_job") 15 | end 16 | 17 | it "sets up a config property for the library" do 18 | config = Config.instance 19 | _(config.delayed_job.enabled).must_equal true 20 | _(config.delayed_job.max_queues).must_equal 20 21 | _(config.delayed_job.queues).must_equal [] 22 | _(config.delayed_job.track_busy_jobs).must_equal false 23 | 24 | Judoscale.configure do |config| 25 | config.delayed_job.queues = %w[test drive] 26 | config.delayed_job.track_busy_jobs = true 27 | end 28 | 29 | _(config.delayed_job.queues).must_equal %w[test drive] 30 | _(config.delayed_job.track_busy_jobs).must_equal true 31 | 32 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 33 | _(report.as_json[:config]).must_include(:delayed_job) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /judoscale-good_job/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-good_job" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord" 7 | gem "pg" 8 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-good_job/Gemfile-activerecord-6: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-good_job" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord", "~> 6.1" 7 | gem "good_job", "~> 3.30" 8 | gem "pg" 9 | gem "minitest" 10 | gem "rake" 11 | -------------------------------------------------------------------------------- /judoscale-good_job/Gemfile-activerecord-7: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-good_job" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord", "~> 7.0" 7 | gem "pg" 8 | gem "minitest" 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-good_job/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-good_job/judoscale-good_job.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-good_job" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Good Job workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "good_job", ">= 3.0", "< 5.0" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-good_job/lib/judoscale-good_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/good_job" 4 | -------------------------------------------------------------------------------- /judoscale-good_job/lib/judoscale/good_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # require "good_job" fails unless we require these first 4 | require "logger" 5 | require "rails" 6 | require "active_support/core_ext/numeric/time" 7 | require "active_job/railtie" 8 | require "good_job" 9 | require "judoscale-ruby" 10 | require "judoscale/config" 11 | require "judoscale/version" 12 | require "judoscale/good_job/metrics_collector" 13 | 14 | Judoscale.add_adapter :"judoscale-good_job", 15 | { 16 | adapter_version: Judoscale::VERSION, 17 | framework_version: ::GoodJob::VERSION 18 | }, 19 | metrics_collector: Judoscale::GoodJob::MetricsCollector, 20 | expose_config: Judoscale::Config::JobAdapterConfig.new(:good_job) 21 | -------------------------------------------------------------------------------- /judoscale-good_job/lib/rails-autoscale-good_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-good_job" 4 | -------------------------------------------------------------------------------- /judoscale-good_job/rails-autoscale-good_job.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-good_job" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Good Job workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-good_job", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-good_job/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe GoodJob do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-good_job" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::GoodJob::MetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-good_job") 15 | end 16 | 17 | it "sets up a config property for the library" do 18 | config = Config.instance 19 | _(config.good_job.enabled).must_equal true 20 | _(config.good_job.max_queues).must_equal 20 21 | _(config.good_job.queues).must_equal [] 22 | _(config.good_job.track_busy_jobs).must_equal false 23 | 24 | Judoscale.configure do |config| 25 | config.good_job.queues = %w[test drive] 26 | config.good_job.track_busy_jobs = true 27 | end 28 | 29 | _(config.good_job.queues).must_equal %w[test drive] 30 | _(config.good_job.track_busy_jobs).must_equal true 31 | 32 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 33 | _(report.as_json[:config]).must_include(:good_job) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /judoscale-que/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-que" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord" 7 | gem "pg" 8 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-que/Gemfile-activerecord-6: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-que" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord", "~> 6.1" 7 | gem "pg" 8 | gem "minitest" 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-que/Gemfile-activerecord-7: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-que" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord", "~> 7.0" 7 | gem "pg" 8 | gem "minitest" 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-que/Gemfile-que-1: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-que" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "que", "~> 1.0" 7 | gem "activerecord" 8 | gem "pg" 9 | gem "minitest" 10 | gem "rake" 11 | -------------------------------------------------------------------------------- /judoscale-que/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: ../judoscale-ruby 3 | specs: 4 | judoscale-ruby (1.11.1) 5 | 6 | PATH 7 | remote: . 8 | specs: 9 | judoscale-que (1.11.1) 10 | judoscale-ruby (= 1.11.1) 11 | que (>= 1.0) 12 | 13 | GEM 14 | remote: https://rubygems.org/ 15 | specs: 16 | activemodel (8.0.2) 17 | activesupport (= 8.0.2) 18 | activerecord (8.0.2) 19 | activemodel (= 8.0.2) 20 | activesupport (= 8.0.2) 21 | timeout (>= 0.4.0) 22 | activesupport (8.0.2) 23 | base64 24 | benchmark (>= 0.3) 25 | bigdecimal 26 | concurrent-ruby (~> 1.0, >= 1.3.1) 27 | connection_pool (>= 2.2.5) 28 | drb 29 | i18n (>= 1.6, < 2) 30 | logger (>= 1.4.2) 31 | minitest (>= 5.1) 32 | securerandom (>= 0.3) 33 | tzinfo (~> 2.0, >= 2.0.5) 34 | uri (>= 0.13.1) 35 | base64 (0.2.0) 36 | benchmark (0.4.0) 37 | bigdecimal (3.1.9) 38 | concurrent-ruby (1.3.5) 39 | connection_pool (2.5.1) 40 | drb (2.2.1) 41 | i18n (1.14.7) 42 | concurrent-ruby (~> 1.0) 43 | logger (1.7.0) 44 | minitest (5.25.4) 45 | pg (1.5.9) 46 | que (2.4.1) 47 | rake (13.2.1) 48 | securerandom (0.4.1) 49 | timeout (0.4.3) 50 | tzinfo (2.0.6) 51 | concurrent-ruby (~> 1.0) 52 | uri (1.0.3) 53 | 54 | PLATFORMS 55 | arm64-darwin 56 | x86_64-linux 57 | 58 | DEPENDENCIES 59 | activerecord 60 | judoscale-que! 61 | judoscale-ruby! 62 | minitest (= 5.25.4) 63 | pg 64 | rake 65 | 66 | BUNDLED WITH 67 | 2.6.8 68 | -------------------------------------------------------------------------------- /judoscale-que/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-que/judoscale-que.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-que" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Que workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "que", ">= 1.0" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-que/lib/judoscale-que.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/que" 4 | -------------------------------------------------------------------------------- /judoscale-que/lib/judoscale/que.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | require "judoscale/config" 5 | require "judoscale/version" 6 | require "judoscale/que/metrics_collector" 7 | require "que" 8 | 9 | Judoscale.add_adapter :"judoscale-que", 10 | { 11 | adapter_version: Judoscale::VERSION, 12 | framework_version: ::Que::VERSION 13 | }, 14 | metrics_collector: Judoscale::Que::MetricsCollector, 15 | expose_config: Judoscale::Config::JobAdapterConfig.new(:que) 16 | -------------------------------------------------------------------------------- /judoscale-que/lib/rails-autoscale-que.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-que" 4 | -------------------------------------------------------------------------------- /judoscale-que/rails-autoscale-que.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-que" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Que workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-que", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-que/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe Que do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-que" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::Que::MetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-que") 15 | end 16 | 17 | it "sets up a config property for the library" do 18 | config = Config.instance 19 | _(config.que.enabled).must_equal true 20 | _(config.que.max_queues).must_equal 20 21 | _(config.que.queues).must_equal [] 22 | _(config.que.track_busy_jobs).must_equal false 23 | 24 | Judoscale.configure do |config| 25 | config.que.queues = %w[test drive] 26 | config.que.track_busy_jobs = true 27 | end 28 | 29 | _(config.que.queues).must_equal %w[test drive] 30 | _(config.que.track_busy_jobs).must_equal true 31 | 32 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 33 | _(report.as_json[:config]).must_include(:que) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /judoscale-que/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 | require "judoscale-que" 5 | 6 | require "minitest/autorun" 7 | require "minitest/spec" 8 | 9 | require "active_record" 10 | 11 | DATABASE_NAME = "judoscale_que_test" 12 | DATABASE_USERNAME = "postgres" 13 | DATABASE_URL = "postgres://#{DATABASE_USERNAME}:@localhost/#{DATABASE_NAME}" 14 | 15 | ActiveRecord::Tasks::DatabaseTasks.create(DATABASE_URL) 16 | Minitest.after_run { 17 | ActiveRecord::Tasks::DatabaseTasks.drop(DATABASE_URL) 18 | } 19 | ActiveRecord::Base.establish_connection(DATABASE_URL) 20 | 21 | Que.connection = ActiveRecord 22 | Que::Migrations.migrate!(version: Que::Migrations::CURRENT_VERSION) 23 | 24 | module Judoscale::Test 25 | end 26 | 27 | Dir[File.expand_path("../../judoscale-ruby/test/support/*.rb", __dir__)].sort.each { |file| require file } 28 | 29 | Minitest::Test.include(Judoscale::Test) 30 | -------------------------------------------------------------------------------- /judoscale-rack/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-rack" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 7 | gem "rake" 8 | gem "sinatra", ">= 2.0" 9 | gem "rack-test" 10 | -------------------------------------------------------------------------------- /judoscale-rack/Gemfile-rack-2: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-rack" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "rack", "~> 2.0" 7 | gem "minitest" 8 | gem "rake" 9 | gem "sinatra", ">= 2.0" 10 | gem "rack-test" 11 | -------------------------------------------------------------------------------- /judoscale-rack/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: ../judoscale-ruby 3 | specs: 4 | judoscale-ruby (1.11.1) 5 | 6 | PATH 7 | remote: . 8 | specs: 9 | judoscale-rack (1.11.1) 10 | judoscale-ruby (= 1.11.1) 11 | rack 12 | 13 | GEM 14 | remote: https://rubygems.org/ 15 | specs: 16 | base64 (0.2.0) 17 | logger (1.7.0) 18 | minitest (5.25.4) 19 | mustermann (3.0.3) 20 | ruby2_keywords (~> 0.0.1) 21 | rack (3.1.13) 22 | rack-protection (4.1.1) 23 | base64 (>= 0.1.0) 24 | logger (>= 1.6.0) 25 | rack (>= 3.0.0, < 4) 26 | rack-session (2.1.0) 27 | base64 (>= 0.1.0) 28 | rack (>= 3.0.0) 29 | rack-test (2.2.0) 30 | rack (>= 1.3) 31 | rake (13.2.1) 32 | ruby2_keywords (0.0.5) 33 | sinatra (4.1.1) 34 | logger (>= 1.6.0) 35 | mustermann (~> 3.0) 36 | rack (>= 3.0.0, < 4) 37 | rack-protection (= 4.1.1) 38 | rack-session (>= 2.0.0, < 3) 39 | tilt (~> 2.0) 40 | tilt (2.6.0) 41 | 42 | PLATFORMS 43 | arm64-darwin 44 | x86_64-linux 45 | 46 | DEPENDENCIES 47 | judoscale-rack! 48 | judoscale-ruby! 49 | minitest (= 5.25.4) 50 | rack-test 51 | rake 52 | sinatra (>= 2.0) 53 | 54 | BUNDLED WITH 55 | 2.6.8 56 | -------------------------------------------------------------------------------- /judoscale-rack/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-rack/judoscale-rack.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-rack" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Rack applications." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "rack" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-rack/lib/judoscale-rack.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/rack" 4 | -------------------------------------------------------------------------------- /judoscale-rack/lib/judoscale/rack.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | require "judoscale/version" 5 | require "judoscale/web_metrics_collector" 6 | require "judoscale/request_middleware" 7 | require "rack" 8 | 9 | # For Rack apps, Judoscale::RequestMiddleware must be manually inserted into 10 | # the app's middleware chain. 11 | 12 | Judoscale.add_adapter :"judoscale-rack", { 13 | adapter_version: Judoscale::VERSION, 14 | # Rack deprecated `version` in v3, removed in v3.1. 15 | framework_version: ::Rack.respond_to?(:release) ? ::Rack.release : ::Rack.version 16 | }, metrics_collector: Judoscale::WebMetricsCollector 17 | -------------------------------------------------------------------------------- /judoscale-rack/lib/rails-autoscale-rack.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-rack" 4 | -------------------------------------------------------------------------------- /judoscale-rack/rails-autoscale-rack.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-rack" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Rack applications." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-rack", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-rack/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe Rack do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-rack" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::WebMetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-rack") 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /judoscale-rack/test/app_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | require "rack/test" 3 | 4 | module Judoscale 5 | describe "App Request Metrics" do 6 | include ::Rack::Test::Methods 7 | 8 | def app 9 | TestSinatraApp 10 | end 11 | 12 | after { 13 | MetricsStore.instance.clear 14 | } 15 | 16 | it "tracks request metrics for each request" do 17 | header "X-Request-Start", (Time.now.utc.to_i - 10).to_s 18 | 19 | 1.upto(3) { |i| 20 | get "/" 21 | 22 | _(last_response).must_be :ok? 23 | _(last_response.body).must_match(/Hello World/m) 24 | 25 | _(MetricsStore.instance.metrics.size).must_equal i * 2 26 | _(MetricsStore.instance.metrics.last(2).map(&:identifier)).must_equal [:qt, :at] 27 | } 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-rack/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 | require "judoscale-rack" 5 | 6 | require "minitest/autorun" 7 | require "minitest/spec" 8 | require "sinatra/base" 9 | 10 | ENV["DYNO"] ||= "web.1" 11 | ENV["RACK_ENV"] ||= "test" 12 | 13 | Judoscale.configure do |config| 14 | config.logger = ::Logger.new(StringIO.new, progname: "rack-app") 15 | end 16 | 17 | class TestSinatraApp < Sinatra::Base 18 | set :environment, :test 19 | use Judoscale::RequestMiddleware 20 | 21 | get "/" do 22 | "Hello World!" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /judoscale-rails/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-rails" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 7 | gem "minitest-stub-const" 8 | gem "rake" 9 | -------------------------------------------------------------------------------- /judoscale-rails/Gemfile-rails-6-1: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-rails" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "railties", "~> 6.1" 7 | gem "minitest" 8 | gem "minitest-stub-const" 9 | gem "rake" 10 | 11 | if RUBY_VERSION >= "3.3" 12 | gem "base64" 13 | gem "bigdecimal" 14 | gem "mutex_m" 15 | end 16 | -------------------------------------------------------------------------------- /judoscale-rails/Gemfile-rails-7-0: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-rails" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "railties", "~> 7.0.0" 7 | gem "minitest" 8 | gem "minitest-stub-const" 9 | gem "rake" 10 | 11 | if RUBY_VERSION >= "3.3" 12 | gem "base64" 13 | gem "bigdecimal" 14 | gem "mutex_m" 15 | end 16 | -------------------------------------------------------------------------------- /judoscale-rails/Gemfile-rails-7-1: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-rails" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "railties", "~> 7.1.0" 7 | gem "minitest" 8 | gem "minitest-stub-const" 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-rails/Gemfile-rails-7-2: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-rails" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "railties", "~> 7.2.0" 7 | gem "minitest" 8 | gem "minitest-stub-const" 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-rails/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-rails/judoscale-rails.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-rails" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Ruby on Rails applications." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "railties" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-rails/lib/judoscale-rails.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/rails" 4 | -------------------------------------------------------------------------------- /judoscale-rails/lib/judoscale/rails.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | require "judoscale/version" 5 | require "judoscale/rails/railtie" 6 | require "judoscale/web_metrics_collector" 7 | require "rails/version" 8 | 9 | Judoscale.add_adapter :"judoscale-rails", { 10 | adapter_version: Judoscale::VERSION, 11 | framework_version: ::Rails.version 12 | }, metrics_collector: Judoscale::WebMetricsCollector 13 | -------------------------------------------------------------------------------- /judoscale-rails/lib/judoscale/rails/config.rb: -------------------------------------------------------------------------------- 1 | require "judoscale/config" 2 | 3 | module Judoscale 4 | module Rails 5 | module Config 6 | attr_accessor :start_reporter_after_initialize, :rake_task_ignore_regex, :utilization_enabled, :utilization_interval 7 | 8 | def reset 9 | super 10 | @start_reporter_after_initialize = true 11 | @rake_task_ignore_regex = /assets:|db:/ 12 | 13 | @utilization_enabled = ENV["JUDOSCALE_UTILIZATION_ENABLED"] == "true" 14 | @utilization_interval = (ENV["JUDOSCALE_UTILIZATION_INTERVAL"] || 1.0).to_f 15 | end 16 | end 17 | 18 | ::Judoscale::Config.prepend Config 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /judoscale-rails/lib/rails-autoscale-web.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-rails" 4 | -------------------------------------------------------------------------------- /judoscale-rails/rails-autoscale-web.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-web" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Ruby on Rails applications." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-rails", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-rails/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe Rails do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-rails" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::WebMetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-rails") 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /judoscale-rails/test/app_test.rb: -------------------------------------------------------------------------------- 1 | require "test_helper" 2 | require "rack/test" 3 | 4 | module Judoscale 5 | describe "App Request Metrics" do 6 | include Rack::Test::Methods 7 | 8 | def app 9 | # This refers to TestRailsApp created in test_helper.rb 10 | ::Rails.application 11 | end 12 | 13 | after { 14 | MetricsStore.instance.clear 15 | } 16 | 17 | it "tracks request metrics for each request" do 18 | header "X-Request-Start", (Time.now.utc.to_i - 10).to_s 19 | 20 | 1.upto(3) { |i| 21 | get "/" 22 | 23 | _(last_response).must_be :ok? 24 | _(last_response.body).must_equal "Hello World" 25 | 26 | _(MetricsStore.instance.metrics.size).must_equal i * 2 27 | _(MetricsStore.instance.metrics.last(2).map(&:identifier)).must_equal [:qt, :at] 28 | } 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /judoscale-rails/test/config_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/rails/config" 5 | 6 | module Judoscale 7 | describe Judoscale::Rails::Config do 8 | it "adds the start_reporter_after_initialize config option" do 9 | _(::Judoscale::Config.instance.start_reporter_after_initialize).must_equal true 10 | end 11 | 12 | it "adds the rake_task_ignore_regex config option" do 13 | _(::Judoscale::Config.instance.rake_task_ignore_regex).must_equal(/assets:|db:/) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /judoscale-rails/test/railtie_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "minitest/stub_const" 5 | 6 | module Judoscale 7 | describe Judoscale::Rails::Railtie do 8 | it "uses the Rails.logger when initialized though Rails" do 9 | _(::Judoscale::Config.instance.logger).must_equal ::Rails.logger 10 | end 11 | 12 | it "inserts the request middleware into the application middleware" do 13 | _(::Rails.application.config.middleware).must_include Judoscale::RequestMiddleware 14 | end 15 | 16 | it "boots up a reporter automatically after the app/config is initialized" do 17 | _(::Judoscale::Reporter.instance).must_be :started? 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /judoscale-rails/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 | require "judoscale-rails" 5 | 6 | require "minitest/autorun" 7 | require "minitest/spec" 8 | 9 | ENV["DYNO"] ||= "web.1" 10 | ENV["RACK_ENV"] ||= "test" 11 | require "action_controller" 12 | 13 | class TestRailsApp < Rails::Application 14 | config.load_defaults "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}" 15 | config.secret_key_base = "test-secret" 16 | config.eager_load = false 17 | config.logger = ::Logger.new(StringIO.new, progname: "rails-app") 18 | routes.append do 19 | root to: proc { 20 | [200, {"Content-Type" => "text/plain"}, ["Hello World"]] 21 | } 22 | end 23 | initialize! 24 | end 25 | -------------------------------------------------------------------------------- /judoscale-resque/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-resque" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 7 | gem "rake" 8 | # Lock an older version of Sinatra that supports Ruby 2.6 9 | gem "sinatra", "~> 3.2" 10 | -------------------------------------------------------------------------------- /judoscale-resque/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: ../judoscale-ruby 3 | specs: 4 | judoscale-ruby (1.11.1) 5 | 6 | PATH 7 | remote: . 8 | specs: 9 | judoscale-resque (1.11.1) 10 | judoscale-ruby (= 1.11.1) 11 | resque (>= 2.0) 12 | 13 | GEM 14 | remote: https://rubygems.org/ 15 | specs: 16 | base64 (0.2.0) 17 | connection_pool (2.5.1) 18 | minitest (5.25.4) 19 | mono_logger (1.1.2) 20 | multi_json (1.15.0) 21 | mustermann (3.0.3) 22 | ruby2_keywords (~> 0.0.1) 23 | rack (2.2.13) 24 | rack-protection (3.2.0) 25 | base64 (>= 0.1.0) 26 | rack (~> 2.2, >= 2.2.4) 27 | rake (13.2.1) 28 | redis (5.4.0) 29 | redis-client (>= 0.22.0) 30 | redis-client (0.24.0) 31 | connection_pool 32 | redis-namespace (1.11.0) 33 | redis (>= 4) 34 | resque (2.7.0) 35 | mono_logger (~> 1) 36 | multi_json (~> 1.0) 37 | redis-namespace (~> 1.6) 38 | sinatra (>= 0.9.2) 39 | ruby2_keywords (0.0.5) 40 | sinatra (3.2.0) 41 | mustermann (~> 3.0) 42 | rack (~> 2.2, >= 2.2.4) 43 | rack-protection (= 3.2.0) 44 | tilt (~> 2.0) 45 | tilt (2.6.0) 46 | 47 | PLATFORMS 48 | arm64-darwin 49 | x86_64-linux 50 | 51 | DEPENDENCIES 52 | judoscale-resque! 53 | judoscale-ruby! 54 | minitest (= 5.25.4) 55 | rake 56 | sinatra (~> 3.2) 57 | 58 | BUNDLED WITH 59 | 2.6.8 60 | -------------------------------------------------------------------------------- /judoscale-resque/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-resque/judoscale-resque.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-resque" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Resque workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "resque", ">= 2.0" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-resque/lib/judoscale-resque.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/resque" 4 | -------------------------------------------------------------------------------- /judoscale-resque/lib/judoscale/resque.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | require "judoscale/config" 5 | require "judoscale/version" 6 | require "judoscale/resque/metrics_collector" 7 | require "resque" 8 | require "judoscale/resque/latency_extension" 9 | 10 | Judoscale.add_adapter :"judoscale-resque", 11 | { 12 | adapter_version: Judoscale::VERSION, 13 | framework_version: ::Resque::VERSION 14 | }, 15 | metrics_collector: Judoscale::Resque::MetricsCollector, 16 | expose_config: Judoscale::Config::JobAdapterConfig.new(:resque) 17 | -------------------------------------------------------------------------------- /judoscale-resque/lib/judoscale/resque/latency_extension.rb: -------------------------------------------------------------------------------- 1 | module Judoscale 2 | module Resque 3 | module LatencyExtension 4 | # Store the time when jobs are pushed to the queue in order to calculate latency. 5 | def push(queue, item) 6 | item["timestamp"] = Time.now.utc.to_f 7 | super 8 | end 9 | 10 | # Calculate latency for the given queue using the stored timestamp of the oldest item in the queue. 11 | def latency(queue) 12 | if (item = peek(queue)) 13 | timestamp = item["timestamp"] 14 | timestamp ? Time.now.utc.to_f - timestamp.to_f : 0.0 15 | else 16 | 0.0 17 | end 18 | end 19 | end 20 | end 21 | end 22 | 23 | ::Resque.extend(Judoscale::Resque::LatencyExtension) 24 | -------------------------------------------------------------------------------- /judoscale-resque/lib/judoscale/resque/metrics_collector.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/job_metrics_collector" 4 | require "judoscale/metric" 5 | 6 | module Judoscale 7 | module Resque 8 | class MetricsCollector < Judoscale::JobMetricsCollector 9 | def self.adapter_config 10 | Judoscale::Config.instance.resque 11 | end 12 | 13 | def collect 14 | metrics = [] 15 | time = Time.now.utc 16 | current_queues = ::Resque.queues 17 | 18 | if track_busy_jobs? 19 | busy_counts = Hash.new { |h, k| h[k] = 0 } 20 | 21 | ::Resque.working.each do |worker| 22 | if !worker.idle? && (job = worker.job) 23 | busy_counts[job["queue"]] += 1 24 | end 25 | end 26 | end 27 | 28 | self.queues |= current_queues 29 | 30 | queues.each do |queue| 31 | next if queue.nil? || queue.empty? 32 | depth = ::Resque.size(queue) 33 | latency = (::Resque.latency(queue) * 1000).ceil 34 | 35 | metrics.push Metric.new(:qd, depth, time, queue) 36 | metrics.push Metric.new(:qt, latency, time, queue) 37 | 38 | if track_busy_jobs? 39 | busy_count = busy_counts[queue] 40 | metrics.push Metric.new(:busy, busy_count, time, queue) 41 | end 42 | end 43 | 44 | log_collection(metrics) 45 | metrics 46 | end 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /judoscale-resque/lib/rails-autoscale-resque.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-resque" 4 | -------------------------------------------------------------------------------- /judoscale-resque/rails-autoscale-resque.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-resque" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Resque workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-resque", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-resque/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe Resque do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-resque" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::Resque::MetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-resque") 15 | end 16 | 17 | it "sets up a config property for the library" do 18 | config = Config.instance 19 | _(config.resque.enabled).must_equal true 20 | _(config.resque.max_queues).must_equal 20 21 | _(config.resque.queues).must_equal [] 22 | _(config.resque.track_busy_jobs).must_equal false 23 | 24 | Judoscale.configure do |config| 25 | config.resque.queues = %w[test drive] 26 | config.resque.track_busy_jobs = true 27 | end 28 | 29 | _(config.resque.queues).must_equal %w[test drive] 30 | _(config.resque.track_busy_jobs).must_equal true 31 | 32 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 33 | _(report.as_json[:config]).must_include(:resque) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /judoscale-resque/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 | require "judoscale-resque" 5 | 6 | require "minitest/autorun" 7 | require "minitest/spec" 8 | 9 | module Judoscale::Test 10 | end 11 | 12 | Dir[File.expand_path("../../judoscale-ruby/test/support/*.rb", __dir__)].sort.each { |file| require file } 13 | 14 | Minitest::Test.include(Judoscale::Test) 15 | -------------------------------------------------------------------------------- /judoscale-ruby/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-ruby" 4 | 5 | gem "rake", ">= 12.3.3" 6 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 7 | gem "minitest-stub-const" 8 | gem "webmock" 9 | gem "public_suffix", "~> 5.0" # support for older Ruby versions 10 | -------------------------------------------------------------------------------- /judoscale-ruby/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: . 3 | specs: 4 | judoscale-ruby (1.11.1) 5 | 6 | GEM 7 | remote: https://rubygems.org/ 8 | specs: 9 | addressable (2.8.7) 10 | public_suffix (>= 2.0.2, < 7.0) 11 | bigdecimal (3.1.9) 12 | crack (1.0.0) 13 | bigdecimal 14 | rexml 15 | hashdiff (1.1.2) 16 | minitest (5.25.4) 17 | minitest-stub-const (0.6) 18 | public_suffix (5.1.1) 19 | rake (13.2.1) 20 | rexml (3.4.1) 21 | webmock (3.25.1) 22 | addressable (>= 2.8.0) 23 | crack (>= 0.3.2) 24 | hashdiff (>= 0.4.0, < 2.0.0) 25 | 26 | PLATFORMS 27 | arm64-darwin 28 | x86_64-linux 29 | 30 | DEPENDENCIES 31 | judoscale-ruby! 32 | minitest (= 5.25.4) 33 | minitest-stub-const 34 | public_suffix (~> 5.0) 35 | rake (>= 12.3.3) 36 | webmock 37 | 38 | BUNDLED WITH 39 | 2.6.8 40 | -------------------------------------------------------------------------------- /judoscale-ruby/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-ruby/judoscale-ruby.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-ruby" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Ruby." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale-ruby.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/config" 4 | require "judoscale/version" 5 | 6 | module Judoscale 7 | # Allows configuring Judoscale through a block, usually defined during application initialization. 8 | # 9 | # Example: 10 | # 11 | # Judoscale.configure do |config| 12 | # config.logger = MyLogger.new 13 | # end 14 | def self.configure 15 | yield Config.instance 16 | end 17 | 18 | @adapters = [] 19 | class << self 20 | attr_reader :adapters 21 | end 22 | 23 | class Adapter < Struct.new(:identifier, :adapter_info, :metrics_collector) 24 | def as_json 25 | {identifier => adapter_info} 26 | end 27 | end 28 | 29 | def self.add_adapter(identifier, adapter_info, metrics_collector: nil, expose_config: nil) 30 | Config.expose_adapter_config(expose_config) if expose_config 31 | @adapters << Adapter.new(identifier, adapter_info, metrics_collector) 32 | end 33 | 34 | add_adapter :"judoscale-ruby", { 35 | adapter_version: VERSION, 36 | language_version: RUBY_VERSION 37 | } 38 | end 39 | 40 | RailsAutoscale = Judoscale 41 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale/metric.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Judoscale 4 | class Metric < Struct.new(:identifier, :value, :time, :queue_name) 5 | # No queue_name is assumed to be a web request metric 6 | # Metrics: qt = queue time (default), qd = queue depth, busy 7 | def initialize(identifier, value, time, queue_name = nil) 8 | super(identifier, value.to_i, time.utc, queue_name) 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale/metrics_collector.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Judoscale 4 | class MetricsCollector 5 | def self.collect?(config) 6 | true 7 | end 8 | 9 | def collect 10 | [] 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale/metrics_store.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "singleton" 4 | require "judoscale/metric" 5 | require "judoscale/report" 6 | 7 | module Judoscale 8 | class MetricsStore 9 | include Singleton 10 | 11 | attr_reader :metrics, :flushed_at 12 | 13 | def initialize 14 | @metrics = [] 15 | @flushed_at = Time.now 16 | end 17 | 18 | def push(identifier, value, time = Time.now, queue_name = nil) 19 | # If it's been two minutes since clearing out the store, stop collecting metrics. 20 | # There could be an issue with the reporter, and continuing to collect will consume linear memory. 21 | return if @flushed_at && @flushed_at < Time.now - 120 22 | 23 | @metrics << Metric.new(identifier, value, time, queue_name) 24 | end 25 | 26 | def flush 27 | @flushed_at = Time.now 28 | flushed_metrics = [] 29 | 30 | while (metric = @metrics.shift) 31 | flushed_metrics << metric 32 | end 33 | 34 | flushed_metrics 35 | end 36 | 37 | def clear 38 | @metrics.clear 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale/report.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Judoscale 4 | class Report 5 | attr_reader :adapters, :config, :metrics 6 | 7 | def initialize(adapters, config, metrics = []) 8 | @adapters = adapters 9 | @config = config 10 | @metrics = metrics 11 | end 12 | 13 | def as_json 14 | { 15 | container: config.current_runtime_container, 16 | pid: Process.pid, 17 | config: config.as_json, 18 | adapters: adapters.reduce({}) { |hash, adapter| hash.merge!(adapter.as_json) }, 19 | metrics: metrics.map { |metric| 20 | [ 21 | metric.time.to_i, 22 | metric.value, 23 | metric.identifier, 24 | metric.queue_name 25 | ] 26 | } 27 | } 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale/request_middleware.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/metrics_store" 4 | require "judoscale/reporter" 5 | require "judoscale/logger" 6 | require "judoscale/request_metrics" 7 | 8 | module Judoscale 9 | class RequestMiddleware 10 | include Logger 11 | 12 | def initialize(app) 13 | @app = app 14 | end 15 | 16 | def call(env) 17 | request_metrics = RequestMetrics.new(env) 18 | store = MetricsStore.instance 19 | time = Time.now.utc 20 | 21 | if request_metrics.track_queue_time? 22 | queue_time = request_metrics.queue_time(time) 23 | network_time = request_metrics.network_time 24 | 25 | # NOTE: Expose queue time to the app 26 | env["judoscale.queue_time"] = queue_time 27 | store.push :qt, queue_time, time 28 | 29 | unless network_time.zero? 30 | env["judoscale.network_time"] = network_time 31 | store.push :nt, network_time, time 32 | end 33 | 34 | logger.debug "Request queue_time=#{queue_time}ms network_time=#{network_time}ms request_id=#{request_metrics.request_id} size=#{request_metrics.size}" 35 | end 36 | 37 | Reporter.start 38 | 39 | app_time, response = request_metrics.elapsed_time do 40 | @app.call(env) 41 | end 42 | store.push :at, app_time, time 43 | 44 | response 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale/version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Judoscale 4 | VERSION = "1.11.1" 5 | end 6 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/judoscale/web_metrics_collector.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/metrics_collector" 4 | require "judoscale/metrics_store" 5 | 6 | module Judoscale 7 | class WebMetricsCollector < MetricsCollector 8 | def collect 9 | MetricsStore.instance.flush 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /judoscale-ruby/lib/rails-autoscale-core.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | -------------------------------------------------------------------------------- /judoscale-ruby/rails-autoscale-core.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-core" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Ruby." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-ruby/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | describe Judoscale do 7 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 8 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-ruby" } 9 | _(adapter).wont_be_nil 10 | _(adapter.metrics_collector).must_be_nil 11 | 12 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 13 | _(report.as_json[:adapters]).must_include(:"judoscale-ruby") 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /judoscale-ruby/test/metric_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "time" 4 | require "test_helper" 5 | require "judoscale/metric" 6 | 7 | module Judoscale 8 | describe Metric do 9 | describe "#value" do 10 | it "is always an Integer" do 11 | metric = Metric.new(:qt, 123.45, Time.now) 12 | _(metric.value).must_equal 123 13 | end 14 | end 15 | 16 | describe "#time" do 17 | it "is always in UTC" do 18 | metric = Metric.new(:qt, 123, Time.iso8601("2016-12-03T01:11:00-05:00")) 19 | _(metric.time.iso8601).must_equal "2016-12-03T06:11:00Z" 20 | end 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /judoscale-ruby/test/support/config_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/config" 4 | 5 | module ConfigHelpers 6 | # Override Config.instance for a single spec 7 | # Example: 8 | # use_config quiet: true do 9 | # ... 10 | # end 11 | def use_config(options, &example) 12 | swap_config Judoscale::Config.instance, options, example 13 | end 14 | 15 | def use_adapter_config(adapter_identifier, options, &example) 16 | adapter_config = Judoscale::Config.instance.public_send(adapter_identifier) 17 | swap_config adapter_config, options, example 18 | end 19 | 20 | def before_setup 21 | super 22 | Judoscale::Config.instance.logger = LogHelpers.logger 23 | end 24 | 25 | # Reset config instance after each test to ensure changes don't leak to other tests. 26 | def after_teardown 27 | Judoscale::Config.instance.reset 28 | super 29 | end 30 | 31 | private 32 | 33 | def swap_config(config_instance, options, example) 34 | original_config = {} 35 | 36 | options.each do |key, val| 37 | original_config[key] = config_instance.public_send(key) 38 | config_instance.public_send :"#{key}=", val 39 | end 40 | 41 | example.call 42 | ensure 43 | options.each do |key, val| 44 | config_instance.public_send :"#{key}=", original_config[key] 45 | end 46 | end 47 | end 48 | 49 | Judoscale::Test.include ConfigHelpers 50 | -------------------------------------------------------------------------------- /judoscale-ruby/test/support/env_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module EnvHelpers 4 | attr_accessor :_original_env 5 | 6 | # Overrides ENV values for the duration of the block. 7 | # Example: 8 | # use_env "RAILS_ENV" => "production" do 9 | # ... 10 | # end 11 | def use_env(config, &test) 12 | setup_env(config) 13 | test.call 14 | ensure 15 | restore_env 16 | end 17 | 18 | # Overrides ENV values during the test setup, use `restore_env` to revert to original values. 19 | # Example: 20 | # setup_env "RAILS_ENV" => "production" 21 | # ... test stuff 22 | # restore_env 23 | # 24 | # Example with before/after hooks: 25 | # before { setup_env ... } 26 | # after { restore_env } 27 | def setup_env(config) 28 | self._original_env = {} 29 | 30 | config.each do |key, val| 31 | _original_env[key] = ENV[key] 32 | ENV[key] = val 33 | end 34 | 35 | # Force config to load with the swapped ENV. 36 | Judoscale::Config.instance.reset 37 | end 38 | 39 | # Restores ENV values to their original state. (from when `setup_env` was called, see it for more info.) 40 | def restore_env 41 | return unless _original_env 42 | 43 | _original_env.each do |key, val| 44 | ENV[key] = val 45 | end 46 | end 47 | 48 | # Always restore ENV on teardown for each test to ensure changes don't leak to other tests. 49 | def after_teardown 50 | restore_env 51 | super 52 | end 53 | end 54 | 55 | Judoscale::Test.include EnvHelpers 56 | -------------------------------------------------------------------------------- /judoscale-ruby/test/support/log_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module LogHelpers 4 | @log_io = StringIO.new 5 | @logger = ::Logger.new(@log_io) 6 | 7 | class << self 8 | attr_reader :log_io, :logger 9 | end 10 | 11 | def log_string 12 | LogHelpers.log_io.string 13 | end 14 | 15 | def clear_log 16 | LogHelpers.log_io.reopen 17 | end 18 | 19 | def after_teardown 20 | clear_log 21 | super 22 | end 23 | end 24 | 25 | Judoscale::Test.include(LogHelpers) 26 | -------------------------------------------------------------------------------- /judoscale-ruby/test/support/time_helpers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module TimeHelpers 4 | def freeze_time(time = Time.now.utc, &block) 5 | Time.stub(:now, time, &block) 6 | end 7 | end 8 | 9 | Judoscale::Test.include(TimeHelpers) 10 | -------------------------------------------------------------------------------- /judoscale-ruby/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 | require "judoscale-ruby" 5 | 6 | require "minitest/autorun" 7 | require "minitest/spec" 8 | require "webmock/minitest" 9 | 10 | require "judoscale/job_metrics_collector" 11 | require "judoscale/web_metrics_collector" 12 | 13 | module Judoscale 14 | module Test 15 | class TestJobMetricsCollector < Judoscale::JobMetricsCollector 16 | def self.adapter_config 17 | Judoscale::Config.instance.test_job_config 18 | end 19 | 20 | def collect 21 | [Metric.new(:qt, 2, Time.now, "test-queue")] 22 | end 23 | end 24 | 25 | class TestWebMetricsCollector < Judoscale::WebMetricsCollector 26 | def collect 27 | [Metric.new(:qt, 1, Time.now)] 28 | end 29 | end 30 | end 31 | 32 | add_adapter :test_web, {}, metrics_collector: Test::TestWebMetricsCollector 33 | add_adapter :test_job, {}, metrics_collector: Test::TestJobMetricsCollector, 34 | expose_config: Config::JobAdapterConfig.new(:test_job_config) 35 | end 36 | 37 | Dir[File.expand_path("./support/*.rb", __dir__)].sort.each { |file| require file } 38 | 39 | Minitest::Test.include(Judoscale::Test) 40 | -------------------------------------------------------------------------------- /judoscale-ruby/test/web_metrics_collector_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "minitest/stub_const" 5 | require "judoscale/web_metrics_collector" 6 | require "judoscale/config" 7 | 8 | module RailsMock 9 | module Command 10 | class GenerateCommand; end 11 | end 12 | end 13 | 14 | module Judoscale 15 | describe WebMetricsCollector do 16 | describe "#collect" do 17 | let(:store) { MetricsStore.instance } 18 | 19 | it "flushes the metrics previously collected from the store" do 20 | collector = WebMetricsCollector.new 21 | _(collector.collect).must_be :empty? 22 | 23 | 1.upto(3) { |i| store.push :qt, i, Time.now } 24 | _(store.metrics.size).must_equal 3 25 | 26 | collected_metrics = collector.collect 27 | 28 | _(collected_metrics.size).must_equal 3 29 | _(collected_metrics.map(&:value)).must_equal [1, 2, 3] 30 | _(collected_metrics[0].identifier).must_equal :qt 31 | _(store.metrics).must_be :empty? 32 | end 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /judoscale-shoryuken/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-shoryuken" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "shoryuken", "~> 6.2" 7 | gem "aws-sdk-sqs" # shoryuken integration with AWS SDK v3+ 8 | gem "rexml" # aws-sdk-core requires an XML parser. 9 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 10 | gem "rake" 11 | -------------------------------------------------------------------------------- /judoscale-shoryuken/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: ../judoscale-ruby 3 | specs: 4 | judoscale-ruby (1.11.1) 5 | 6 | PATH 7 | remote: . 8 | specs: 9 | judoscale-shoryuken (1.11.1) 10 | judoscale-ruby (= 1.11.1) 11 | shoryuken (>= 6.0) 12 | 13 | GEM 14 | remote: https://rubygems.org/ 15 | specs: 16 | aws-eventstream (1.3.2) 17 | aws-partitions (1.1090.0) 18 | aws-sdk-core (3.222.2) 19 | aws-eventstream (~> 1, >= 1.3.0) 20 | aws-partitions (~> 1, >= 1.992.0) 21 | aws-sigv4 (~> 1.9) 22 | base64 23 | jmespath (~> 1, >= 1.6.1) 24 | logger 25 | aws-sdk-sqs (1.93.0) 26 | aws-sdk-core (~> 3, >= 3.216.0) 27 | aws-sigv4 (~> 1.5) 28 | aws-sigv4 (1.11.0) 29 | aws-eventstream (~> 1, >= 1.0.2) 30 | base64 (0.2.0) 31 | concurrent-ruby (1.3.5) 32 | jmespath (1.6.2) 33 | logger (1.7.0) 34 | minitest (5.25.4) 35 | rake (13.2.1) 36 | rexml (3.4.1) 37 | shoryuken (6.2.1) 38 | aws-sdk-core (>= 2) 39 | concurrent-ruby 40 | thor 41 | thor (1.3.2) 42 | 43 | PLATFORMS 44 | arm64-darwin 45 | x86_64-linux 46 | 47 | DEPENDENCIES 48 | aws-sdk-sqs 49 | judoscale-ruby! 50 | judoscale-shoryuken! 51 | minitest (= 5.25.4) 52 | rake 53 | rexml 54 | shoryuken (~> 6.2) 55 | 56 | BUNDLED WITH 57 | 2.6.8 58 | -------------------------------------------------------------------------------- /judoscale-shoryuken/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs = %w[lib test] 7 | t.pattern = "test/**/*_test.rb" 8 | end 9 | 10 | task default: :test 11 | -------------------------------------------------------------------------------- /judoscale-shoryuken/judoscale-shoryuken.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-shoryuken" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Shoryuken workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "shoryuken", ">= 6.0" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-shoryuken/lib/judoscale-shoryuken.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/shoryuken" 4 | -------------------------------------------------------------------------------- /judoscale-shoryuken/lib/judoscale/shoryuken.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | require "judoscale/config" 5 | require "judoscale/version" 6 | require "judoscale/shoryuken/metrics_collector" 7 | require "shoryuken" 8 | 9 | Judoscale.add_adapter :"judoscale-shoryuken", 10 | { 11 | adapter_version: Judoscale::VERSION, 12 | framework_version: ::Shoryuken::VERSION 13 | }, 14 | metrics_collector: Judoscale::Shoryuken::MetricsCollector, 15 | expose_config: Judoscale::Config::JobAdapterConfig.new(:shoryuken, support_busy_jobs: false) 16 | -------------------------------------------------------------------------------- /judoscale-shoryuken/lib/judoscale/shoryuken/metrics_collector.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/job_metrics_collector" 4 | require "judoscale/metric" 5 | 6 | module Judoscale 7 | module Shoryuken 8 | class MetricsCollector < Judoscale::JobMetricsCollector 9 | SQS_QUEUE_DEPTH_ATTRIBUTE = "ApproximateNumberOfMessages" 10 | 11 | def self.adapter_config 12 | Judoscale::Config.instance.shoryuken 13 | end 14 | 15 | def collect 16 | metrics = [] 17 | time = Time.now.utc 18 | self.queues |= ::Shoryuken.ungrouped_queues 19 | 20 | queues.each do |queue_name| 21 | queue = ::Shoryuken::Client.queues(queue_name) 22 | 23 | # Reach out to SQS client directly to fetch the queue attribute we need to report. 24 | # Shoryuken has a private `queue_attributes` API to fetch all attributes, this call mimics that. 25 | sqs_queue_attributes = ::Shoryuken.sqs_client 26 | .get_queue_attributes(queue_url: queue.url, attribute_names: [SQS_QUEUE_DEPTH_ATTRIBUTE]) 27 | depth = sqs_queue_attributes.attributes[SQS_QUEUE_DEPTH_ATTRIBUTE] 28 | 29 | metrics.push Metric.new(:qd, depth, time, queue_name) 30 | end 31 | 32 | log_collection(metrics) 33 | metrics 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /judoscale-shoryuken/lib/rails-autoscale-shoryuken.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-shoryuken" 4 | -------------------------------------------------------------------------------- /judoscale-shoryuken/rails-autoscale-shoryuken.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-shoryuken" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Shoryuken workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-shoryuken", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-shoryuken/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 | require "judoscale-shoryuken" 5 | 6 | require "minitest/autorun" 7 | require "minitest/spec" 8 | 9 | module Judoscale::Test 10 | end 11 | 12 | Dir[File.expand_path("../../judoscale-ruby/test/support/*.rb", __dir__)].sort.each { |file| require file } 13 | 14 | Minitest::Test.include(Judoscale::Test) 15 | 16 | # Setup Shoryuken with a stub SQS Client to avoid any API hits, and facilitate testing. 17 | ::Shoryuken.sqs_client = Aws::SQS::Client.new(stub_responses: true) 18 | -------------------------------------------------------------------------------- /judoscale-sidekiq/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-sidekiq" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "sidekiq", "~> 8.0" 7 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 8 | gem "rake" 9 | -------------------------------------------------------------------------------- /judoscale-sidekiq/Gemfile-sidekiq-5: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-sidekiq" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "sidekiq", "~> 5.0" 7 | gem "minitest" 8 | gem "rake" 9 | 10 | if RUBY_VERSION >= "3.3" 11 | gem "base64" 12 | end 13 | -------------------------------------------------------------------------------- /judoscale-sidekiq/Gemfile-sidekiq-6: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-sidekiq" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "sidekiq", "~> 6.0" 7 | gem "minitest" 8 | gem "rake" 9 | 10 | if RUBY_VERSION >= "3.3" 11 | gem "base64" 12 | end 13 | -------------------------------------------------------------------------------- /judoscale-sidekiq/Gemfile-sidekiq-7: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-sidekiq" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "sidekiq", "~> 7.0" 7 | gem "minitest" 8 | gem "rake" 9 | -------------------------------------------------------------------------------- /judoscale-sidekiq/Gemfile.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: ../judoscale-ruby 3 | specs: 4 | judoscale-ruby (1.11.1) 5 | 6 | PATH 7 | remote: . 8 | specs: 9 | judoscale-sidekiq (1.11.1) 10 | judoscale-ruby (= 1.11.1) 11 | sidekiq (>= 5.0) 12 | 13 | GEM 14 | remote: https://rubygems.org/ 15 | specs: 16 | connection_pool (2.5.1) 17 | json (2.10.2) 18 | logger (1.7.0) 19 | minitest (5.25.4) 20 | rack (3.1.13) 21 | rake (13.2.1) 22 | redis-client (0.24.0) 23 | connection_pool 24 | sidekiq (8.0.2) 25 | connection_pool (>= 2.5.0) 26 | json (>= 2.9.0) 27 | logger (>= 1.6.2) 28 | rack (>= 3.1.0) 29 | redis-client (>= 0.23.2) 30 | 31 | PLATFORMS 32 | arm64-darwin 33 | x86_64-linux 34 | 35 | DEPENDENCIES 36 | judoscale-ruby! 37 | judoscale-sidekiq! 38 | minitest (= 5.25.4) 39 | rake 40 | sidekiq (~> 8.0) 41 | 42 | BUNDLED WITH 43 | 2.6.8 44 | -------------------------------------------------------------------------------- /judoscale-sidekiq/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs = %w[lib test] 7 | t.pattern = "test/**/*_test.rb" 8 | end 9 | 10 | Rake::TestTask.new(:bench) do |t| 11 | t.libs = %w[lib test] 12 | t.pattern = "test/benchmarks/**/*_benchmark.rb" 13 | end 14 | 15 | task default: :test 16 | -------------------------------------------------------------------------------- /judoscale-sidekiq/judoscale-sidekiq.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-sidekiq" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Sidekiq workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.6.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "sidekiq", ">= 5.0" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-sidekiq/lib/judoscale-sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/sidekiq" 4 | -------------------------------------------------------------------------------- /judoscale-sidekiq/lib/judoscale/sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-ruby" 4 | require "judoscale/config" 5 | require "judoscale/version" 6 | require "judoscale/sidekiq/metrics_collector" 7 | require "sidekiq/api" 8 | 9 | Judoscale.add_adapter :"judoscale-sidekiq", 10 | { 11 | adapter_version: Judoscale::VERSION, 12 | framework_version: ::Sidekiq::VERSION 13 | }, 14 | metrics_collector: Judoscale::Sidekiq::MetricsCollector, 15 | expose_config: Judoscale::Config::JobAdapterConfig.new(:sidekiq) 16 | -------------------------------------------------------------------------------- /judoscale-sidekiq/lib/rails-autoscale-sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-sidekiq" 4 | -------------------------------------------------------------------------------- /judoscale-sidekiq/rails-autoscale-sidekiq.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-sidekiq" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Sidekiq workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-sidekiq", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-sidekiq/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe Sidekiq do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-sidekiq" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::Sidekiq::MetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-sidekiq") 15 | end 16 | 17 | it "sets up a config property for the library" do 18 | config = Config.instance 19 | _(config.sidekiq.enabled).must_equal true 20 | _(config.sidekiq.max_queues).must_equal 20 21 | _(config.sidekiq.queues).must_equal [] 22 | _(config.sidekiq.track_busy_jobs).must_equal false 23 | 24 | Judoscale.configure do |config| 25 | config.sidekiq.queues = %w[test drive] 26 | config.sidekiq.track_busy_jobs = true 27 | end 28 | 29 | _(config.sidekiq.queues).must_equal %w[test drive] 30 | _(config.sidekiq.track_busy_jobs).must_equal true 31 | 32 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 33 | _(report.as_json[:config]).must_include(:sidekiq) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /judoscale-sidekiq/test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | $LOAD_PATH.unshift File.expand_path("../lib", __dir__) 4 | require "judoscale-sidekiq" 5 | 6 | require "minitest/autorun" 7 | require "minitest/spec" 8 | 9 | module Judoscale::Test 10 | end 11 | 12 | Dir[File.expand_path("../../judoscale-ruby/test/support/*.rb", __dir__)].sort.each { |file| require file } 13 | 14 | Minitest::Test.include(Judoscale::Test) 15 | -------------------------------------------------------------------------------- /judoscale-solid_queue/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-solid_queue" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "activerecord" 7 | gem "pg" 8 | gem "minitest", "5.25.4" # latest version that supports Ruby 2.6 9 | gem "rake" 10 | -------------------------------------------------------------------------------- /judoscale-solid_queue/Gemfile-solid_queue-0-3: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec name: "judoscale-solid_queue" 4 | 5 | gem "judoscale-ruby", path: "../judoscale-ruby" 6 | gem "solid_queue", "~> 0.3.0" 7 | gem "activerecord" 8 | gem "pg" 9 | gem "minitest" 10 | gem "rake" 11 | -------------------------------------------------------------------------------- /judoscale-solid_queue/Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rake/testtask" 4 | 5 | Rake::TestTask.new(:test) do |t| 6 | t.libs << "lib" 7 | t.libs << "test" 8 | t.test_files = FileList["test/**/*_test.rb"] 9 | end 10 | 11 | task default: :test 12 | -------------------------------------------------------------------------------- /judoscale-solid_queue/judoscale-solid_queue.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "judoscale-solid_queue" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Solid Queue workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].reject { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.required_ruby_version = ">= 2.7.0" 27 | 28 | spec.add_dependency "judoscale-ruby", Judoscale::VERSION 29 | spec.add_dependency "solid_queue", ">= 0.3" 30 | end 31 | -------------------------------------------------------------------------------- /judoscale-solid_queue/lib/judoscale-solid_queue.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale/solid_queue" 4 | -------------------------------------------------------------------------------- /judoscale-solid_queue/lib/judoscale/solid_queue.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "solid_queue" 4 | require "judoscale-ruby" 5 | require "judoscale/config" 6 | require "judoscale/version" 7 | require "judoscale/solid_queue/metrics_collector" 8 | 9 | Judoscale.add_adapter :"judoscale-solid_queue", 10 | { 11 | adapter_version: Judoscale::VERSION, 12 | framework_version: ::SolidQueue::VERSION 13 | }, 14 | metrics_collector: Judoscale::SolidQueue::MetricsCollector, 15 | expose_config: Judoscale::Config::JobAdapterConfig.new(:solid_queue) 16 | -------------------------------------------------------------------------------- /judoscale-solid_queue/lib/rails-autoscale-solid_queue.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "judoscale-solid_queue" 4 | -------------------------------------------------------------------------------- /judoscale-solid_queue/rails-autoscale-solid_queue.gemspec: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative "../judoscale-ruby/lib/judoscale/version" 4 | 5 | Gem::Specification.new do |spec| 6 | spec.name = "rails-autoscale-solid_queue" 7 | spec.version = Judoscale::VERSION 8 | spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"] 9 | spec.email = ["hello@judoscale.com"] 10 | 11 | spec.summary = "Autoscaling for Solid Queue workers." 12 | spec.homepage = "https://judoscale.com" 13 | spec.license = "MIT" 14 | 15 | spec.metadata = { 16 | "homepage_uri" => "https://judoscale.com", 17 | "bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues", 18 | "documentation_uri" => "https://judoscale.com/docs", 19 | "changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md", 20 | "source_code_uri" => "https://github.com/judoscale/judoscale-ruby" 21 | } 22 | 23 | spec.files = Dir["lib/**/*"].select { |f| f.match?(%r{rails-autoscale}) } 24 | spec.require_paths = ["lib"] 25 | 26 | spec.add_dependency "judoscale-solid_queue", Judoscale::VERSION 27 | end 28 | -------------------------------------------------------------------------------- /judoscale-solid_queue/test/adapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "test_helper" 4 | require "judoscale/report" 5 | 6 | module Judoscale 7 | describe SolidQueue do 8 | it "adds itself as an adapter with information to be reported to the Judoscale API" do 9 | adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-solid_queue" } 10 | _(adapter).wont_be_nil 11 | _(adapter.metrics_collector).must_equal Judoscale::SolidQueue::MetricsCollector 12 | 13 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 14 | _(report.as_json[:adapters]).must_include(:"judoscale-solid_queue") 15 | end 16 | 17 | it "sets up a config property for the library" do 18 | config = Config.instance 19 | _(config.solid_queue.enabled).must_equal true 20 | _(config.solid_queue.max_queues).must_equal 20 21 | _(config.solid_queue.queues).must_equal [] 22 | _(config.solid_queue.track_busy_jobs).must_equal false 23 | 24 | Judoscale.configure do |config| 25 | config.solid_queue.queues = %w[test drive] 26 | config.solid_queue.track_busy_jobs = true 27 | end 28 | 29 | _(config.solid_queue.queues).must_equal %w[test drive] 30 | _(config.solid_queue.track_busy_jobs).must_equal true 31 | 32 | report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, []) 33 | _(report.as_json[:config]).must_include(:solid_queue) 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /sample-apps/.gitattributes: -------------------------------------------------------------------------------- 1 | # Shared .gitattributes file generated by Rails for the sample-apps. 2 | 3 | # See https://git-scm.com/docs/gitattributes for more about git attribute files. 4 | 5 | # Mark the database schema as having been generated. 6 | /*-sample/db/schema.rb linguist-generated 7 | 8 | # Mark any vendored files as having been vendored. 9 | /*-sample/vendor/* linguist-vendored 10 | -------------------------------------------------------------------------------- /sample-apps/.gitignore: -------------------------------------------------------------------------------- 1 | # Shared .gitignore file generated by Rails for the sample-apps. 2 | 3 | # Ignore bundler config. 4 | /*-sample/.bundle 5 | 6 | # Ignore the default SQLite database. 7 | /*-sample/db/*.sqlite3 8 | /*-sample/db/*.sqlite3-* 9 | 10 | # Ignore all logfiles and tempfiles. 11 | /*-sample/log/* 12 | /*-sample/tmp/* 13 | !/*-sample/log/.keep 14 | !/*-sample/tmp/.keep 15 | 16 | # Ignore pidfiles, but keep the directory. 17 | /*-sample/tmp/pids/* 18 | !/*-sample/tmp/pids/ 19 | !/*-sample/tmp/pids/.keep 20 | 21 | /*-sample/public/assets 22 | 23 | # Ignore master key for decrypting credentials and more. 24 | /*-sample/config/master.key 25 | -------------------------------------------------------------------------------- /sample-apps/delayed_job-sample/Gemfile: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 3 | 4 | # Require only the frameworks we currently use instead of loading everything. 5 | %w(activerecord actionpack actionview railties).each { |rails_gem| 6 | gem rails_gem, "~> 7.1.0" 7 | } 8 | 9 | gem "pg", "~> 1.1" 10 | gem "puma", "~> 6.0" 11 | 12 | gem "delayed_job_active_record" 13 | gem "delayed_job_web" 14 | 15 | # Need to reference all locally, otherwise it'd use the the gemspecs to try to find each gem, 16 | # but we want to test against the local dev versions of them, not the released gems. 17 | gem "judoscale-ruby", path: "../../judoscale-ruby" 18 | gem "judoscale-rails", path: "../../judoscale-rails" 19 | gem "judoscale-delayed_job", path: "../../judoscale-delayed_job" 20 | -------------------------------------------------------------------------------- /sample-apps/delayed_job-sample/Procfile: -------------------------------------------------------------------------------- 1 | release: bundle exec rails db:migrate 2 | proxy: npx judoscale-adapter-proxy-server 3 | 4 | # NOTE: Enable either the `heroku_` processes or the `render_` processes based 5 | # on which env you want to spoof locally. 6 | 7 | heroku_rails: DYNO=web.1 bundle exec rails server 8 | heroku_dj: DYNO=worker.1 QUEUES=default,low,high bundle exec rake jobs:work 9 | 10 | # render_rails: RENDER_SERVICE_ID=srv-xyz RENDER_INSTANCE_ID=srv-xyz-1234 RENDER_SERVICE_TYPE=web bundle exec rails server 11 | # render_dj: RENDER_SERVICE_ID=srv-abc RENDER_INSTANCE_ID=srv-abc-1234 RENDER_SERVICE_TYPE=worker QUEUES=default,low,high bundle exec rake jobs:work 12 | -------------------------------------------------------------------------------- /sample-apps/delayed_job-sample/Rakefile: -------------------------------------------------------------------------------- 1 | require_relative "config/application" 2 | 3 | Rails.application.load_tasks 4 | -------------------------------------------------------------------------------- /sample-apps/delayed_job-sample/app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | end 3 | -------------------------------------------------------------------------------- /sample-apps/delayed_job-sample/app/controllers/jobs_controller.rb: -------------------------------------------------------------------------------- 1 | class JobsController < ApplicationController 2 | QUEUES = %w(default low high) 3 | 4 | def index 5 | @available_queues = QUEUES.dup 6 | @queues = Delayed::Backend::ActiveRecord::Job.group(:queue).count 7 | end 8 | 9 | def create 10 | job_params = params.require(:job).permit(:queue_name, :enqueue_count) 11 | 12 | queue_name = job_params[:queue_name] 13 | enqueue_count = job_params[:enqueue_count].to_i 14 | 15 | if QUEUES.include?(queue_name) && enqueue_count.between?(1, 100) 16 | 1.upto(enqueue_count) { 17 | Delayed::Job.enqueue SampleJob, queue: queue_name 18 | } 19 | 20 | flash[:notice] = "#{enqueue_count} #{"job".pluralize(enqueue_count)} enqueued on the #{queue_name.inspect} queue." 21 | redirect_to action: :index 22 | else 23 | flash[:alert] = "Please enter queue name & enqueue count." 24 | redirect_to action: :index 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /sample-apps/delayed_job-sample/app/jobs/sample_job.rb: -------------------------------------------------------------------------------- 1 | class SampleJob 2 | def self.perform 3 | sleep rand(3) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /sample-apps/delayed_job-sample/app/views/jobs/index.html.erb: -------------------------------------------------------------------------------- 1 |
4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. They will be slowly processed by DelayedJob, while Judoscale collects and reports available queue metrics. 11 |
12 | 13 |<%= notice %><% end %> 16 | <% if alert %>
<%= alert %><% end %> 17 | 18 | <% if @queues.any? %> 19 |
No queues found.
26 | <% end %> 27 | 28 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. 11 | They will be slowly processed by GoodJob, while Judoscale collects and reports available queue metrics. 12 | <%= link_to "GoodJob Dashboard ↗", "/good_job", target: "_blank" %>. 13 |
14 | 15 |<%= notice %><% end %> 18 | <% if alert %>
<%= alert %><% end %> 19 | 20 | <% if @queues.any? %> 21 |
No queues found.
28 | <% end %> 29 | 30 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. 11 | They will be slowly processed by GoodJob, while Judoscale collects and reports available queue metrics. 12 | <%= link_to "GoodJob Dashboard ↗", "/good_job", target: "_blank" %>. 13 |
14 | 15 |<%= notice %><% end %> 18 | <% if alert %>
<%= alert %><% end %> 19 | 20 | <% if @queues.any? %> 21 |
No queues found.
28 | <% end %> 29 | 30 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. They will be slowly processed by Que, while Judoscale collects and reports available queue metrics. 11 |
12 | 13 |<%= notice %><% end %> 16 | <% if alert %>
<%= alert %><% end %> 17 | 18 | <% if @queues.any? %> 19 |
No queues found.
26 | <% end %> 27 | 28 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 | -------------------------------------------------------------------------------- /sample-apps/rails-sample/app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. They will be slowly processed by Resque, while Judoscale collects and reports available queue metrics. 11 |
12 | 13 |<%= notice %><% end %> 16 | <% if alert %>
<%= alert %><% end %> 17 | 18 | <% if @queues.any? %> 19 |
No queues found.
26 | <% end %> 27 | 28 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. They will be slowly processed by Shoryuken, while Judoscale collects and reports available queue metrics. 11 |
12 | 13 |<%= notice %><% end %> 16 | <% if alert %>
<%= alert %><% end %> 17 | 18 | <% if @queues.any? %> 19 |
No queues found.
26 | <% end %> 27 | 28 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. They will be slowly processed by Sidekiq, while Judoscale collects and reports available queue metrics. 11 |
12 | 13 |<%= notice %><% end %> 16 | <% if alert %>
<%= alert %><% end %> 17 | 18 | <% if @queues.any? %> 19 |
No queues found.
26 | <% end %> 27 | 28 |4 | Judoscale is reporting metrics to https://judoscale-adapter-mock.requestcatcher.com. 5 |
6 |7 | Open that page to watch as metrics are being reported, and reload this page multiple times to collect and report web metrics. 8 |
9 |10 | Enqueue test jobs using the form below. 11 | They will be slowly processed by SolidQueue, while Judoscale collects and reports available queue metrics. 12 | <%= link_to "SolidQueue / MissionControl Dashboard ↗", "/jobs", target: "_blank" if defined?(MissionControl) %>. 13 |
14 | 15 |<%= notice %><% end %> 18 | <% if alert %>
<%= alert %><% end %> 19 | 20 | <% if @queues.any? %> 21 |
No queues found.
28 | <% end %> 29 | 30 |