rails4: gemify delayed_job

closes CNVS-14275

While we're at it, fix all the rspec deprecation warnings.

test plan: delayed jobs should still work as before, including queuing,
viewing in the UI, and running.

Change-Id: I36c6b74aa2b59a99e4f1f36e25e6d0e9e153f92a
Reviewed-on: https://gerrit.instructure.com/41211
Reviewed-by: Cody Cutrer <cody@instructure.com>
QA-Review: August Thornton <august@instructure.com>
Tested-by: Jenkins <jenkins@instructure.com>
Product-Review: Brian Palmer <brianp@instructure.com>
This commit is contained in:
Brian Palmer 2014-09-16 14:35:31 -06:00
parent 4219b7192a
commit 5a9cae7d0f
44 changed files with 123 additions and 88 deletions

View File

@ -0,0 +1 @@
source "https://rubygems.org"

View File

@ -1,5 +1,5 @@
Portions copyright (c) 2005 Tobias Luetke
Portions copyright (c) 2011 Instructure Inc.
Portions copyright (c) 2011-2014 Instructure Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@ -0,0 +1,22 @@
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "delayed/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "delayed_job"
s.version = Delayed::VERSION
s.authors = ["Tobias Luetke", "Brian Palmer"]
s.email = ["brianp@instructure.com"]
s.homepage = "http://www.instructure.com"
s.summary = "Instructure-maintained fork of delayed_job"
s.files = Dir["{app,config,db,lib}/**/*"]
s.test_files = Dir["spec_canvas/**/*"]
s.add_dependency "rails", ">= 3.2", "< 4.2"
s.add_dependency 'rufus-scheduler', '2.0.6'
s.add_dependency 'redis-scripting', '1.0.1'
end

View File

@ -15,9 +15,11 @@
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
require 'redis/scripting'
# This module handles loading the Lua functions into Redis and running them
module Delayed::Backend::Redis
class Functions < Redis::Scripting::Module
class Functions < ::Redis::Scripting::Module
def initialize(redis)
super(redis, File.dirname(__FILE__))
end

View File

@ -28,6 +28,7 @@
# * have a master auditor that fails jobs if a whole pool dies
# * audit strands ocasionally, look for any stuck strands where the strand queue isn't empty but there's no strand job running or queued
module Delayed::Backend::Redis
require 'delayed/backend/redis/functions'
class Job
extend ActiveModel::Callbacks

View File

@ -1,3 +1,5 @@
require 'rufus-scheduler'
module Delayed
class Periodic
attr_reader :name, :cron

View File

@ -0,0 +1,3 @@
module Delayed
VERSION = "1.0.0"
end

View File

@ -0,0 +1,25 @@
module Delayed
MIN_PRIORITY = 0
HIGH_PRIORITY = 0
NORMAL_PRIORITY = 10
LOW_PRIORITY = 20
LOWER_PRIORITY = 50
MAX_PRIORITY = 1_000_000
end
require 'delayed/backend/base'
require 'delayed/backend/active_record'
require 'delayed/backend/redis/job'
require 'delayed/batch'
require 'delayed/job_tracking'
require 'delayed/lifecycle'
require 'delayed/message_sending'
require 'delayed/performable_method'
require 'delayed/periodic'
require 'delayed/pool'
require 'delayed/stats'
require 'delayed/worker'
require 'delayed/yaml_extensions'
Object.send(:include, Delayed::MessageSending)
Module.send(:include, Delayed::MessageSending::ClassMethods)

View File

@ -1,4 +1,4 @@
require File.expand_path("../../../../../spec/sharding_spec_helper", __FILE__)
require File.expand_path("../../../../../../spec/sharding_spec_helper", __FILE__)
shared_examples_for 'Delayed::Batch' do
before :each do
@ -9,9 +9,9 @@ shared_examples_for 'Delayed::Batch' do
it "should batch up all deferrable delayed methods" do
later = 1.hour.from_now
Delayed::Batch.serial_batch {
"string".send_later_enqueue_args(:size, no_delay: true).should be_true
"string".send_later_enqueue_args(:reverse, run_at: later, no_delay: true).should be_true # won't be batched, it'll get its own job
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be_true
"string".send_later_enqueue_args(:size, no_delay: true).should be true
"string".send_later_enqueue_args(:reverse, run_at: later, no_delay: true).should be_truthy # won't be batched, it'll get its own job
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be_truthy
}
batch_jobs = Delayed::Job.find_available(5)
regular_jobs = Delayed::Job.list_jobs(:future, 5)
@ -30,8 +30,8 @@ shared_examples_for 'Delayed::Batch' do
it "should not let you invoke it directly" do
later = 1.hour.from_now
Delayed::Batch.serial_batch {
"string".send_later_enqueue_args(:size, no_delay: true).should be_true
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be_true
"string".send_later_enqueue_args(:size, no_delay: true).should be true
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be true
}
Delayed::Job.jobs_count(:current).should == 1
job = Delayed::Job.find_available(1).first
@ -40,8 +40,8 @@ shared_examples_for 'Delayed::Batch' do
it "should create valid jobs" do
Delayed::Batch.serial_batch {
"string".send_later_enqueue_args(:size, no_delay: true).should be_true
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be_true
"string".send_later_enqueue_args(:size, no_delay: true).should be true
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be true
}
Delayed::Job.jobs_count(:current).should == 1
@ -64,16 +64,16 @@ shared_examples_for 'Delayed::Batch' do
it "should create a different batch for each priority" do
later = 1.hour.from_now
Delayed::Batch.serial_batch {
"string".send_later_enqueue_args(:size, :priority => Delayed::LOW_PRIORITY, :no_delay => true).should be_true
"string".send_later_enqueue_args(:gsub, { :no_delay => true }, /./, "!").should be_true
"string".send_later_enqueue_args(:size, :priority => Delayed::LOW_PRIORITY, :no_delay => true).should be true
"string".send_later_enqueue_args(:gsub, { :no_delay => true }, /./, "!").should be true
}
Delayed::Job.jobs_count(:current).should == 2
end
it "should use the given priority for all, if specified" do
Delayed::Batch.serial_batch(:priority => 11) {
"string".send_later_enqueue_args(:size, :priority => 20, :no_delay => true).should be_true
"string".send_later_enqueue_args(:gsub, { :priority => 15, :no_delay => true }, /./, "!").should be_true
"string".send_later_enqueue_args(:size, :priority => 20, :no_delay => true).should be true
"string".send_later_enqueue_args(:gsub, { :priority => 15, :no_delay => true }, /./, "!").should be true
}
Delayed::Job.jobs_count(:current).should == 1
Delayed::Job.find_available(1).first.priority.should == 11
@ -81,7 +81,7 @@ shared_examples_for 'Delayed::Batch' do
it "should just create the job, if there's only one in the batch" do
Delayed::Batch.serial_batch(:priority => 11) {
"string".send_later_enqueue_args(:size, no_delay: true).should be_true
"string".send_later_enqueue_args(:size, no_delay: true).should be true
}
Delayed::Job.jobs_count(:current).should == 1
Delayed::Job.find_available(1).first.tag.should == "String#size"
@ -94,8 +94,8 @@ shared_examples_for 'Delayed::Batch' do
shard = @shard1 || Shard.default
shard.activate do
Delayed::Batch.serial_batch {
"string".send_later_enqueue_args(:size, no_delay: true).should be_true
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be_true
"string".send_later_enqueue_args(:size, no_delay: true).should be true
"string".send_later_enqueue_args(:gsub, { no_delay: true }, /./, "!").should be true
}
end
job = Delayed::Job.find_available(1).first

View File

@ -41,9 +41,9 @@ shared_examples_for 'random ruby objects' do
obj = TestObject.new
lambda { obj.test_method }.should change { Delayed::Job.jobs_count(:current) }.by(1)
lambda { obj.test_method_with_send_later }.should change { Delayed::Job.jobs_count(:current) }.by(1)
obj.ran.should be_false
obj.ran.should be_falsey
lambda { obj.test_method_without_send_later }.should_not change { Delayed::Job.jobs_count(:current) }
obj.ran.should be_true
obj.ran.should be true
end
it "should work without default_async" do
@ -54,13 +54,13 @@ shared_examples_for 'random ruby objects' do
end
obj = TestObject.new
lambda { obj.test_method_with_send_later }.should change { Delayed::Job.jobs_count(:current) }.by(1)
obj.ran.should be_false
obj.ran.should be_falsey
lambda { obj.test_method }.should_not change { Delayed::Job.jobs_count(:current) }
obj.ran.should be_true
obj.ran.should be true
obj.ran = false
obj.ran.should be_false
obj.ran.should be false
lambda { obj.test_method_without_send_later }.should_not change { Delayed::Job.jobs_count(:current) }
obj.ran.should be_true
obj.ran.should be true
end
it "should send along enqueue args and args default async" do
@ -132,9 +132,9 @@ shared_examples_for 'random ruby objects' do
obj = TestObject.new
lambda { obj.test_method? }.should change { Delayed::Job.jobs_count(:current) }.by(1)
lambda { obj.test_method_with_send_later? }.should change { Delayed::Job.jobs_count(:current) }.by(1)
obj.ran.should be_false
obj.ran.should be_falsey
lambda { obj.test_method_without_send_later? }.should_not change { Delayed::Job.jobs_count(:current) }
obj.ran.should be_true
obj.ran.should be true
end
it "should handle punctuation correctly without default_async" do
@ -145,13 +145,13 @@ shared_examples_for 'random ruby objects' do
end
obj = TestObject.new
lambda { obj.test_method_with_send_later? }.should change { Delayed::Job.jobs_count(:current) }.by(1)
obj.ran.should be_false
obj.ran.should be_falsey
lambda { obj.test_method? }.should_not change { Delayed::Job.jobs_count(:current) }
obj.ran.should be_true
obj.ran.should be true
obj.ran = false
obj.ran.should be_false
obj.ran.should be false
lambda { obj.test_method_without_send_later? }.should_not change { Delayed::Job.jobs_count(:current) }
obj.ran.should be_true
obj.ran.should be true
end
it "should handle assignment punctuation correctly with default_async" do
@ -198,12 +198,12 @@ shared_examples_for 'random ruby objects' do
def test_method; end
add_send_later_methods :test_method, {}, true
end
TestObject1.public_method_defined?(:test_method).should be_true
TestObject2.public_method_defined?(:test_method).should be_false
TestObject3.public_method_defined?(:test_method).should be_false
TestObject2.protected_method_defined?(:test_method).should be_true
TestObject3.protected_method_defined?(:test_method).should be_false
TestObject3.private_method_defined?(:test_method).should be_true
TestObject1.public_method_defined?(:test_method).should be true
TestObject2.public_method_defined?(:test_method).should be false
TestObject3.public_method_defined?(:test_method).should be false
TestObject2.protected_method_defined?(:test_method).should be true
TestObject3.protected_method_defined?(:test_method).should be false
TestObject3.private_method_defined?(:test_method).should be true
end
end

View File

@ -13,7 +13,7 @@ shared_examples_for 'a backend' do
it "should not set run_at automatically if already set" do
later = Delayed::Job.db_time_now + 5.minutes
Delayed::Job.create(:payload_object => ErrorJob.new, :run_at => later).run_at.should be_close(later, 1)
Delayed::Job.create(:payload_object => ErrorJob.new, :run_at => later).run_at.should be_within(1).of(later)
end
it "should raise ArgumentError when handler doesn't respond_to :perform" do
@ -43,7 +43,7 @@ shared_examples_for 'a backend' do
it "should be able to set run_at when enqueuing items" do
later = Delayed::Job.db_time_now + 5.minutes
@job = Delayed::Job.enqueue SimpleJob.new, :priority => 5, :run_at => later
@job.run_at.should be_close(later, 1)
@job.run_at.should be_within(1).of(later)
end
it "should work with jobs in modules" do
@ -617,20 +617,20 @@ shared_examples_for 'a backend' do
end
it "should hold a scope of jobs" do
@affected_jobs.all? { |j| j.on_hold? }.should be_false
@ignored_jobs.any? { |j| j.on_hold? }.should be_false
@affected_jobs.all? { |j| j.on_hold? }.should be false
@ignored_jobs.any? { |j| j.on_hold? }.should be false
Delayed::Job.bulk_update('hold', :flavor => @flavor, :query => @query).should == @affected_jobs.size
@affected_jobs.all? { |j| Delayed::Job.find(j.id).on_hold? }.should be_true
@ignored_jobs.any? { |j| Delayed::Job.find(j.id).on_hold? }.should be_false
@affected_jobs.all? { |j| Delayed::Job.find(j.id).on_hold? }.should be true
@ignored_jobs.any? { |j| Delayed::Job.find(j.id).on_hold? }.should be false
end
it "should un-hold a scope of jobs" do
pending "fragile on mysql for unknown reasons" if Delayed::Job == Delayed::Backend::ActiveRecord::Job && %w{MySQL Mysql2}.include?(Delayed::Job.connection.adapter_name)
Delayed::Job.bulk_update('unhold', :flavor => @flavor, :query => @query).should == @affected_jobs.size
@affected_jobs.any? { |j| Delayed::Job.find(j.id).on_hold? }.should be_false
@ignored_jobs.any? { |j| Delayed::Job.find(j.id).on_hold? }.should be_false
@affected_jobs.any? { |j| Delayed::Job.find(j.id).on_hold? }.should be false
@ignored_jobs.any? { |j| Delayed::Job.find(j.id).on_hold? }.should be false
end
it "should delete a scope of jobs" do
@ -699,14 +699,14 @@ shared_examples_for 'a backend' do
j2 = create_job(:run_at => 2.hours.from_now)
j3 = "test".send_later_enqueue_args(:to_i, :strand => 's1', :no_delay => true)
Delayed::Job.bulk_update('hold', :ids => [j1.id, j2.id]).should == 2
Delayed::Job.find(j1.id).on_hold?.should be_true
Delayed::Job.find(j2.id).on_hold?.should be_true
Delayed::Job.find(j3.id).on_hold?.should be_false
Delayed::Job.find(j1.id).on_hold?.should be true
Delayed::Job.find(j2.id).on_hold?.should be true
Delayed::Job.find(j3.id).on_hold?.should be false
Delayed::Job.bulk_update('unhold', :ids => [j2.id]).should == 1
Delayed::Job.find(j1.id).on_hold?.should be_true
Delayed::Job.find(j2.id).on_hold?.should be_false
Delayed::Job.find(j3.id).on_hold?.should be_false
Delayed::Job.find(j1.id).on_hold?.should be true
Delayed::Job.find(j2.id).on_hold?.should be false
Delayed::Job.find(j3.id).on_hold?.should be false
end
it "should delete given job ids" do

View File

@ -130,7 +130,7 @@ shared_examples_for 'Delayed::Worker' do
@job = Delayed::Job.list_jobs(:failed, 1).first
@job.original_job_id.should == old_id
@job.last_error.should =~ /did not work/
@job.last_error.should =~ /worker_spec.rb/
@job.last_error.should =~ /shared\/worker.rb/
@job.attempts.should == 1
@job.failed_at.should_not be_nil
@job.run_at.should > Delayed::Job.db_time_now - 10.minutes

View File

@ -0,0 +1,15 @@
require File.expand_path('../shared/shared_backend', __FILE__)
require File.expand_path('../shared/delayed_batch', __FILE__)
require File.expand_path('../shared/delayed_method', __FILE__)
require File.expand_path('../shared/performable_method', __FILE__)
require File.expand_path('../shared/stats', __FILE__)
require File.expand_path('../shared/worker', __FILE__)
shared_examples_for 'a delayed_jobs implementation' do
include_examples 'a backend'
include_examples 'Delayed::Batch'
include_examples 'random ruby objects'
include_examples 'Delayed::PerformableMethod'
include_examples 'Delayed::Stats'
include_examples 'Delayed::Worker'
end

View File

@ -27,4 +27,4 @@ module MyReverser
end
require File.expand_path('../sample_jobs', __FILE__)
require File.expand_path('../shared_jobs_spec', __FILE__)
require File.expand_path('../shared_jobs_specs', __FILE__)

View File

@ -1,5 +1,5 @@
#!/usr/bin/env ruby
ENV['RUNNING_AS_DAEMON'] = 'true'
require(File.expand_path("../../vendor/plugins/delayed_job/lib/delayed/pool", __FILE__))
require(File.expand_path("../../gems/plugins/delayed_job/lib/delayed/pool", __FILE__))
Delayed::Pool.new.run()

View File

@ -1 +0,0 @@
gem 'rufus-scheduler','2.0.6'

View File

@ -1 +0,0 @@
require File.expand_path(File.dirname(__FILE__) + '/lib/delayed_job')

View File

@ -1,19 +0,0 @@
module Delayed
MIN_PRIORITY = 0
HIGH_PRIORITY = 0
NORMAL_PRIORITY = 10
LOW_PRIORITY = 20
LOWER_PRIORITY = 50
MAX_PRIORITY = 1_000_000
end
require File.expand_path(File.dirname(__FILE__) + '/delayed/message_sending')
require File.expand_path(File.dirname(__FILE__) + '/delayed/performable_method')
require File.expand_path(File.dirname(__FILE__) + '/delayed/backend/base')
require File.expand_path(File.dirname(__FILE__) + '/delayed/backend/active_record')
require File.expand_path(File.dirname(__FILE__) + '/delayed/worker')
require File.expand_path(File.dirname(__FILE__) + '/delayed/lifecycle')
require File.expand_path(File.dirname(__FILE__) + '/delayed/yaml_extensions')
Object.send(:include, Delayed::MessageSending)
Module.send(:include, Delayed::MessageSending::ClassMethods)

View File

@ -1,15 +0,0 @@
require File.expand_path('../shared_backend_spec', __FILE__)
require File.expand_path('../delayed_batch_spec', __FILE__)
require File.expand_path('../delayed_method_spec', __FILE__)
require File.expand_path('../performable_method_spec', __FILE__)
require File.expand_path('../stats_spec', __FILE__)
require File.expand_path('../worker_spec', __FILE__)
shared_examples_for 'a delayed_jobs implementation' do
include_examples 'a backend'
include_examples 'Delayed::Batch'
include_examples 'random ruby objects'
include_examples 'Delayed::PerformableMethod'
include_examples 'Delayed::Stats'
include_examples 'Delayed::Worker'
end