-
Notifications
You must be signed in to change notification settings - Fork 46
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #367 from bdewater/interruption-adapter-from-job
Infer interruption handler from a job's queue adapter
- Loading branch information
Showing
12 changed files
with
114 additions
and
112 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# frozen_string_literal: true | ||
|
||
module JobIteration | ||
# @api private | ||
module Integrations | ||
LoadError = Class.new(StandardError) | ||
|
||
extend self | ||
|
||
attr_accessor :registered_integrations | ||
|
||
self.registered_integrations = {} | ||
|
||
autoload :Sidekiq, "job-iteration/integrations/sidekiq" | ||
autoload :Resque, "job-iteration/integrations/resque" | ||
|
||
# @api public | ||
def register(name, callable) | ||
raise ArgumentError, "Interruption adapter must respond to #call" unless callable.respond_to?(:call) | ||
|
||
registered_integrations[name] = callable | ||
end | ||
|
||
def load(name) | ||
if (callable = registered_integrations[name]) | ||
callable | ||
else | ||
begin | ||
klass = "#{self}::#{name.camelize}".constantize | ||
register(name, klass) | ||
rescue NameError | ||
raise LoadError, "Could not find integration for '#{name}'" | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,52 @@ | ||
# frozen_string_literal: true | ||
|
||
require "test_helper" | ||
require "open3" | ||
|
||
class IntegrationsTest < ActiveSupport::TestCase | ||
test "will prevent loading two integrations" do | ||
with_env("ITERATION_DISABLE_AUTOCONFIGURE", nil) do | ||
rubby = <<~RUBBY | ||
require 'bundler/setup' | ||
require 'job-iteration' | ||
RUBBY | ||
_stdout, stderr, status = run_ruby(rubby) | ||
|
||
assert_equal false, status.success? | ||
assert_match(/resque integration has already been loaded, but sidekiq is also available/, stderr) | ||
|
||
class IntegrationsTest < IterationUnitTest | ||
class IterationJob < ActiveJob::Base | ||
include JobIteration::Iteration | ||
|
||
def build_enumerator(cursor:) | ||
enumerator_builder.build_once_enumerator(cursor: cursor) | ||
end | ||
end | ||
|
||
test "successfully loads one (resque) integration" do | ||
with_env("ITERATION_DISABLE_AUTOCONFIGURE", nil) do | ||
rubby = <<~RUBBY | ||
require 'bundler/setup' | ||
# Remove sidekiq, only resque will be left | ||
$LOAD_PATH.delete_if { |p| p =~ /sidekiq/ } | ||
require 'job-iteration' | ||
RUBBY | ||
_stdout, _stderr, status = run_ruby(rubby) | ||
|
||
assert_equal true, status.success? | ||
def each_iteration(*) | ||
end | ||
end | ||
|
||
private | ||
class ResqueJob < IterationJob | ||
self.queue_adapter = :resque | ||
end | ||
|
||
class SidekiqJob < IterationJob | ||
self.queue_adapter = :sidekiq | ||
end | ||
|
||
test "loads multiple integrations" do | ||
resque_job = ResqueJob.new.serialize | ||
ActiveJob::Base.execute(resque_job) | ||
|
||
sidekiq_job = SidekiqJob.new.serialize | ||
ActiveJob::Base.execute(sidekiq_job) | ||
end | ||
|
||
test ".register accepts an object does implementing #call" do | ||
JobIteration::Integrations.register(:registration_test, -> { true }) | ||
|
||
def run_ruby(body) | ||
stdout, stderr, status = nil | ||
Tempfile.open do |f| | ||
f.write(body) | ||
f.close | ||
assert(JobIteration::Integrations.registered_integrations[:registration_test].call) | ||
end | ||
|
||
command = "ruby #{f.path}" | ||
stdout, stderr, status = Open3.capture3(command) | ||
test ".register raises when the callable object does not implement #call" do | ||
error = assert_raises(ArgumentError) do | ||
JobIteration::Integrations.register("foo", "bar") | ||
end | ||
[stdout, stderr, status] | ||
assert_equal("Interruption adapter must respond to #call", error.message) | ||
end | ||
|
||
def with_env(variable, value) | ||
original = ENV[variable] | ||
ENV[variable] = value | ||
yield | ||
ensure | ||
ENV[variable] = original | ||
test "raises for unknown Active Job queue adapter names" do | ||
error = assert_raises(JobIteration::Integrations::LoadError) do | ||
JobIteration::Integrations.load("unknown") | ||
end | ||
assert_equal("Could not find integration for 'unknown'", error.message) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters