Skip to content

Commit

Permalink
[WIP] SolidQueue integration
Browse files Browse the repository at this point in the history
  • Loading branch information
carlosantoniodasilva committed Apr 22, 2024
1 parent b6a5863 commit 5a3042e
Show file tree
Hide file tree
Showing 15 changed files with 573 additions and 0 deletions.
45 changes: 45 additions & 0 deletions .github/workflows/judoscale-solid_queue.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: judoscale-solid_queue tests
defaults:
run:
working-directory: judoscale-solid_queue
on:
push:
branches:
- main
pull_request:
jobs:
test:
strategy:
fail-fast: false
matrix:
gemfile:
- Gemfile
ruby:
- "2.7"
- "3.0"
- "3.1"
- "3.2"
- "3.3"
exclude:

runs-on: ubuntu-latest
env: # $BUNDLE_GEMFILE must be set at the job level, so it is set for all steps
BUNDLE_GEMFILE: ${{ github.workspace }}/judoscale-solid_queue/${{ matrix.gemfile }}
services:
db:
image: postgres:latest
env:
POSTGRES_HOST_AUTH_METHOD: trust
ports: ["5432:5432"]
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true # runs bundle install and caches installed gems automatically
- run: bundle exec rake
1 change: 1 addition & 0 deletions judoscale-good_job/test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
require "action_controller"

class TestRailsApp < Rails::Application
config.load_defaults "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
config.secret_key_base = "test-secret"
config.eager_load = false
config.logger = ::Logger.new(StringIO.new, progname: "rails-app")
Expand Down
1 change: 1 addition & 0 deletions judoscale-rails/test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
require "action_controller"

class TestRailsApp < Rails::Application
config.load_defaults "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
config.secret_key_base = "test-secret"
config.eager_load = false
config.logger = ::Logger.new(StringIO.new, progname: "rails-app")
Expand Down
9 changes: 9 additions & 0 deletions judoscale-solid_queue/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
source "https://rubygems.org"

gemspec name: "judoscale-solid_queue"

gem "judoscale-ruby", path: "../judoscale-ruby"
gem "activerecord"
gem "pg"
gem "minitest"
gem "rake"
11 changes: 11 additions & 0 deletions judoscale-solid_queue/Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# frozen_string_literal: true

require "rake/testtask"

Rake::TestTask.new(:test) do |t|
t.libs << "lib"
t.libs << "test"
t.test_files = FileList["test/**/*_test.rb"]
end

task default: :test
30 changes: 30 additions & 0 deletions judoscale-solid_queue/judoscale-solid_queue.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "judoscale/solid_queue/version"

Gem::Specification.new do |spec|
spec.name = "judoscale-solid_queue"
spec.version = Judoscale::SolidQueue::VERSION
spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"]
spec.email = ["[email protected]"]

spec.summary = "This gem provides SolidQueue integration with the Judoscale autoscaling add-on for Heroku."
spec.homepage = "https://judoscale.com"
spec.license = "MIT"

spec.metadata = {
"homepage_uri" => "https://judoscale.com",
"bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues",
"documentation_uri" => "https://judoscale.com/docs",
"changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md",
"source_code_uri" => "https://github.com/judoscale/judoscale-ruby"
}

spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.require_paths = ["lib"]

spec.required_ruby_version = ">= 2.7.0"

spec.add_dependency "judoscale-ruby", Judoscale::SolidQueue::VERSION
spec.add_dependency "solid_queue", ">= 0.3"
end
3 changes: 3 additions & 0 deletions judoscale-solid_queue/lib/judoscale-solid_queue.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

require "judoscale/solid_queue"
15 changes: 15 additions & 0 deletions judoscale-solid_queue/lib/judoscale/solid_queue.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# frozen_string_literal: true

require "solid_queue"
require "judoscale-ruby"
require "judoscale/config"
require "judoscale/solid_queue/version"
require "judoscale/solid_queue/metrics_collector"

Judoscale.add_adapter :"judoscale-solid_queue",
{
adapter_version: Judoscale::SolidQueue::VERSION,
framework_version: ::SolidQueue::VERSION
},
metrics_collector: Judoscale::SolidQueue::MetricsCollector,
expose_config: Judoscale::Config::JobAdapterConfig.new(:solid_queue)
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# frozen_string_literal: true

require "judoscale/job_metrics_collector"
require "judoscale/job_metrics_collector/active_record_helper"
require "judoscale/metric"

module Judoscale
module SolidQueue
class MetricsCollector < Judoscale::JobMetricsCollector
include ActiveRecordHelper

def self.adapter_config
Judoscale::Config.instance.solid_queue
end

def self.collect?(config)
super && ActiveRecordHelper.table_exists_for_model?(::SolidQueue::Job)
end

def initialize
super

queue_names = run_silently do
::SolidQueue::Job.distinct.pluck(:queue_name)
end
self.queues |= queue_names
end

def collect
metrics = []
time = Time.now.utc

oldest_execution_time_by_queue = run_silently do
::SolidQueue::ReadyExecution
.group(:queue_name)
.minimum(:created_at)
end
self.queues |= oldest_execution_time_by_queue.keys

if track_busy_jobs?
busy_count_by_queue = run_silently do
::SolidQueue::Job.joins(:claimed_execution).group(:queue_name).count
end
self.queues |= busy_count_by_queue.keys
end

queues.each do |queue|
run_at = oldest_execution_time_by_queue[queue]
latency_ms = run_at ? ((time - run_at) * 1000).ceil : 0
latency_ms = 0 if latency_ms < 0

metrics.push Metric.new(:qt, latency_ms, time, queue)

if track_busy_jobs?
busy_count = busy_count_by_queue[queue] || 0
metrics.push Metric.new(:busy, busy_count, Time.now, queue)
end
end

log_collection(metrics)
metrics
end
end
end
end
7 changes: 7 additions & 0 deletions judoscale-solid_queue/lib/judoscale/solid_queue/version.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

module Judoscale
module SolidQueue
VERSION = "1.5.4"
end
end
3 changes: 3 additions & 0 deletions judoscale-solid_queue/lib/rails-autoscale-solid_queue.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: true

require "judoscale/solid_queue"
30 changes: 30 additions & 0 deletions judoscale-solid_queue/rails-autoscale-solid_queue.gemspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "judoscale/solid_queue/version"

Gem::Specification.new do |spec|
spec.name = "rails-autoscale-solid_queue"
spec.version = Judoscale::SolidQueue::VERSION
spec.authors = ["Adam McCrea", "Carlos Antonio da Silva", "Jon Sullivan"]
spec.email = ["[email protected]"]

spec.summary = "This gem provides SolidQueue integration with the Judoscale autoscaling add-on for Heroku."
spec.homepage = "https://judoscale.com"
spec.license = "MIT"

spec.metadata = {
"homepage_uri" => "https://judoscale.com",
"bug_tracker_uri" => "https://github.com/judoscale/judoscale-ruby/issues",
"documentation_uri" => "https://judoscale.com/docs",
"changelog_uri" => "https://github.com/judoscale/judoscale-ruby/blob/main/CHANGELOG.md",
"source_code_uri" => "https://github.com/judoscale/judoscale-ruby"
}

spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.require_paths = ["lib"]

spec.required_ruby_version = ">= 2.6.0"

spec.add_dependency "rails-autoscale-core", Judoscale::SolidQueue::VERSION
spec.add_dependency "solid_queue", ">= 0.3"
end
36 changes: 36 additions & 0 deletions judoscale-solid_queue/test/adapter_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

require "test_helper"
require "judoscale/report"

module Judoscale
describe SolidQueue do
it "adds itself as an adapter with information to be reported to the Judoscale API" do
adapter = Judoscale.adapters.detect { |adapter| adapter.identifier == :"judoscale-solid_queue" }
_(adapter).wont_be_nil
_(adapter.metrics_collector).must_equal Judoscale::SolidQueue::MetricsCollector

report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, [])
_(report.as_json[:adapters]).must_include(:"judoscale-solid_queue")
end

it "sets up a config property for the library" do
config = Config.instance
_(config.solid_queue.enabled).must_equal true
_(config.solid_queue.max_queues).must_equal 20
_(config.solid_queue.queues).must_equal []
_(config.solid_queue.track_busy_jobs).must_equal false

Judoscale.configure do |config|
config.solid_queue.queues = %w[test drive]
config.solid_queue.track_busy_jobs = true
end

_(config.solid_queue.queues).must_equal %w[test drive]
_(config.solid_queue.track_busy_jobs).must_equal true

report = ::Judoscale::Report.new(Judoscale.adapters, Judoscale::Config.instance, [])
_(report.as_json[:config]).must_include(:solid_queue)
end
end
end
Loading

0 comments on commit 5a3042e

Please sign in to comment.