Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Build
on: [push, pull_request]
on: [push]

jobs:
tests:
Expand Down Expand Up @@ -39,3 +39,5 @@ jobs:
bin/rails db:setup
- name: Run tests
run: bin/rails test
- name: Run tests with separate connection
run: SEPARATE_CONNECTION=1 bin/rails test
2 changes: 2 additions & 0 deletions app/models/solid_queue/record.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module SolidQueue
class Record < ActiveRecord::Base
self.abstract_class = true

connects_to **SolidQueue.connects_to if SolidQueue.connects_to
end
end

Expand Down
3 changes: 1 addition & 2 deletions lib/solid_queue.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@

module SolidQueue
mattr_accessor :logger, default: ActiveSupport::Logger.new($stdout)
mattr_accessor :app_executor
mattr_accessor :on_thread_error
mattr_accessor :app_executor, :on_thread_error, :connects_to

mattr_accessor :process_heartbeat_interval, default: 60.seconds
mattr_accessor :process_alive_threshold, default: 5.minutes
Expand Down
4 changes: 4 additions & 0 deletions test/dummy/config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ class Application < Rails::Application
# config.eager_load_paths << Rails.root.join("extras")

config.active_job.queue_adapter = :solid_queue

if ENV["SEPARATE_CONNECTION"] && ENV["TARGET_DB"] != "sqlite"
config.solid_queue.connects_to = { database: { writing: :primary, reading: :replica } }
end
end
end
53 changes: 28 additions & 25 deletions test/dummy/config/database.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,14 @@
# gem "mysql2"
#

<% def database_name_from(name); ENV["TARGET_DB"]=="sqlite" ? "db/#{name}.sqlite3" : name; end %>

<% if ENV["TARGET_DB"] == "sqlite" %>
default: &default
adapter: sqlite3
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 50 } %>
retries: 100

development:
<<: *default
database: db/development.sqlite3

test:
<<: *default
pool: 20
database: db/test.sqlite3

<% elsif ENV["TARGET_DB"] == "postgres" %>
default: &default
adapter: postgresql
Expand All @@ -30,30 +23,40 @@ default: &default
port: 55432
gssencmode: disable # https://github.com/ged/ruby-pg/issues/311

development:
<<: *default
database: solid_queue_development

test:
<<: *default
pool: 20
database: solid_queue_test

<% else %>
default: &default
adapter: mysql2
username: root
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
host: "127.0.0.1"
port: 33060
<% end %>

# development:
# <<: *default
# database: <%= database_name_from("solid_queue_development") %>

# test:
# <<: *default
# database: <%= database_name_from("solid_queue_development") %>


development:
<<: *default
database: solid_queue_development
primary:
<<: *default
database: <%= database_name_from("solid_queue_development") %>
replica:
<<: *default
database: <%= database_name_from("solid_queue_development") %>
replica: true

test:
<<: *default
pool: 20
database: solid_queue_test
<% end %>

primary:
<<: *default
pool: 20
database: <%= database_name_from("solid_queue_test") %>
replica:
<<: *default
pool: 20
database: <%= database_name_from("solid_queue_test") %>
replica: true
8 changes: 4 additions & 4 deletions test/integration/concurrency_controls_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ class ConcurrencyControlsTest < ActiveSupport::TestCase
test "schedule several conflicting jobs over the same record sequentially" do
UpdateResultJob.set(wait: 0.2.seconds).perform_later(@result, name: "000", pause: 0.1.seconds)

("A".."F").each do |name|
SequentialUpdateResultJob.set(wait: 0.2.seconds).perform_later(@result, name: name, pause: 0.2.seconds)
("A".."F").each_with_index do |name, i|
SequentialUpdateResultJob.set(wait: (0.2 + i * 0.01).seconds).perform_later(@result, name: name, pause: 0.2.seconds)
end

("G".."K").each do |name|
SequentialUpdateResultJob.set(wait: 0.4.seconds).perform_later(@result, name: name)
("G".."K").each_with_index do |name, i|
SequentialUpdateResultJob.set(wait: (0.4 + i * 0.01).seconds).perform_later(@result, name: name)
end

wait_for_jobs_to_finish_for(4.seconds)
Expand Down
24 changes: 24 additions & 0 deletions test/models/solid_queue/job_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
require "test_helper"

class SolidQueue::JobTest < ActiveSupport::TestCase
self.use_transactional_tests = false

teardown do
SolidQueue::Job.destroy_all
JobResult.delete_all
end

class NonOverlappingJob < ApplicationJob
limits_concurrency key: ->(job_result, **) { job_result }

Expand Down Expand Up @@ -108,6 +115,23 @@ class NonOverlappingGroupedJob2 < NonOverlappingJob
assert blocked_execution.expires_at <= SolidQueue.default_concurrency_control_period.from_now
end

if ENV["SEPARATE_CONNECTION"] && ENV["TARGET_DB"] != "sqlite"
test "uses a different connection and transaction than the one in use when connects_to is specified" do
assert_difference -> { SolidQueue::Job.count } do
assert_no_difference -> { JobResult.count } do
JobResult.transaction do
JobResult.create!(queue_name: "default", value: "this will be rolled back")
StoreResultJob.perform_later("enqueued inside a rolled back transaction")
raise ActiveRecord::Rollback
end
end
end

job = SolidQueue::Job.last
assert_equal "enqueued inside a rolled back transaction", job.arguments.dig("arguments", 0)
end
end

private
def assert_ready(&block)
assert_difference -> { SolidQueue::Job.count } => +1, -> { SolidQueue::ReadyExecution.count } => +1, &block
Expand Down
2 changes: 1 addition & 1 deletion test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,6 @@ def reap_processes
# by the cached queries might have been updated, created or deleted in the forked
# processes.
def skip_active_record_query_cache(&block)
ActiveRecord::Base.uncached(&block)
SolidQueue::Record.uncached(&block)
end
end