Skip to content

Commit

Permalink
Cleanup thread tests, introduce "Slow" ExampleJob type, refactor Exam…
Browse files Browse the repository at this point in the history
…pleJob types, run cron in GoodJob Development harness (#390)
  • Loading branch information
bensheldon authored Sep 30, 2021
1 parent c2949e8 commit 719af5b
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 61 deletions.
27 changes: 19 additions & 8 deletions spec/app/jobs/example_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,50 @@
end

describe "#perform" do
describe ":success" do
describe "SUCCESS_TYPE" do
it 'completes successfully' do
active_job = described_class.perform_later('success')
active_job = described_class.perform_later(described_class::SUCCESS_TYPE)
execution = GoodJob::Execution.find(active_job.provider_job_id)
expect(execution.error).to be_nil
end
end

describe ":error_once" do
describe "ERROR_ONCE_TYPE" do
it 'errors once then succeeds' do
active_job = described_class.perform_later('error_once')
active_job = described_class.perform_later(described_class::ERROR_ONCE_TYPE)
executions = GoodJob::Execution.where(active_job_id: active_job.job_id).order(created_at: :asc)
expect(executions.size).to eq 2
expect(executions.last.error).to be_nil
end
end

describe ":error_five_times" do
describe "ERROR_FIVE_TIMES_TYPE" do
it 'errors five times then succeeds' do
active_job = described_class.perform_later('error_five_times')
active_job = described_class.perform_later(described_class::ERROR_FIVE_TIMES_TYPE)
executions = GoodJob::Execution.where(active_job_id: active_job.job_id).order(created_at: :asc)
expect(executions.size).to eq 6
expect(executions.last.error).to be_nil
end
end

describe ":dead" do
describe "DEAD_TYPE" do
it 'errors but does not retry' do
active_job = described_class.perform_later('dead')
active_job = described_class.perform_later(described_class::DEAD_TYPE)
executions = GoodJob::Execution.where(active_job_id: active_job.job_id).order(created_at: :asc)
expect(executions.size).to eq 3
expect(executions.last.error).to be_present
end
end

describe "SLOW_TYPE" do
it 'sleeps for period' do
expect_any_instance_of(Object).to receive(:sleep)

active_job = described_class.perform_later(described_class::SLOW_TYPE)

execution = GoodJob::Execution.find(active_job.provider_job_id)
expect(execution.error).to be_nil
end
end
end
end
69 changes: 25 additions & 44 deletions spec/lib/good_job/current_thread_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,36 @@
require 'rails_helper'

RSpec.describe GoodJob::CurrentThread do
describe '.error_on_discard' do
it 'maintains value across threads' do
described_class.error_on_discard = 'apple'

Thread.new do
described_class.error_on_discard = 'bear'
end.join

expect(described_class.error_on_discard).to eq 'apple'
end

it 'maintains value across Rails execution wrapper' do
Rails.application.executor.wrap do
described_class.error_on_discard = 'apple'
[
:cron_key,
:execution,
:error_on_discard,
:error_on_retry,
].each do |accessor|
describe ".#{accessor}" do
it 'maintains value across threads' do
described_class.send "#{accessor}=", 'apple'

Thread.new do
described_class.send "#{accessor}=", 'bear'
end.join

expect(described_class.send(accessor)).to eq 'apple'
end

expect(described_class.error_on_discard).to eq 'apple'
end

it 'is resettable' do
described_class.error_on_discard = 'apple'
described_class.reset
expect(described_class.error_on_discard).to eq nil
end
end
it 'maintains value across Rails reloader wrapper' do
Rails.application.reloader.wrap do
described_class.send "#{accessor}=", 'apple'
end

describe '.error_on_retry' do
it 'maintains value across threads' do
described_class.error_on_retry = 'apple'

Thread.new do
described_class.error_on_retry = 'bear'
end.join

expect(described_class.error_on_retry).to eq 'apple'
end

it 'maintains value across Rails execution wrapper' do
Rails.application.executor.wrap do
described_class.error_on_retry = 'apple'
expect(described_class.send(accessor)).to eq 'apple'
end

expect(described_class.error_on_retry).to eq 'apple'
end

it 'is resettable' do
described_class.error_on_retry = 'apple'
described_class.reset
expect(described_class.error_on_retry).to eq nil
it 'is resettable' do
described_class.send "#{accessor}=", 'apple'
described_class.reset
expect(described_class.send(accessor)).to eq nil
end
end
end

Expand Down
23 changes: 15 additions & 8 deletions spec/test_app/app/jobs/example_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,27 @@ class ExampleJob < ApplicationJob
ExpectedError = Class.new(StandardError)
DeadError = Class.new(StandardError)

TYPES = [
SUCCESS_TYPE = 'success',
ERROR_ONCE_TYPE = 'error_once',
ERROR_FIVE_TIMES_TYPE = 'error_five_times',
DEAD_TYPE = 'dead',
SLOW_TYPE = 'slow',
]

retry_on DeadError, attempts: 3

def perform(type = :success)
return unless type.respond_to?(:to_sym)
type = type.to_sym

if type == :success
def perform(type = SUCCESS_TYPE)
if type == SUCCESS_TYPE
true
elsif type == :error_once
elsif type == ERROR_ONCE_TYPE
raise(ExpectedError, "Executed #{executions} #{"time".pluralize(executions)}.") if executions < 2
elsif type == :error_five_times
elsif type == ERROR_FIVE_TIMES_TYPE
raise(ExpectedError, "Executed #{executions} #{"time".pluralize(executions)}.") if executions < 6
elsif type == :dead
elsif type == DEAD_TYPE
raise DeadError
elsif type == SLOW_TYPE
sleep 5
end
end
end
2 changes: 1 addition & 1 deletion spec/test_app/config/environments/demo.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
cron: "* * * * * *",
class: "ExampleJob",
args: (lambda do
type = [:success, :error_once, :error_five_times, :dead].sample
type = ExampleJob::TYPES.sample
[type.to_s]
end),
set: (lambda do
Expand Down
20 changes: 20 additions & 0 deletions spec/test_app/config/environments/development.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,24 @@

config.active_job.queue_adapter = :good_job
GoodJob.preserve_job_records = true

config.good_job.enable_cron = true
config.good_job.cron = {
frequent_example: {
description: "Enqueue an ExampleJob",
cron: "*/5 * * * * *",
class: "ExampleJob",
args: (lambda do
type = ExampleJob::SLOW_TYPE # ExampleJob::TYPES.sample
[type.to_s]
end),
set: (lambda do
queue = [:default, :elephants, :mice].sample
delay = [0, (0..60).to_a.sample].sample
priority = [-10, 0, 10].sample

{ wait: delay, queue: queue, priority: priority }
end),
},
}
end
13 changes: 13 additions & 0 deletions spec/test_app/config/initializers/postgres.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Output Postgres notifications through Rails.logger instead of stderr
if Rails.env.development?
ActiveSupport.on_load :active_record do
ActiveRecord::ConnectionAdapters::AbstractAdapter.set_callback :checkout, :before, lambda { |conn|
raw_connection = conn.raw_connection
next unless raw_connection.respond_to? :set_notice_receiver

raw_connection.set_notice_receiver do |result|
Rails.logger.info("Postgres notice: #{result.error_message}\n#{caller.join("\n")}")
end
}
end
end

0 comments on commit 719af5b

Please sign in to comment.