mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Add 'activejob/' from commit '14f74a8331f94150dfee653224de8fc837797709'
git-subtree-dir: activejob git-subtree-mainline:b45b99894a
git-subtree-split:14f74a8331
This commit is contained in:
commit
a75f085941
104 changed files with 2276 additions and 0 deletions
2
activejob/.gitignore
vendored
Normal file
2
activejob/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/test/dummy/log/*
|
||||
/test/dummy/tmp/*
|
39
activejob/.travis.yml
Normal file
39
activejob/.travis.yml
Normal file
|
@ -0,0 +1,39 @@
|
|||
before_install:
|
||||
- travis_retry gem install bundler
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install beanstalkd
|
||||
- echo "START=yes" | sudo tee -a /etc/default/beanstalkd
|
||||
- sudo /etc/init.d/beanstalkd start
|
||||
|
||||
rvm:
|
||||
- 1.9.3
|
||||
- 2.0.0
|
||||
- 2.1
|
||||
- ruby-head
|
||||
- rbx-2
|
||||
- jruby
|
||||
env:
|
||||
- QC_DATABASE_URL="postgres://postgres@localhost/active_jobs_qc_int_test" QUE_DATABASE_URL="postgres://postgres@localhost/active_jobs_qc_int_test"
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rvm: rbx-2
|
||||
- rvm: jruby
|
||||
- rvm: ruby-head
|
||||
fast_finish: true
|
||||
notifications:
|
||||
email: false
|
||||
irc:
|
||||
on_success: change
|
||||
on_failure: always
|
||||
channels:
|
||||
- irc.freenode.org#rails-contrib
|
||||
campfire:
|
||||
on_success: change
|
||||
on_failure: always
|
||||
rooms:
|
||||
- secure: AgZwJA+9VdnWAw7QN9Z5s6RpQIzsEB0q7V+p3pCzXY45156WocL8iNQx+KnyOQ8jbRUt4L/XIOiZl5xHf4pHjXytHWHNhetAlVQP/hPeDcCSk/h0g5gqgf6QABdp38tBNaUq866bXHgCOZYPwwP9bypcmuv2SLyfIO+b/PBgqN0=
|
||||
services:
|
||||
- redis
|
||||
- rabbitmq
|
||||
addons:
|
||||
postgresql: "9.3"
|
1
activejob/CHANGELOG.md
Normal file
1
activejob/CHANGELOG.md
Normal file
|
@ -0,0 +1 @@
|
|||
* Started project.
|
25
activejob/Gemfile
Normal file
25
activejob/Gemfile
Normal file
|
@ -0,0 +1,25 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gemspec
|
||||
|
||||
gem 'rake'
|
||||
gem 'resque'
|
||||
gem 'resque-scheduler'
|
||||
gem 'sidekiq'
|
||||
gem 'sucker_punch'
|
||||
gem 'delayed_job'
|
||||
gem 'queue_classic'
|
||||
gem 'sneakers', '0.1.1.pre'
|
||||
gem 'que'
|
||||
gem 'backburner'
|
||||
gem 'qu-rails', github: "bkeepers/qu", branch: "master"
|
||||
gem 'qu-redis'
|
||||
|
||||
#for integration testing
|
||||
gem 'arel', github: 'rails/arel'
|
||||
gem 'rack', github: 'rack/rack'
|
||||
gem 'i18n', github: 'svenfuchs/i18n'
|
||||
gem 'rails', github: 'rails/rails'
|
||||
gem 'sqlite3'
|
||||
gem 'delayed_job_active_record'
|
||||
gem 'sequel'
|
206
activejob/Gemfile.lock
Normal file
206
activejob/Gemfile.lock
Normal file
|
@ -0,0 +1,206 @@
|
|||
GIT
|
||||
remote: git://github.com/bkeepers/qu.git
|
||||
revision: 50f3788f2b55ddd4dc939767fb35aebefa260322
|
||||
branch: master
|
||||
specs:
|
||||
qu (0.2.0)
|
||||
qu-rails (0.2.0)
|
||||
qu (= 0.2.0)
|
||||
railties (>= 3.2, < 5)
|
||||
qu-redis (0.2.0)
|
||||
qu (= 0.2.0)
|
||||
redis-namespace
|
||||
|
||||
GIT
|
||||
remote: git://github.com/rack/rack.git
|
||||
revision: e98a9f7ef0ddd9589145ea953948c73a8ce3caa9
|
||||
specs:
|
||||
rack (1.6.0.alpha)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/rails/arel.git
|
||||
revision: 66cee768bc163537087037a583f60639eae49fc3
|
||||
specs:
|
||||
arel (6.0.0.20140505020427)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/rails/rails.git
|
||||
revision: b2e88043b52a8f83820a0f4e8a65aa42fd40c544
|
||||
specs:
|
||||
actionmailer (4.2.0.alpha)
|
||||
actionpack (= 4.2.0.alpha)
|
||||
actionview (= 4.2.0.alpha)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
actionpack (4.2.0.alpha)
|
||||
actionview (= 4.2.0.alpha)
|
||||
activesupport (= 4.2.0.alpha)
|
||||
rack (~> 1.6.0.alpha)
|
||||
rack-test (~> 0.6.2)
|
||||
actionview (4.2.0.alpha)
|
||||
activesupport (= 4.2.0.alpha)
|
||||
builder (~> 3.1)
|
||||
erubis (~> 2.7.0)
|
||||
activemodel (4.2.0.alpha)
|
||||
activesupport (= 4.2.0.alpha)
|
||||
builder (~> 3.1)
|
||||
activerecord (4.2.0.alpha)
|
||||
activemodel (= 4.2.0.alpha)
|
||||
activesupport (= 4.2.0.alpha)
|
||||
arel (~> 6.0.0)
|
||||
activesupport (4.2.0.alpha)
|
||||
i18n (>= 0.7.0.dev, < 0.8)
|
||||
json (~> 1.7, >= 1.7.7)
|
||||
minitest (~> 5.1)
|
||||
thread_safe (~> 0.1)
|
||||
tzinfo (~> 1.1)
|
||||
rails (4.2.0.alpha)
|
||||
actionmailer (= 4.2.0.alpha)
|
||||
actionpack (= 4.2.0.alpha)
|
||||
actionview (= 4.2.0.alpha)
|
||||
activemodel (= 4.2.0.alpha)
|
||||
activerecord (= 4.2.0.alpha)
|
||||
activesupport (= 4.2.0.alpha)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.2.0.alpha)
|
||||
sprockets-rails (~> 2.1)
|
||||
railties (4.2.0.alpha)
|
||||
actionpack (= 4.2.0.alpha)
|
||||
activesupport (= 4.2.0.alpha)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/svenfuchs/i18n.git
|
||||
revision: cb679b8cdbab675703a3f88de4d48a48f7b50e06
|
||||
specs:
|
||||
i18n (0.7.0.dev)
|
||||
|
||||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
activejob (4.2.0.alpha)
|
||||
activemodel-globalid
|
||||
activesupport (>= 4.1.0)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
activemodel-globalid (0.1.1)
|
||||
activemodel (>= 4.1.0)
|
||||
activesupport (>= 4.1.0)
|
||||
amq-protocol (1.9.2)
|
||||
backburner (0.4.5)
|
||||
beaneater (~> 0.3.1)
|
||||
dante (~> 0.1.5)
|
||||
beaneater (0.3.2)
|
||||
builder (3.2.2)
|
||||
bunny (1.1.9)
|
||||
amq-protocol (>= 1.9.2)
|
||||
celluloid (0.15.2)
|
||||
timers (~> 1.1.0)
|
||||
connection_pool (2.0.0)
|
||||
dante (0.1.5)
|
||||
delayed_job (4.0.2)
|
||||
activesupport (>= 3.0, < 4.2)
|
||||
delayed_job_active_record (4.0.1)
|
||||
activerecord (>= 3.0, < 4.2)
|
||||
delayed_job (>= 3.0, < 4.1)
|
||||
erubis (2.7.0)
|
||||
hike (1.2.3)
|
||||
json (1.8.1)
|
||||
mail (2.6.1)
|
||||
mime-types (>= 1.16, < 3)
|
||||
mime-types (2.3)
|
||||
minitest (5.4.0)
|
||||
mono_logger (1.1.0)
|
||||
multi_json (1.10.1)
|
||||
pg (0.17.1)
|
||||
que (0.8.1)
|
||||
queue_classic (2.2.3)
|
||||
pg (~> 0.17.0)
|
||||
rack-protection (1.5.3)
|
||||
rack
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rake (10.3.2)
|
||||
redis (3.1.0)
|
||||
redis-namespace (1.5.1)
|
||||
redis (~> 3.0, >= 3.0.4)
|
||||
resque (1.25.2)
|
||||
mono_logger (~> 1.0)
|
||||
multi_json (~> 1.0)
|
||||
redis-namespace (~> 1.3)
|
||||
sinatra (>= 0.9.2)
|
||||
vegas (~> 0.1.2)
|
||||
resque-scheduler (3.0.0)
|
||||
mono_logger (~> 1.0)
|
||||
redis (~> 3.0)
|
||||
resque (~> 1.25)
|
||||
rufus-scheduler (~> 2.0)
|
||||
rufus-scheduler (2.0.24)
|
||||
tzinfo (>= 0.3.22)
|
||||
sequel (4.8.0)
|
||||
serverengine (1.5.9)
|
||||
sigdump (~> 0.2.2)
|
||||
sidekiq (3.2.1)
|
||||
celluloid (>= 0.15.2)
|
||||
connection_pool (>= 2.0.0)
|
||||
json
|
||||
redis (>= 3.0.6)
|
||||
redis-namespace (>= 1.3.1)
|
||||
sigdump (0.2.2)
|
||||
sinatra (1.4.5)
|
||||
rack (~> 1.4)
|
||||
rack-protection (~> 1.4)
|
||||
tilt (~> 1.3, >= 1.3.4)
|
||||
sneakers (0.1.1.pre)
|
||||
bunny (~> 1.1.3)
|
||||
serverengine
|
||||
thor
|
||||
thread
|
||||
sprockets (2.12.1)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sprockets-rails (2.1.3)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (~> 2.8)
|
||||
sqlite3 (1.3.9)
|
||||
sucker_punch (1.1)
|
||||
celluloid (~> 0.15.2)
|
||||
thor (0.19.1)
|
||||
thread (0.1.4)
|
||||
thread_safe (0.3.4)
|
||||
tilt (1.4.1)
|
||||
timers (1.1.0)
|
||||
tzinfo (1.2.1)
|
||||
thread_safe (~> 0.1)
|
||||
vegas (0.1.11)
|
||||
rack (>= 1.0.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
activejob!
|
||||
arel!
|
||||
backburner
|
||||
delayed_job
|
||||
delayed_job_active_record
|
||||
i18n!
|
||||
qu-rails!
|
||||
qu-redis
|
||||
que
|
||||
queue_classic
|
||||
rack!
|
||||
rails!
|
||||
rake
|
||||
resque
|
||||
resque-scheduler
|
||||
sequel
|
||||
sidekiq
|
||||
sneakers (= 0.1.1.pre)
|
||||
sqlite3
|
||||
sucker_punch
|
21
activejob/MIT-LICENSE
Normal file
21
activejob/MIT-LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
Copyright (c) 2014 David Heinemeier Hansson
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
120
activejob/README.md
Normal file
120
activejob/README.md
Normal file
|
@ -0,0 +1,120 @@
|
|||
# Active Job -- Make work happen later
|
||||
|
||||
Active Job is a framework for declaring jobs and making them run on a variety
|
||||
of queueing backends. These jobs can be everything from regularly scheduled
|
||||
clean-ups, billing charges, or mailings. Anything that can be chopped up into
|
||||
small units of work and run in parallel, really.
|
||||
|
||||
It also serves as the backend for [ActionMailer's #deliver_later functionality](https://github.com/rails/activejob/issues/13)
|
||||
that makes it easy to turn any mailing into a job for running later. That's
|
||||
one of the most common jobs in a modern web application: Sending emails outside
|
||||
of the request-response cycle, so the user doesn't have to wait on it.
|
||||
|
||||
The main point is to ensure that all Rails apps will have a job infrastructure
|
||||
in place, even if it's in the form of an "immediate runner". We can then have
|
||||
framework features and other gems build on top of that, without having to worry
|
||||
about API differences between Delayed Job and Resque. Picking your queuing
|
||||
backend becomes more of an operational concern, then. And you'll be able to
|
||||
switch between them without having to rewrite your jobs.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Set the queue adapter for Active Job:
|
||||
|
||||
``` ruby
|
||||
ActiveJob::Base.queue_adapter = :inline # default queue adapter
|
||||
# Adapters currently supported: :backburner, :delayed_job, :qu, :que, :queue_classic,
|
||||
# :resque, :sidekiq, :sneakers, :sucker_punch
|
||||
```
|
||||
|
||||
Declare a job like so:
|
||||
|
||||
```ruby
|
||||
class MyJob < ActiveJob::Base
|
||||
queue_as :my_jobs
|
||||
|
||||
def perform(record)
|
||||
record.do_work
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Enqueue a job like so:
|
||||
|
||||
```ruby
|
||||
MyJob.enqueue record # Enqueue a job to be performed as soon the queueing system is free.
|
||||
```
|
||||
|
||||
```ruby
|
||||
MyJob.enqueue_at Date.tomorrow.noon, record # Enqueue a job to be performed tomorrow at noon.
|
||||
```
|
||||
|
||||
```ruby
|
||||
MyJob.enqueue_in 1.week, record # Enqueue a job to be performed 1 week from now.
|
||||
```
|
||||
|
||||
That's it!
|
||||
|
||||
|
||||
## GlobalID support
|
||||
|
||||
Active Job supports [GlobalID serialization](https://github.com/rails/activemodel-globalid/) for parameters. This makes it possible
|
||||
to pass live Active Record objects to your job instead of class/id pairs, which
|
||||
you then have to manually deserialize. Before, jobs would look like this:
|
||||
|
||||
```ruby
|
||||
class TrashableCleanupJob
|
||||
def perform(trashable_class, trashable_id, depth)
|
||||
trashable = trashable_class.constantize.find(trashable_id)
|
||||
trashable.cleanup(depth)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
Now you can simply do:
|
||||
|
||||
```ruby
|
||||
class TrashableCleanupJob
|
||||
def perform(trashable, depth)
|
||||
trashable.cleanup(depth)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
This works with any class that mixes in ActiveModel::GlobalIdentification, which
|
||||
by default has been mixed into Active Record classes.
|
||||
|
||||
|
||||
## Supported queueing systems
|
||||
|
||||
We currently have adapters for:
|
||||
|
||||
* [Backburner](https://github.com/nesquena/backburner)
|
||||
* [Delayed Job](https://github.com/collectiveidea/delayed_job)
|
||||
* [Qu](https://github.com/bkeepers/qu)
|
||||
* [Que](https://github.com/chanks/que)
|
||||
* [QueueClassic](https://github.com/ryandotsmith/queue_classic)
|
||||
* [Resque 1.x](https://github.com/resque/resque)
|
||||
* [Sidekiq](https://github.com/mperham/sidekiq)
|
||||
* [Sneakers](https://github.com/jondot/sneakers)
|
||||
* [Sucker Punch](https://github.com/brandonhilkert/sucker_punch)
|
||||
|
||||
|
||||
## Auxiliary gems
|
||||
|
||||
* [activejob-stats](https://github.com/seuros/activejob-stats)
|
||||
|
||||
## Under development as a gem, targeted for Rails inclusion
|
||||
|
||||
Active Job is currently being developed in a separate repository until it's
|
||||
ready to be merged in with Rails. The current plan is to have Active Job
|
||||
be part of the Rails 4.2 release, but plans may change depending on when
|
||||
this framework stabilizes and feels ready.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Active Job is released under the MIT license:
|
||||
|
||||
* http://www.opensource.org/licenses/MIT
|
68
activejob/Rakefile
Normal file
68
activejob/Rakefile
Normal file
|
@ -0,0 +1,68 @@
|
|||
require 'bundler/gem_tasks'
|
||||
|
||||
require 'rake/testtask'
|
||||
|
||||
def run_without_aborting(*tasks)
|
||||
errors = []
|
||||
|
||||
tasks.each do |task|
|
||||
begin
|
||||
Rake::Task[task].invoke
|
||||
rescue Exception
|
||||
errors << task
|
||||
end
|
||||
end
|
||||
|
||||
abort "Errors running #{errors.join(', ')}" if errors.any?
|
||||
end
|
||||
|
||||
task default: :test
|
||||
|
||||
ADAPTERS = %w(inline delayed_job qu que queue_classic resque sidekiq sneakers sucker_punch backburner)
|
||||
|
||||
desc 'Run all adapter tests'
|
||||
task :test do
|
||||
tasks = ADAPTERS.map{|a| "test_#{a}" }+["integration_test"]
|
||||
run_without_aborting(*tasks)
|
||||
end
|
||||
|
||||
ADAPTERS.each do |adapter|
|
||||
Rake::TestTask.new("test_#{adapter}") do |t|
|
||||
t.libs << 'test'
|
||||
t.test_files = FileList['test/cases/**/*_test.rb']
|
||||
t.verbose = true
|
||||
end
|
||||
|
||||
namespace adapter do
|
||||
task test: "test_#{adapter}"
|
||||
task(:env) { ENV['AJADAPTER'] = adapter }
|
||||
end
|
||||
|
||||
task "test_#{adapter}" => "#{adapter}:env"
|
||||
end
|
||||
|
||||
|
||||
|
||||
desc 'Run all adapter integration tests'
|
||||
task :integration_test do
|
||||
tasks = (ADAPTERS-['inline']).map{|a| "integration_test_#{a}" }
|
||||
run_without_aborting(*tasks)
|
||||
end
|
||||
|
||||
(ADAPTERS-['inline']).each do |adapter|
|
||||
Rake::TestTask.new("integration_test_#{adapter}") do |t|
|
||||
t.libs << 'test'
|
||||
t.test_files = FileList['test/integration/**/*_test.rb']
|
||||
t.verbose = true
|
||||
end
|
||||
|
||||
namespace "integration_#{adapter}" do
|
||||
task test: "integration_test_#{adapter}"
|
||||
task(:env) do
|
||||
ENV['AJADAPTER'] = adapter
|
||||
ENV['AJ_INTEGRATION_TESTS'] = "1"
|
||||
end
|
||||
end
|
||||
|
||||
task "integration_test_#{adapter}" => "integration_#{adapter}:env"
|
||||
end
|
21
activejob/activejob.gemspec
Normal file
21
activejob/activejob.gemspec
Normal file
|
@ -0,0 +1,21 @@
|
|||
Gem::Specification.new do |s|
|
||||
s.platform = Gem::Platform::RUBY
|
||||
s.name = 'activejob'
|
||||
s.version = '4.2.0.alpha'
|
||||
s.summary = 'Job framework with pluggable queues (will be part of Rails).'
|
||||
s.description = 'Declare job classes that can be run by a variety of queueing backends.'
|
||||
|
||||
s.required_ruby_version = '>= 1.9.3'
|
||||
|
||||
s.license = 'MIT'
|
||||
|
||||
s.author = 'David Heinemeier Hansson'
|
||||
s.email = 'david@loudthinking.com'
|
||||
s.homepage = 'http://www.rubyonrails.org'
|
||||
|
||||
s.files = Dir['CHANGELOG.md', 'MIT-LICENSE', 'README.rdoc', 'lib/**/*']
|
||||
s.require_path = 'lib'
|
||||
|
||||
s.add_dependency 'activesupport', '>= 4.1.0'
|
||||
s.add_dependency 'activemodel-globalid'
|
||||
end
|
34
activejob/lib/active_job.rb
Normal file
34
activejob/lib/active_job.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
#--
|
||||
# Copyright (c) 2014 David Heinemeier Hansson
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining
|
||||
# a copy of this software and associated documentation files (the
|
||||
# "Software"), to deal in the Software without restriction, including
|
||||
# without limitation the rights to use, copy, modify, merge, publish,
|
||||
# distribute, sublicense, and/or sell copies of the Software, and to
|
||||
# permit persons to whom the Software is furnished to do so, subject to
|
||||
# the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be
|
||||
# included in all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#++
|
||||
|
||||
require 'active_support'
|
||||
require 'active_support/rails'
|
||||
|
||||
require 'active_job/railtie' if defined?(Rails)
|
||||
require 'active_job/version'
|
||||
|
||||
module ActiveJob
|
||||
extend ActiveSupport::Autoload
|
||||
|
||||
autoload :Base
|
||||
end
|
52
activejob/lib/active_job/arguments.rb
Normal file
52
activejob/lib/active_job/arguments.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
require 'active_model/global_locator'
|
||||
require 'active_model/global_identification'
|
||||
|
||||
module ActiveJob
|
||||
class Arguments
|
||||
TYPE_WHITELIST = [ NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ]
|
||||
|
||||
def self.serialize(arguments)
|
||||
arguments.map { |argument| serialize_argument(argument) }
|
||||
end
|
||||
|
||||
def self.deserialize(arguments)
|
||||
arguments.map { |argument| deserialize_argument(argument) }
|
||||
end
|
||||
|
||||
private
|
||||
def self.serialize_argument(argument)
|
||||
case argument
|
||||
when ActiveModel::GlobalIdentification
|
||||
argument.global_id.to_s
|
||||
when *TYPE_WHITELIST
|
||||
argument
|
||||
when Array
|
||||
serialize(argument)
|
||||
when Hash
|
||||
Hash[ argument.map { |key, value| [ serialize_hash_key(key), serialize_argument(value) ] } ]
|
||||
else
|
||||
raise "Unsupported argument type: #{argument.class.name}"
|
||||
end
|
||||
end
|
||||
|
||||
def self.deserialize_argument(argument)
|
||||
case argument
|
||||
when Array
|
||||
deserialize(argument)
|
||||
when Hash
|
||||
Hash[ argument.map { |key, value| [ key, deserialize_argument(value) ] } ].with_indifferent_access
|
||||
else
|
||||
ActiveModel::GlobalLocator.locate(argument) || argument
|
||||
end
|
||||
end
|
||||
|
||||
def self.serialize_hash_key(key)
|
||||
case key
|
||||
when String, Symbol
|
||||
key.to_s
|
||||
else
|
||||
raise "Unsupported hash key type: #{key.class.name}"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
22
activejob/lib/active_job/base.rb
Normal file
22
activejob/lib/active_job/base.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require 'active_job/queue_adapter'
|
||||
require 'active_job/queue_name'
|
||||
require 'active_job/enqueuing'
|
||||
require 'active_job/execution'
|
||||
require 'active_job/callbacks'
|
||||
require 'active_job/identifier'
|
||||
require 'active_job/logging'
|
||||
|
||||
module ActiveJob
|
||||
class Base
|
||||
extend QueueAdapter
|
||||
|
||||
include QueueName
|
||||
include Enqueuing
|
||||
include Execution
|
||||
include Callbacks
|
||||
include Identifier
|
||||
include Logging
|
||||
|
||||
ActiveSupport.run_load_hooks(:active_job, self)
|
||||
end
|
||||
end
|
40
activejob/lib/active_job/callbacks.rb
Normal file
40
activejob/lib/active_job/callbacks.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
require 'active_support/callbacks'
|
||||
|
||||
module ActiveJob
|
||||
module Callbacks
|
||||
extend ActiveSupport::Concern
|
||||
include ActiveSupport::Callbacks
|
||||
|
||||
included do
|
||||
define_callbacks :perform
|
||||
define_callbacks :enqueue
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def before_perform(*filters, &blk)
|
||||
set_callback(:perform, :before, *filters, &blk)
|
||||
end
|
||||
|
||||
def after_perform(*filters, &blk)
|
||||
set_callback(:perform, :after, *filters, &blk)
|
||||
end
|
||||
|
||||
def around_perform(*filters, &blk)
|
||||
set_callback(:perform, :around, *filters, &blk)
|
||||
end
|
||||
|
||||
|
||||
def before_enqueue(*filters, &blk)
|
||||
set_callback(:enqueue, :before, *filters, &blk)
|
||||
end
|
||||
|
||||
def after_enqueue(*filters, &blk)
|
||||
set_callback(:enqueue, :after, *filters, &blk)
|
||||
end
|
||||
|
||||
def around_enqueue(*filters, &blk)
|
||||
set_callback(:enqueue, :around, *filters, &blk)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
71
activejob/lib/active_job/enqueuing.rb
Normal file
71
activejob/lib/active_job/enqueuing.rb
Normal file
|
@ -0,0 +1,71 @@
|
|||
require 'active_job/arguments'
|
||||
|
||||
module ActiveJob
|
||||
module Enqueuing
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
# Push a job onto the queue. The arguments must be legal JSON types
|
||||
# (string, int, float, nil, true, false, hash or array) or
|
||||
# ActiveModel::GlobalIdentication instances. Arbitrary Ruby objects
|
||||
# are not supported.
|
||||
#
|
||||
# Returns an instance of the job class queued with args available in
|
||||
# Job#arguments.
|
||||
def enqueue(*args)
|
||||
new(args).tap do |job|
|
||||
job.run_callbacks :enqueue do
|
||||
queue_adapter.enqueue self, job.job_id, *Arguments.serialize(args)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Enqueue a job to be performed at +interval+ from now.
|
||||
#
|
||||
# enqueue_in(1.week, "mike")
|
||||
#
|
||||
# Returns an instance of the job class queued with args available in
|
||||
# Job#arguments and the timestamp in Job#enqueue_at.
|
||||
def enqueue_in(interval, *args)
|
||||
enqueue_at interval.seconds.from_now, *args
|
||||
end
|
||||
|
||||
# Enqueue a job to be performed at an explicit point in time.
|
||||
#
|
||||
# enqueue_at(Date.tomorrow.midnight, "mike")
|
||||
#
|
||||
# Returns an instance of the job class queued with args available in
|
||||
# Job#arguments and the timestamp in Job#enqueue_at.
|
||||
def enqueue_at(timestamp, *args)
|
||||
new(args).tap do |job|
|
||||
job.enqueued_at = timestamp
|
||||
|
||||
job.run_callbacks :enqueue do
|
||||
queue_adapter.enqueue_at self, timestamp.to_f, job.job_id, *Arguments.serialize(args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
included do
|
||||
attr_accessor :arguments
|
||||
attr_accessor :enqueued_at
|
||||
end
|
||||
|
||||
def initialize(arguments = nil)
|
||||
@arguments = arguments
|
||||
end
|
||||
|
||||
def retry_now
|
||||
self.class.enqueue *arguments
|
||||
end
|
||||
|
||||
def retry_in(interval)
|
||||
self.class.enqueue_in interval, *arguments
|
||||
end
|
||||
|
||||
def retry_at(timestamp)
|
||||
self.class.enqueue_at timestamp, *arguments
|
||||
end
|
||||
end
|
||||
end
|
27
activejob/lib/active_job/execution.rb
Normal file
27
activejob/lib/active_job/execution.rb
Normal file
|
@ -0,0 +1,27 @@
|
|||
require 'active_support/rescuable'
|
||||
require 'active_job/arguments'
|
||||
|
||||
module ActiveJob
|
||||
module Execution
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include ActiveSupport::Rescuable
|
||||
end
|
||||
|
||||
def execute(job_id, *serialized_args)
|
||||
self.job_id = job_id
|
||||
self.arguments = Arguments.deserialize(serialized_args)
|
||||
|
||||
run_callbacks :perform do
|
||||
perform *arguments
|
||||
end
|
||||
rescue => exception
|
||||
rescue_with_handler(exception) || raise(exception)
|
||||
end
|
||||
|
||||
def perform(*)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
15
activejob/lib/active_job/gem_version.rb
Normal file
15
activejob/lib/active_job/gem_version.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
module ActiveJob
|
||||
# Returns the version of the currently loaded ActiveJob as a <tt>Gem::Version</tt>
|
||||
def self.gem_version
|
||||
Gem::Version.new VERSION::STRING
|
||||
end
|
||||
|
||||
module VERSION
|
||||
MAJOR = 4
|
||||
MINOR = 2
|
||||
TINY = 0
|
||||
PRE = "alpha"
|
||||
|
||||
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
||||
end
|
||||
end
|
15
activejob/lib/active_job/identifier.rb
Normal file
15
activejob/lib/active_job/identifier.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
require 'active_job/arguments'
|
||||
|
||||
module ActiveJob
|
||||
module Identifier
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
attr_writer :job_id
|
||||
end
|
||||
|
||||
def job_id
|
||||
@job_id ||= SecureRandom.uuid
|
||||
end
|
||||
end
|
||||
end
|
88
activejob/lib/active_job/logging.rb
Normal file
88
activejob/lib/active_job/logging.rb
Normal file
|
@ -0,0 +1,88 @@
|
|||
require 'active_support/core_ext/string/filters'
|
||||
|
||||
module ActiveJob
|
||||
module Logging
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
cattr_accessor(:logger) { ActiveSupport::TaggedLogging.new(ActiveSupport::Logger.new(STDOUT)) }
|
||||
|
||||
around_enqueue do |job, block, _|
|
||||
tag_logger do
|
||||
block.call
|
||||
end
|
||||
end
|
||||
|
||||
around_perform do |job, block, _|
|
||||
tag_logger(job.class.name, job.job_id) do
|
||||
payload = {adapter: job.class.queue_adapter, job: job.class, args: job.arguments}
|
||||
ActiveSupport::Notifications.instrument("perform_start.active_job", payload.dup)
|
||||
ActiveSupport::Notifications.instrument("perform.active_job", payload) do |payload|
|
||||
block.call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
before_enqueue do |job|
|
||||
if job.enqueued_at
|
||||
ActiveSupport::Notifications.instrument "enqueue_at.active_job",
|
||||
adapter: job.class.queue_adapter, job: job.class, job_id: job.job_id, args: job.arguments, timestamp: job.enqueued_at
|
||||
else
|
||||
ActiveSupport::Notifications.instrument "enqueue.active_job",
|
||||
adapter: job.class.queue_adapter, job: job.class, job_id: job.job_id, args: job.arguments
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def tag_logger(*tags)
|
||||
if logger.respond_to?(:tagged)
|
||||
tags.unshift "ActiveJob" unless logger_tagged_by_active_job?
|
||||
ActiveJob::Base.logger.tagged(*tags){ yield }
|
||||
else
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def logger_tagged_by_active_job?
|
||||
logger.formatter.current_tags.include?("ActiveJob")
|
||||
end
|
||||
|
||||
class LogSubscriber < ActiveSupport::LogSubscriber
|
||||
def enqueue(event)
|
||||
info "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)}" + args_info(event)
|
||||
end
|
||||
|
||||
def enqueue_at(event)
|
||||
info "Enqueued #{event.payload[:job].name} (Job ID: #{event.payload[:job_id]}) to #{queue_name(event)} at #{enqueued_at(event)}" + args_info(event)
|
||||
end
|
||||
|
||||
def perform_start(event)
|
||||
info "Performing #{event.payload[:job].name} from #{queue_name(event)}" + args_info(event)
|
||||
end
|
||||
|
||||
def perform(event)
|
||||
info "Performed #{event.payload[:job].name} from #{queue_name(event)} in #{event.duration.round(2).to_s}ms"
|
||||
end
|
||||
|
||||
private
|
||||
def queue_name(event)
|
||||
event.payload[:adapter].name.demodulize.remove('Adapter') + "(#{event.payload[:job].queue_name})"
|
||||
end
|
||||
|
||||
def args_info(event)
|
||||
event.payload[:args].any? ? " with arguments: #{event.payload[:args].map(&:inspect).join(", ")}" : ""
|
||||
end
|
||||
|
||||
def enqueued_at(event)
|
||||
Time.at(event.payload[:timestamp]).utc
|
||||
end
|
||||
|
||||
def logger
|
||||
ActiveJob::Base.logger
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ActiveJob::Logging::LogSubscriber.attach_to :active_job
|
24
activejob/lib/active_job/queue_adapter.rb
Normal file
24
activejob/lib/active_job/queue_adapter.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
require 'active_job/queue_adapters/inline_adapter'
|
||||
require 'active_support/core_ext/string/inflections'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapter
|
||||
mattr_reader(:queue_adapter) { ActiveJob::QueueAdapters::InlineAdapter }
|
||||
|
||||
def queue_adapter=(name_or_adapter)
|
||||
@@queue_adapter = \
|
||||
case name_or_adapter
|
||||
when Symbol, String
|
||||
load_adapter(name_or_adapter)
|
||||
when Class
|
||||
name_or_adapter
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_adapter(name)
|
||||
require "active_job/queue_adapters/#{name}_adapter"
|
||||
"ActiveJob::QueueAdapters::#{name.to_s.camelize}Adapter".constantize
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
require 'backburner'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class BackburnerAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
Backburner::Worker.enqueue JobWrapper, [ job.name, *args ], queue: job.queue_name
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper
|
||||
class << self
|
||||
def perform(job_name, *args)
|
||||
job_name.constantize.new.execute *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
require 'delayed_job'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class DelayedJobAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
JobWrapper.new.delay(queue: job.queue_name).perform(job, *args)
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
JobWrapper.new.delay(queue: job.queue_name, run_at: Time.at(timestamp)).perform(job, *args)
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper
|
||||
def perform(job, *args)
|
||||
job.new.execute *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
15
activejob/lib/active_job/queue_adapters/inline_adapter.rb
Normal file
15
activejob/lib/active_job/queue_adapters/inline_adapter.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class InlineAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
job.new.execute *args
|
||||
end
|
||||
|
||||
def enqueue_at(*)
|
||||
raise NotImplementedError.new("Use a queueing backend to enqueue jobs in the future. Read more at https://github.com/rails/activejob")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
30
activejob/lib/active_job/queue_adapters/qu_adapter.rb
Normal file
30
activejob/lib/active_job/queue_adapters/qu_adapter.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require 'qu'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class QuAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
Qu::Payload.new(klass: JobWrapper, args: [job.name, *args]).tap do |payload|
|
||||
payload.instance_variable_set(:@queue, job.queue_name)
|
||||
end.push
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper < Qu::Job
|
||||
def initialize(job_name, *args)
|
||||
@job = job_name.constantize
|
||||
@args = args
|
||||
end
|
||||
|
||||
def perform
|
||||
@job.new.execute *@args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
23
activejob/lib/active_job/queue_adapters/que_adapter.rb
Normal file
23
activejob/lib/active_job/queue_adapters/que_adapter.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'que'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class QueAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
JobWrapper.enqueue job.name, *args, queue: job.queue_name
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper < Que::Job
|
||||
def run(job_name, *args)
|
||||
job_name.constantize.new.execute *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
require 'queue_classic'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class QueueClassicAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
QC::Queue.new(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.name, *args)
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper
|
||||
def self.perform(job_name, *args)
|
||||
job_name.constantize.new.execute *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
38
activejob/lib/active_job/queue_adapters/resque_adapter.rb
Normal file
38
activejob/lib/active_job/queue_adapters/resque_adapter.rb
Normal file
|
@ -0,0 +1,38 @@
|
|||
require 'resque'
|
||||
require 'active_support/core_ext/enumerable'
|
||||
require 'active_support/core_ext/array/access'
|
||||
|
||||
begin
|
||||
require 'resque-scheduler'
|
||||
rescue LoadError
|
||||
begin
|
||||
require 'resque_scheduler'
|
||||
rescue LoadError
|
||||
$stderr.puts 'The ActiveJob resque adapter requires resque-scheduler. Please add it to your Gemfile and run bundle install'
|
||||
raise e
|
||||
end
|
||||
end
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class ResqueAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
Resque.enqueue_to job.queue_name, JobWrapper, job.name, *args
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.name, *args
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper
|
||||
class << self
|
||||
def perform(job_name, *args)
|
||||
job_name.constantize.new.execute *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
35
activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
Normal file
35
activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb
Normal file
|
@ -0,0 +1,35 @@
|
|||
require 'sidekiq'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class SidekiqAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
#Sidekiq::Client does not support symbols as keys
|
||||
Sidekiq::Client.push \
|
||||
'class' => JobWrapper,
|
||||
'queue' => job.queue_name,
|
||||
'args' => [ job, *args ],
|
||||
'retry' => true
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
Sidekiq::Client.push \
|
||||
'class' => JobWrapper,
|
||||
'queue' => job.queue_name,
|
||||
'args' => [ job, *args ],
|
||||
'retry' => true,
|
||||
'at' => timestamp
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper
|
||||
include Sidekiq::Worker
|
||||
|
||||
def perform(job_name, *args)
|
||||
job_name.constantize.new.execute *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
34
activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
Normal file
34
activejob/lib/active_job/queue_adapters/sneakers_adapter.rb
Normal file
|
@ -0,0 +1,34 @@
|
|||
require 'sneakers'
|
||||
require 'thread'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class SneakersAdapter
|
||||
@monitor = Monitor.new
|
||||
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
@monitor.synchronize do
|
||||
JobWrapper.from_queue job.queue_name
|
||||
JobWrapper.enqueue ActiveSupport::JSON.encode([ job.name, *args ])
|
||||
end
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper
|
||||
include Sneakers::Worker
|
||||
from_queue 'active_jobs_default'
|
||||
|
||||
def work(msg)
|
||||
job_name, *args = ActiveSupport::JSON.decode(msg)
|
||||
job_name.constantize.new.execute *args
|
||||
ack!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,25 @@
|
|||
require 'sucker_punch'
|
||||
|
||||
module ActiveJob
|
||||
module QueueAdapters
|
||||
class SuckerPunchAdapter
|
||||
class << self
|
||||
def enqueue(job, *args)
|
||||
JobWrapper.new.async.perform job, *args
|
||||
end
|
||||
|
||||
def enqueue_at(job, timestamp, *args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
|
||||
class JobWrapper
|
||||
include SuckerPunch::Job
|
||||
|
||||
def perform(job, *args)
|
||||
job.new.execute *args
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
18
activejob/lib/active_job/queue_name.rb
Normal file
18
activejob/lib/active_job/queue_name.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module ActiveJob
|
||||
module QueueName
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
module ClassMethods
|
||||
mattr_accessor(:queue_base_name) { "active_jobs" }
|
||||
|
||||
def queue_as(part_name)
|
||||
self.queue_name = "#{queue_base_name}_#{part_name}"
|
||||
end
|
||||
end
|
||||
|
||||
included do
|
||||
class_attribute :queue_name
|
||||
self.queue_name = queue_base_name
|
||||
end
|
||||
end
|
||||
end
|
10
activejob/lib/active_job/railtie.rb
Normal file
10
activejob/lib/active_job/railtie.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
require 'active_model/railtie'
|
||||
|
||||
module ActiveJob
|
||||
# = Active Job Railtie
|
||||
class Railtie < Rails::Railtie # :nodoc:
|
||||
initializer 'active_job' do
|
||||
ActiveSupport.on_load(:active_job) { self.logger = ::Rails.logger }
|
||||
end
|
||||
end
|
||||
end
|
8
activejob/lib/active_job/version.rb
Normal file
8
activejob/lib/active_job/version.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
require_relative 'gem_version'
|
||||
|
||||
module ActiveJob
|
||||
# Returns the version of the currently loaded ActiveJob as a <tt>Gem::Version</tt>
|
||||
def self.version
|
||||
gem_version
|
||||
end
|
||||
end
|
1
activejob/lib/activejob.rb
Normal file
1
activejob/lib/activejob.rb
Normal file
|
@ -0,0 +1 @@
|
|||
require 'active_job'
|
22
activejob/lib/rails/generators/active_job/job_generator.rb
Normal file
22
activejob/lib/rails/generators/active_job/job_generator.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require 'rails/generators/named_base'
|
||||
|
||||
module ActiveJob
|
||||
module Generators # :nodoc:
|
||||
class JobGenerator < Rails::Generators::NamedBase # :nodoc:
|
||||
desc 'This generator creates an active job file at app/jobs'
|
||||
|
||||
class_option :queue, type: :string, default: 'default', desc: 'The queue name for the generated job'
|
||||
|
||||
def self.default_generator_root
|
||||
File.dirname(__FILE__)
|
||||
end
|
||||
|
||||
check_class_collision suffix: 'Job'
|
||||
|
||||
def create_job_file
|
||||
template 'job.rb', File.join('app/jobs', class_path, "#{file_name}_job.rb")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
<% module_namespacing do -%>
|
||||
class <%= class_name %>Job < ActiveJob::Base
|
||||
queue_as :<%= options[:queue] %>
|
||||
|
||||
def perform
|
||||
# Do something later
|
||||
end
|
||||
end
|
||||
<% end -%>
|
3
activejob/test/adapters/backburner.rb
Normal file
3
activejob/test/adapters/backburner.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
require 'support/backburner/inline'
|
||||
|
||||
ActiveJob::Base.queue_adapter = :backburner
|
7
activejob/test/adapters/delayed_job.rb
Normal file
7
activejob/test/adapters/delayed_job.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
ActiveJob::Base.queue_adapter = :delayed_job
|
||||
|
||||
$LOAD_PATH << File.dirname(__FILE__) + "/../support/delayed_job"
|
||||
|
||||
Delayed::Worker.delay_jobs = false
|
||||
Delayed::Worker.backend = :test
|
||||
|
1
activejob/test/adapters/inline.rb
Normal file
1
activejob/test/adapters/inline.rb
Normal file
|
@ -0,0 +1 @@
|
|||
ActiveJob::Base.queue_adapter = :inline
|
3
activejob/test/adapters/qu.rb
Normal file
3
activejob/test/adapters/qu.rb
Normal file
|
@ -0,0 +1,3 @@
|
|||
require 'qu-immediate'
|
||||
|
||||
ActiveJob::Base.queue_adapter = :qu
|
2
activejob/test/adapters/que.rb
Normal file
2
activejob/test/adapters/que.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
ActiveJob::Base.queue_adapter = :que
|
||||
Que.mode = :sync
|
2
activejob/test/adapters/queue_classic.rb
Normal file
2
activejob/test/adapters/queue_classic.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
require 'support/queue_classic/inline'
|
||||
ActiveJob::Base.queue_adapter = :queue_classic
|
2
activejob/test/adapters/resque.rb
Normal file
2
activejob/test/adapters/resque.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
ActiveJob::Base.queue_adapter = :resque
|
||||
Resque.inline = true
|
2
activejob/test/adapters/sidekiq.rb
Normal file
2
activejob/test/adapters/sidekiq.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
require 'sidekiq/testing/inline'
|
||||
ActiveJob::Base.queue_adapter = :sidekiq
|
2
activejob/test/adapters/sneakers.rb
Normal file
2
activejob/test/adapters/sneakers.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
require 'support/sneakers/inline'
|
||||
ActiveJob::Base.queue_adapter = :sneakers
|
2
activejob/test/adapters/sucker_punch.rb
Normal file
2
activejob/test/adapters/sucker_punch.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
require 'sucker_punch/testing/inline'
|
||||
ActiveJob::Base.queue_adapter = :sucker_punch
|
56
activejob/test/cases/adapter_test.rb
Normal file
56
activejob/test/cases/adapter_test.rb
Normal file
|
@ -0,0 +1,56 @@
|
|||
require 'helper'
|
||||
|
||||
class AdapterTest < ActiveSupport::TestCase
|
||||
setup { @old_adapter = ActiveJob::Base.queue_adapter }
|
||||
teardown { ActiveJob::Base.queue_adapter = @old_adapter }
|
||||
|
||||
test 'should load inline adapter' do
|
||||
ActiveJob::Base.queue_adapter = :inline
|
||||
assert_equal ActiveJob::QueueAdapters::InlineAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Delayed Job adapter' do
|
||||
ActiveJob::Base.queue_adapter = :delayed_job
|
||||
assert_equal ActiveJob::QueueAdapters::DelayedJobAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Qu adapter' do
|
||||
ActiveJob::Base.queue_adapter = :qu
|
||||
assert_equal ActiveJob::QueueAdapters::QuAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Que adapter' do
|
||||
ActiveJob::Base.queue_adapter = :que
|
||||
assert_equal ActiveJob::QueueAdapters::QueAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Queue Classic adapter' do
|
||||
ActiveJob::Base.queue_adapter = :queue_classic
|
||||
assert_equal ActiveJob::QueueAdapters::QueueClassicAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Resque adapter' do
|
||||
ActiveJob::Base.queue_adapter = :resque
|
||||
assert_equal ActiveJob::QueueAdapters::ResqueAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Sidekiq adapter' do
|
||||
ActiveJob::Base.queue_adapter = :sidekiq
|
||||
assert_equal ActiveJob::QueueAdapters::SidekiqAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Sucker Punch adapter' do
|
||||
ActiveJob::Base.queue_adapter = :sucker_punch
|
||||
assert_equal ActiveJob::QueueAdapters::SuckerPunchAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Sneakers adapter' do
|
||||
ActiveJob::Base.queue_adapter = :sneakers
|
||||
assert_equal ActiveJob::QueueAdapters::SneakersAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
|
||||
test 'should load Backburner adapter' do
|
||||
ActiveJob::Base.queue_adapter = :backburner
|
||||
assert_equal ActiveJob::QueueAdapters::BackburnerAdapter, ActiveJob::Base.queue_adapter
|
||||
end
|
||||
end
|
22
activejob/test/cases/callbacks_test.rb
Normal file
22
activejob/test/cases/callbacks_test.rb
Normal file
|
@ -0,0 +1,22 @@
|
|||
require 'helper'
|
||||
require 'jobs/callback_job'
|
||||
|
||||
require 'active_support/core_ext/object/inclusion'
|
||||
|
||||
class CallbacksTest < ActiveSupport::TestCase
|
||||
test 'perform callbacks' do
|
||||
performed_callback_job = CallbackJob.new.tap { |j| j.execute("A-JOB-ID") }
|
||||
assert "CallbackJob ran before_perform".in? performed_callback_job.history
|
||||
assert "CallbackJob ran after_perform".in? performed_callback_job.history
|
||||
assert "CallbackJob ran around_perform_start".in? performed_callback_job.history
|
||||
assert "CallbackJob ran around_perform_stop".in? performed_callback_job.history
|
||||
end
|
||||
|
||||
test 'enqueue callbacks' do
|
||||
enqueued_callback_job = CallbackJob.enqueue
|
||||
assert "CallbackJob ran before_enqueue".in? enqueued_callback_job.history
|
||||
assert "CallbackJob ran after_enqueue".in? enqueued_callback_job.history
|
||||
assert "CallbackJob ran around_enqueue_start".in? enqueued_callback_job.history
|
||||
assert "CallbackJob ran around_enqueue_stop".in? enqueued_callback_job.history
|
||||
end
|
||||
end
|
15
activejob/test/cases/job_serialization_test.rb
Normal file
15
activejob/test/cases/job_serialization_test.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
require 'helper'
|
||||
require 'jobs/gid_job'
|
||||
require 'models/person'
|
||||
|
||||
class JobSerializationTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
$BUFFER = []
|
||||
@person = Person.find(5)
|
||||
end
|
||||
|
||||
test 'serialize job with gid' do
|
||||
GidJob.enqueue @person
|
||||
assert_equal "Person with ID: 5", $BUFFER.pop
|
||||
end
|
||||
end
|
94
activejob/test/cases/logging_test.rb
Normal file
94
activejob/test/cases/logging_test.rb
Normal file
|
@ -0,0 +1,94 @@
|
|||
require 'helper'
|
||||
require "active_support/log_subscriber/test_helper"
|
||||
require 'jobs/logging_job'
|
||||
require 'jobs/nested_job'
|
||||
|
||||
class AdapterTest < ActiveSupport::TestCase
|
||||
include ActiveSupport::LogSubscriber::TestHelper
|
||||
include ActiveSupport::Logger::Severity
|
||||
|
||||
class TestLogger < ActiveSupport::Logger
|
||||
def initialize
|
||||
@file = StringIO.new
|
||||
super(@file)
|
||||
end
|
||||
|
||||
def messages
|
||||
@file.rewind
|
||||
@file.read
|
||||
end
|
||||
end
|
||||
|
||||
def setup
|
||||
super
|
||||
$BUFFER = []
|
||||
@old_logger = ActiveJob::Base.logger
|
||||
@logger = ActiveSupport::TaggedLogging.new(TestLogger.new)
|
||||
set_logger @logger
|
||||
ActiveJob::Logging::LogSubscriber.attach_to :active_job
|
||||
end
|
||||
|
||||
def teardown
|
||||
super
|
||||
ActiveJob::Logging::LogSubscriber.log_subscribers.pop
|
||||
ActiveJob::Base.logger = @old_logger
|
||||
end
|
||||
|
||||
def set_logger(logger)
|
||||
ActiveJob::Base.logger = logger
|
||||
end
|
||||
|
||||
|
||||
def test_uses_active_job_as_tag
|
||||
HelloJob.enqueue "Cristian"
|
||||
assert_match(/\[ActiveJob\]/, @logger.messages)
|
||||
end
|
||||
|
||||
def test_enqueue_job_logging
|
||||
HelloJob.enqueue "Cristian"
|
||||
assert_match(/Enqueued HelloJob \(Job ID: .*?\) to .*?:.*Cristian/, @logger.messages)
|
||||
end
|
||||
|
||||
def test_perform_job_logging
|
||||
LoggingJob.enqueue "Dummy"
|
||||
assert_match(/Performing LoggingJob from .*? with arguments:.*Dummy/, @logger.messages)
|
||||
assert_match(/Dummy, here is it: Dummy/, @logger.messages)
|
||||
assert_match(/Performed LoggingJob from .*? in .*ms/, @logger.messages)
|
||||
end
|
||||
|
||||
def test_perform_uses_job_name_job_logging
|
||||
LoggingJob.enqueue "Dummy"
|
||||
assert_match(/\[LoggingJob\]/, @logger.messages)
|
||||
end
|
||||
|
||||
def test_perform_uses_job_id_job_logging
|
||||
LoggingJob.enqueue "Dummy"
|
||||
assert_match(/\[LOGGING-JOB-ID\]/, @logger.messages)
|
||||
end
|
||||
|
||||
def test_perform_nested_jobs_logging
|
||||
NestedJob.enqueue
|
||||
assert_match(/\[LoggingJob\] \[.*?\]/, @logger.messages)
|
||||
assert_match(/\[ActiveJob\] Enqueued NestedJob \(Job ID: .*\) to/, @logger.messages)
|
||||
assert_match(/\[ActiveJob\] \[NestedJob\] \[NESTED-JOB-ID\] Performing NestedJob from/, @logger.messages)
|
||||
assert_match(/\[ActiveJob\] \[NestedJob\] \[NESTED-JOB-ID\] Enqueued LoggingJob \(Job ID: .*?\) to .* with arguments: "NestedJob"/, @logger.messages)
|
||||
assert_match(/\[ActiveJob\].*\[LoggingJob\] \[LOGGING-JOB-ID\] Performing LoggingJob from .* with arguments: "NestedJob"/, @logger.messages)
|
||||
assert_match(/\[ActiveJob\].*\[LoggingJob\] \[LOGGING-JOB-ID\] Dummy, here is it: NestedJob/, @logger.messages)
|
||||
assert_match(/\[ActiveJob\].*\[LoggingJob\] \[LOGGING-JOB-ID\] Performed LoggingJob from .* in/, @logger.messages)
|
||||
assert_match(/\[ActiveJob\] \[NestedJob\] \[NESTED-JOB-ID\] Performed NestedJob from .* in/, @logger.messages)
|
||||
end
|
||||
|
||||
def test_enqueue_at_job_logging
|
||||
HelloJob.enqueue_at 1, "Cristian"
|
||||
assert_match(/Enqueued HelloJob \(Job ID: .*\) to .*? at.*Cristian/, @logger.messages)
|
||||
rescue NotImplementedError
|
||||
skip
|
||||
end
|
||||
|
||||
def test_enqueue_in_job_logging
|
||||
HelloJob.enqueue_in 2, "Cristian"
|
||||
assert_match(/Enqueued HelloJob \(Job ID: .*\) to .*? at.*Cristian/, @logger.messages)
|
||||
rescue NotImplementedError
|
||||
skip
|
||||
end
|
||||
end
|
77
activejob/test/cases/parameters_test.rb
Normal file
77
activejob/test/cases/parameters_test.rb
Normal file
|
@ -0,0 +1,77 @@
|
|||
require 'helper'
|
||||
require 'active_job/arguments'
|
||||
require 'models/person'
|
||||
require 'active_support/core_ext/hash/indifferent_access'
|
||||
|
||||
class ParameterSerializationTest < ActiveSupport::TestCase
|
||||
test 'should make no change to regular values' do
|
||||
assert_equal [ 1, "something" ], ActiveJob::Arguments.serialize([ 1, "something" ])
|
||||
end
|
||||
|
||||
test 'should not allow complex objects' do
|
||||
assert_equal [ nil ], ActiveJob::Arguments.serialize([ nil ])
|
||||
assert_equal [ 1 ], ActiveJob::Arguments.serialize([ 1 ])
|
||||
assert_equal [ 1.0 ], ActiveJob::Arguments.serialize([ 1.0 ])
|
||||
assert_equal [ 'a' ], ActiveJob::Arguments.serialize([ 'a' ])
|
||||
assert_equal [ true ], ActiveJob::Arguments.serialize([ true ])
|
||||
assert_equal [ false ], ActiveJob::Arguments.serialize([ false ])
|
||||
assert_equal [ { "a" => 1, "b" => 2 } ], ActiveJob::Arguments.serialize([ { a: 1, "b" => 2 } ])
|
||||
assert_equal [ [ 1 ] ], ActiveJob::Arguments.serialize([ [ 1 ] ])
|
||||
assert_equal [ 1_000_000_000_000_000_000_000 ], ActiveJob::Arguments.serialize([ 1_000_000_000_000_000_000_000 ])
|
||||
|
||||
err = assert_raises RuntimeError do
|
||||
ActiveJob::Arguments.serialize([ 1, self ])
|
||||
end
|
||||
assert_equal "Unsupported argument type: #{self.class.name}", err.message
|
||||
end
|
||||
|
||||
test 'should dive deep into arrays or hashes' do
|
||||
assert_equal [ { "a" => Person.find(5).gid.to_s }.with_indifferent_access ], ActiveJob::Arguments.serialize([ { a: Person.find(5) } ])
|
||||
assert_equal [ [ Person.find(5).gid.to_s ] ], ActiveJob::Arguments.serialize([ [ Person.find(5) ] ])
|
||||
end
|
||||
|
||||
test 'should dive deep into arrays or hashes and raise exception on complex objects' do
|
||||
err = assert_raises RuntimeError do
|
||||
ActiveJob::Arguments.serialize([ 1, [self] ])
|
||||
end
|
||||
assert_equal "Unsupported argument type: #{self.class.name}", err.message
|
||||
end
|
||||
|
||||
test 'shoud dive deep into hashes and allow raise exception on not string/symbol keys' do
|
||||
err = assert_raises RuntimeError do
|
||||
ActiveJob::Arguments.serialize([ [ { 1 => 2 } ] ])
|
||||
end
|
||||
assert_equal "Unsupported hash key type: Fixnum", err.message
|
||||
end
|
||||
|
||||
test 'should serialize records with global id' do
|
||||
assert_equal [ Person.find(5).gid.to_s ], ActiveJob::Arguments.serialize([ Person.find(5) ])
|
||||
end
|
||||
|
||||
test 'should serialize values and records together' do
|
||||
assert_equal [ 3, Person.find(5).gid.to_s ], ActiveJob::Arguments.serialize([ 3, Person.find(5) ])
|
||||
end
|
||||
end
|
||||
|
||||
class ParameterDeserializationTest < ActiveSupport::TestCase
|
||||
test 'should make no change to regular values' do
|
||||
assert_equal [ 1, "something" ], ActiveJob::Arguments.deserialize([ 1, "something" ])
|
||||
end
|
||||
|
||||
test 'should deserialize records with global id' do
|
||||
assert_equal [ Person.find(5) ], ActiveJob::Arguments.deserialize([ Person.find(5).gid ])
|
||||
end
|
||||
|
||||
test 'should serialize values and records together' do
|
||||
assert_equal [ 3, Person.find(5) ], ActiveJob::Arguments.deserialize([ 3, Person.find(5).gid ])
|
||||
end
|
||||
|
||||
test 'should dive deep when deserialising arrays' do
|
||||
assert_equal [ [ 3, Person.find(5) ] ], ActiveJob::Arguments.deserialize([ [ 3, Person.find(5).gid ] ])
|
||||
end
|
||||
|
||||
test 'should dive deep when deserialising hashes' do
|
||||
assert_equal [ { "5" => Person.find(5) } ], ActiveJob::Arguments.deserialize([ { "5" => Person.find(5).gid } ])
|
||||
end
|
||||
|
||||
end
|
21
activejob/test/cases/queue_naming_test.rb
Normal file
21
activejob/test/cases/queue_naming_test.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
require 'helper'
|
||||
require 'jobs/hello_job'
|
||||
|
||||
class QueueNamingTest < ActiveSupport::TestCase
|
||||
test 'name derived from base' do
|
||||
assert_equal "active_jobs", HelloJob.queue_name
|
||||
end
|
||||
|
||||
test 'name appended in job' do
|
||||
begin
|
||||
HelloJob.queue_as :greetings
|
||||
LoggingJob.queue_as :bookkeeping
|
||||
|
||||
assert_equal "active_jobs", NestedJob.queue_name
|
||||
assert_equal "active_jobs_greetings", HelloJob.queue_name
|
||||
assert_equal "active_jobs_bookkeeping", LoggingJob.queue_name
|
||||
ensure
|
||||
HelloJob.queue_name = LoggingJob.queue_name = ActiveJob::Base.queue_base_name
|
||||
end
|
||||
end
|
||||
end
|
44
activejob/test/cases/queuing_test.rb
Normal file
44
activejob/test/cases/queuing_test.rb
Normal file
|
@ -0,0 +1,44 @@
|
|||
require 'helper'
|
||||
require 'jobs/hello_job'
|
||||
require 'active_support/core_ext/numeric/time'
|
||||
|
||||
|
||||
class QueuingTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
$BUFFER = []
|
||||
end
|
||||
|
||||
test 'run queued job' do
|
||||
HelloJob.enqueue
|
||||
assert_equal "David says hello", $BUFFER.pop
|
||||
end
|
||||
|
||||
test 'run queued job with arguments' do
|
||||
HelloJob.enqueue "Jamie"
|
||||
assert_equal "Jamie says hello", $BUFFER.pop
|
||||
end
|
||||
|
||||
test 'run queued job later' do
|
||||
begin
|
||||
result = HelloJob.enqueue_at 1.second.ago, "Jamie"
|
||||
assert result
|
||||
rescue NotImplementedError
|
||||
skip
|
||||
end
|
||||
end
|
||||
|
||||
test 'job returned by enqueue has the arguments available' do
|
||||
job = HelloJob.enqueue "Jamie"
|
||||
assert_equal [ "Jamie" ], job.arguments
|
||||
end
|
||||
|
||||
|
||||
test 'job returned by enqueue_at has the timestamp available' do
|
||||
begin
|
||||
job = HelloJob.enqueue_at Time.utc(2014, 1, 1)
|
||||
assert_equal Time.utc(2014, 1, 1), job.enqueued_at
|
||||
rescue NotImplementedError
|
||||
skip
|
||||
end
|
||||
end
|
||||
end
|
23
activejob/test/cases/rescue_test.rb
Normal file
23
activejob/test/cases/rescue_test.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
require 'helper'
|
||||
require 'jobs/rescue_job'
|
||||
|
||||
require 'active_support/core_ext/object/inclusion'
|
||||
|
||||
class RescueTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
$BUFFER = []
|
||||
end
|
||||
|
||||
test 'rescue perform exception with retry' do
|
||||
job = RescueJob.new
|
||||
job.execute(SecureRandom.uuid, "david")
|
||||
assert_equal [ "rescued from ArgumentError", "performed beautifully" ], $BUFFER
|
||||
end
|
||||
|
||||
test 'let through unhandled perform exception' do
|
||||
job = RescueJob.new
|
||||
assert_raises(RescueJob::OtherError) do
|
||||
job.execute(SecureRandom.uuid, "other")
|
||||
end
|
||||
end
|
||||
end
|
3
activejob/test/dummy/Rakefile
Normal file
3
activejob/test/dummy/Rakefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
require 'sneakers/tasks'
|
||||
require File.expand_path('../config/application', __FILE__)
|
||||
Rails.application.load_tasks
|
0
activejob/test/dummy/app/assets/images/.keep
Normal file
0
activejob/test/dummy/app/assets/images/.keep
Normal file
|
@ -0,0 +1,3 @@
|
|||
class ApplicationController < ActionController::Base
|
||||
protect_from_forgery with: :exception
|
||||
end
|
0
activejob/test/dummy/app/controllers/concerns/.keep
Normal file
0
activejob/test/dummy/app/controllers/concerns/.keep
Normal file
2
activejob/test/dummy/app/helpers/application_helper.rb
Normal file
2
activejob/test/dummy/app/helpers/application_helper.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
module ApplicationHelper
|
||||
end
|
9
activejob/test/dummy/app/jobs/test_job.rb
Normal file
9
activejob/test/dummy/app/jobs/test_job.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
class TestJob < ActiveJob::Base
|
||||
queue_as :default
|
||||
|
||||
def perform(x)
|
||||
File.open(Rails.root.join("tmp/#{x}"), "w+") do |f|
|
||||
f.write x
|
||||
end
|
||||
end
|
||||
end
|
0
activejob/test/dummy/app/mailers/.keep
Normal file
0
activejob/test/dummy/app/mailers/.keep
Normal file
0
activejob/test/dummy/app/models/.keep
Normal file
0
activejob/test/dummy/app/models/.keep
Normal file
0
activejob/test/dummy/app/models/concerns/.keep
Normal file
0
activejob/test/dummy/app/models/concerns/.keep
Normal file
4
activejob/test/dummy/config.ru
Normal file
4
activejob/test/dummy/config.ru
Normal file
|
@ -0,0 +1,4 @@
|
|||
# This file is used by Rack-based servers to start the application.
|
||||
|
||||
require ::File.expand_path('../config/environment', __FILE__)
|
||||
run Rails.application
|
9
activejob/test/dummy/config/application.rb
Normal file
9
activejob/test/dummy/config/application.rb
Normal file
|
@ -0,0 +1,9 @@
|
|||
require File.expand_path('../boot', __FILE__)
|
||||
require 'rails/all'
|
||||
Bundler.require(*Rails.groups)
|
||||
|
||||
module Dummy
|
||||
class Application < Rails::Application
|
||||
end
|
||||
end
|
||||
|
5
activejob/test/dummy/config/boot.rb
Normal file
5
activejob/test/dummy/config/boot.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
# Set up gems listed in the Gemfile.
|
||||
ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../../../Gemfile', __FILE__)
|
||||
|
||||
require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
|
||||
$LOAD_PATH.unshift File.expand_path('../../../../lib', __FILE__)
|
3
activejob/test/dummy/config/database.yml
Normal file
3
activejob/test/dummy/config/database.yml
Normal file
|
@ -0,0 +1,3 @@
|
|||
test:
|
||||
adapter: sqlite3
|
||||
database: "db/test.sqlite3"
|
2
activejob/test/dummy/config/environment.rb
Normal file
2
activejob/test/dummy/config/environment.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
require File.expand_path('../application', __FILE__)
|
||||
Rails.application.initialize!
|
13
activejob/test/dummy/config/environments/test.rb
Normal file
13
activejob/test/dummy/config/environments/test.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
Rails.application.configure do
|
||||
config.cache_classes = true
|
||||
config.eager_load = false
|
||||
config.serve_static_assets = true
|
||||
config.static_cache_control = 'public, max-age=3600'
|
||||
config.consider_all_requests_local = true
|
||||
config.action_controller.perform_caching = false
|
||||
config.action_dispatch.show_exceptions = false
|
||||
config.action_controller.allow_forgery_protection = false
|
||||
config.action_mailer.delivery_method = :test
|
||||
config.active_support.deprecation = :stderr
|
||||
config.log_level = :debug
|
||||
end
|
65
activejob/test/dummy/config/initializers/activejob.rb
Normal file
65
activejob/test/dummy/config/initializers/activejob.rb
Normal file
|
@ -0,0 +1,65 @@
|
|||
case ENV['AJADAPTER']
|
||||
when "delayed_job"
|
||||
ActiveJob::Base.queue_adapter = :delayed_job
|
||||
when "sidekiq"
|
||||
ActiveJob::Base.queue_adapter = :sidekiq
|
||||
when "resque"
|
||||
ActiveJob::Base.queue_adapter = :resque
|
||||
Resque.redis = Redis::Namespace.new 'active_jobs_int_test', redis: Redis.connect(url: "tcp://127.0.0.1:6379/12", :thread_safe => true)
|
||||
Resque.logger = Rails.logger
|
||||
when 'qu'
|
||||
ActiveJob::Base.queue_adapter = :qu
|
||||
ENV['REDISTOGO_URL'] = "tcp://127.0.0.1:6379/12"
|
||||
backend = Qu::Backend::Redis.new
|
||||
backend.namespace = "active_jobs_int_test"
|
||||
Qu.backend = backend
|
||||
Qu.logger = Rails.logger
|
||||
Qu.interval = 0.5
|
||||
when 'que'
|
||||
ActiveJob::Base.queue_adapter = :que
|
||||
QUE_URL = ENV['QUE_DATABASE_URL'] || 'postgres://localhost/active_jobs_que_int_test'
|
||||
uri = URI.parse(QUE_URL)
|
||||
user = uri.user||ENV['USER']
|
||||
pass = uri.password
|
||||
db = uri.path[1..-1]
|
||||
%x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -c 'drop database "#{db}"' -U #{user} -t template1}
|
||||
%x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -c 'create database "#{db}"' -U #{user} -t template1}
|
||||
Que.connection = Sequel.connect(QUE_URL)
|
||||
Que.migrate!
|
||||
Que.mode = :off
|
||||
Que.worker_count = 1
|
||||
when 'queue_classic'
|
||||
ENV['QC_DATABASE_URL'] ||= 'postgres://localhost/active_jobs_qc_int_test'
|
||||
ENV['QC_LISTEN_TIME'] = "0.5"
|
||||
ActiveJob::Base.queue_adapter = :queue_classic
|
||||
uri = URI.parse(ENV['QC_DATABASE_URL'])
|
||||
user = uri.user||ENV['USER']
|
||||
pass = uri.password
|
||||
db = uri.path[1..-1]
|
||||
%x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -c 'drop database "#{db}"' -U #{user} -t template1}
|
||||
%x{#{"PGPASSWORD=\"#{pass}\"" if pass} psql -c 'create database "#{db}"' -U #{user} -t template1}
|
||||
QC::Setup.create
|
||||
when 'sidekiq'
|
||||
ActiveJob::Base.queue_adapter = :sidekiq
|
||||
when 'sneakers'
|
||||
ActiveJob::Base.queue_adapter = :sneakers
|
||||
Sneakers.configure :heartbeat => 2,
|
||||
:amqp => 'amqp://guest:guest@localhost:5672',
|
||||
:vhost => '/',
|
||||
:exchange => 'active_jobs_sneakers_int_test',
|
||||
:exchange_type => :direct,
|
||||
:daemonize => true,
|
||||
:threads => 1,
|
||||
:workers => 1,
|
||||
:pid_path => Rails.root.join("tmp/sneakers.pid").to_s,
|
||||
:log => Rails.root.join("log/sneakers.log").to_s
|
||||
when 'sucker_punch'
|
||||
ActiveJob::Base.queue_adapter = :sucker_punch
|
||||
when 'backburner'
|
||||
ActiveJob::Base.queue_adapter = :backburner
|
||||
Backburner.configure do |config|
|
||||
config.logger = Rails.logger
|
||||
end
|
||||
else
|
||||
ActiveJob::Base.queue_adapter = nil
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
Rails.application.config.session_store :cookie_store, key: '_dummy_session'
|
2
activejob/test/dummy/config/routes.rb
Normal file
2
activejob/test/dummy/config/routes.rb
Normal file
|
@ -0,0 +1,2 @@
|
|||
Rails.application.routes.draw do
|
||||
end
|
2
activejob/test/dummy/config/secrets.yml
Normal file
2
activejob/test/dummy/config/secrets.yml
Normal file
|
@ -0,0 +1,2 @@
|
|||
test:
|
||||
secret_key_base: b83ee5aeada663bc4270a1817d0ca43b2784017cc77dc8afcd60967cc968d4ce30caff9eb682766129e18a4048c4d5ebf14eabf463fc37ad67c18934f4345545
|
|
@ -0,0 +1,22 @@
|
|||
class CreateDelayedJobs < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :delayed_jobs, :force => true do |table|
|
||||
table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue
|
||||
table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually.
|
||||
table.text :handler, :null => false # YAML-encoded string of the object that will do work
|
||||
table.text :last_error # reason for last failure (See Note below)
|
||||
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
|
||||
table.datetime :locked_at # Set when a client is working on this object
|
||||
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
||||
table.string :locked_by # Who is working on this object (if locked)
|
||||
table.string :queue # The name of the queue this job is in
|
||||
table.timestamps
|
||||
end
|
||||
|
||||
add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority'
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :delayed_jobs
|
||||
end
|
||||
end
|
32
activejob/test/dummy/db/schema.rb
Normal file
32
activejob/test/dummy/db/schema.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
# encoding: UTF-8
|
||||
# This file is auto-generated from the current state of the database. Instead
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20140804200445) do
|
||||
|
||||
create_table "delayed_jobs", force: true do |t|
|
||||
t.integer "priority", default: 0, null: false
|
||||
t.integer "attempts", default: 0, null: false
|
||||
t.text "handler", null: false
|
||||
t.text "last_error"
|
||||
t.datetime "run_at"
|
||||
t.datetime "locked_at"
|
||||
t.datetime "failed_at"
|
||||
t.string "locked_by"
|
||||
t.string "queue"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority"
|
||||
|
||||
end
|
BIN
activejob/test/dummy/db/test.sqlite3
Normal file
BIN
activejob/test/dummy/db/test.sqlite3
Normal file
Binary file not shown.
0
activejob/test/dummy/lib/assets/.keep
Normal file
0
activejob/test/dummy/lib/assets/.keep
Normal file
0
activejob/test/dummy/log/.keep
Normal file
0
activejob/test/dummy/log/.keep
Normal file
0
activejob/test/dummy/tmp/.keep
Normal file
0
activejob/test/dummy/tmp/.keep
Normal file
19
activejob/test/helper.rb
Normal file
19
activejob/test/helper.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
require 'bundler'
|
||||
Bundler.setup
|
||||
|
||||
$LOAD_PATH << File.dirname(__FILE__) + "/../lib"
|
||||
|
||||
require 'active_job'
|
||||
|
||||
adapter = ENV['AJADAPTER'] || 'inline'
|
||||
puts "Testing#{" integration" if ENV['AJ_INTEGRATION_TESTS']} using #{adapter}"
|
||||
|
||||
if ENV['AJ_INTEGRATION_TESTS']
|
||||
require 'support/integration/helper'
|
||||
else
|
||||
require "adapters/#{adapter}"
|
||||
end
|
||||
|
||||
require 'active_support/testing/autorun'
|
||||
|
||||
ActiveJob::Base.logger.level = Logger::DEBUG
|
18
activejob/test/integration/queuing_test.rb
Normal file
18
activejob/test/integration/queuing_test.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
require 'helper'
|
||||
require 'jobs/logging_job'
|
||||
require 'active_support/core_ext/numeric/time'
|
||||
|
||||
|
||||
class QueuingTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
|
||||
end
|
||||
|
||||
test 'run queued job' do
|
||||
id = "AJ-#{SecureRandom.uuid}"
|
||||
TestJob.enqueue id
|
||||
sleep 2
|
||||
assert Dummy::Application.root.join("tmp/#{id}").exist?
|
||||
end
|
||||
|
||||
end
|
32
activejob/test/jobs/callback_job.rb
Normal file
32
activejob/test/jobs/callback_job.rb
Normal file
|
@ -0,0 +1,32 @@
|
|||
class CallbackJob < ActiveJob::Base
|
||||
before_perform ->(job) { job.history << "CallbackJob ran before_perform" }
|
||||
after_perform ->(job) { job.history << "CallbackJob ran after_perform" }
|
||||
|
||||
before_enqueue ->(job) { job.history << "CallbackJob ran before_enqueue" }
|
||||
after_enqueue ->(job) { job.history << "CallbackJob ran after_enqueue" }
|
||||
|
||||
around_perform :around_perform
|
||||
around_enqueue :around_enqueue
|
||||
|
||||
|
||||
def perform(person = "david")
|
||||
# NOTHING!
|
||||
end
|
||||
|
||||
def history
|
||||
@history ||= []
|
||||
end
|
||||
|
||||
# FIXME: Not sure why these can't be declared inline like before/after
|
||||
def around_perform
|
||||
history << "CallbackJob ran around_perform_start"
|
||||
yield
|
||||
history << "CallbackJob ran around_perform_stop"
|
||||
end
|
||||
|
||||
def around_enqueue
|
||||
history << "CallbackJob ran around_enqueue_start"
|
||||
yield
|
||||
history << "CallbackJob ran around_enqueue_stop"
|
||||
end
|
||||
end
|
6
activejob/test/jobs/gid_job.rb
Normal file
6
activejob/test/jobs/gid_job.rb
Normal file
|
@ -0,0 +1,6 @@
|
|||
class GidJob < ActiveJob::Base
|
||||
def perform(person)
|
||||
$BUFFER << "Person with ID: #{person.id}"
|
||||
end
|
||||
end
|
||||
|
5
activejob/test/jobs/hello_job.rb
Normal file
5
activejob/test/jobs/hello_job.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class HelloJob < ActiveJob::Base
|
||||
def perform(greeter = "David")
|
||||
$BUFFER << "#{greeter} says hello"
|
||||
end
|
||||
end
|
10
activejob/test/jobs/logging_job.rb
Normal file
10
activejob/test/jobs/logging_job.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class LoggingJob < ActiveJob::Base
|
||||
def perform(dummy)
|
||||
logger.info "Dummy, here is it: #{dummy}"
|
||||
end
|
||||
|
||||
def job_id
|
||||
"LOGGING-JOB-ID"
|
||||
end
|
||||
end
|
||||
|
10
activejob/test/jobs/nested_job.rb
Normal file
10
activejob/test/jobs/nested_job.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
class NestedJob < ActiveJob::Base
|
||||
def perform
|
||||
LoggingJob.enqueue "NestedJob"
|
||||
end
|
||||
|
||||
def job_id
|
||||
"NESTED-JOB-ID"
|
||||
end
|
||||
end
|
||||
|
20
activejob/test/jobs/rescue_job.rb
Normal file
20
activejob/test/jobs/rescue_job.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
class RescueJob < ActiveJob::Base
|
||||
class OtherError < StandardError; end
|
||||
|
||||
rescue_from(ArgumentError) do
|
||||
$BUFFER << "rescued from ArgumentError"
|
||||
arguments[0] = "DIFFERENT!"
|
||||
retry_now
|
||||
end
|
||||
|
||||
def perform(person = "david")
|
||||
case person
|
||||
when "david"
|
||||
raise ArgumentError, "Hair too good"
|
||||
when "other"
|
||||
raise OtherError
|
||||
else
|
||||
$BUFFER << "performed beautifully"
|
||||
end
|
||||
end
|
||||
end
|
19
activejob/test/models/person.rb
Normal file
19
activejob/test/models/person.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
require 'active_model/global_identification'
|
||||
|
||||
class Person
|
||||
include ActiveModel::GlobalIdentification
|
||||
|
||||
attr_reader :id
|
||||
|
||||
def self.find(id)
|
||||
new(id)
|
||||
end
|
||||
|
||||
def initialize(id)
|
||||
@id = id
|
||||
end
|
||||
|
||||
def ==(other_person)
|
||||
other_person.is_a?(Person) && id.to_s == other_person.id.to_s
|
||||
end
|
||||
end
|
8
activejob/test/support/backburner/inline.rb
Normal file
8
activejob/test/support/backburner/inline.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
require 'backburner'
|
||||
|
||||
Backburner::Worker.class_eval do
|
||||
class << self; alias_method :original_enqueue, :enqueue; end
|
||||
def self.enqueue(job_class, args=[], opts={})
|
||||
job_class.perform(*args)
|
||||
end
|
||||
end
|
113
activejob/test/support/delayed_job/delayed/backend/test.rb
Normal file
113
activejob/test/support/delayed_job/delayed/backend/test.rb
Normal file
|
@ -0,0 +1,113 @@
|
|||
#copied from https://github.com/collectiveidea/delayed_job/blob/master/spec/delayed/backend/test.rb
|
||||
require 'ostruct'
|
||||
|
||||
# An in-memory backend suitable only for testing. Tries to behave as if it were an ORM.
|
||||
module Delayed
|
||||
module Backend
|
||||
module Test
|
||||
class Job
|
||||
attr_accessor :id
|
||||
attr_accessor :priority
|
||||
attr_accessor :attempts
|
||||
attr_accessor :handler
|
||||
attr_accessor :last_error
|
||||
attr_accessor :run_at
|
||||
attr_accessor :locked_at
|
||||
attr_accessor :locked_by
|
||||
attr_accessor :failed_at
|
||||
attr_accessor :queue
|
||||
|
||||
include Delayed::Backend::Base
|
||||
|
||||
cattr_accessor :id
|
||||
self.id = 0
|
||||
|
||||
def initialize(hash = {})
|
||||
self.attempts = 0
|
||||
self.priority = 0
|
||||
self.id = (self.class.id += 1)
|
||||
hash.each{|k,v| send(:"#{k}=", v)}
|
||||
end
|
||||
|
||||
@jobs = []
|
||||
def self.all
|
||||
@jobs
|
||||
end
|
||||
|
||||
def self.count
|
||||
all.size
|
||||
end
|
||||
|
||||
def self.delete_all
|
||||
all.clear
|
||||
end
|
||||
|
||||
def self.create(attrs = {})
|
||||
new(attrs).tap do |o|
|
||||
o.save
|
||||
end
|
||||
end
|
||||
|
||||
def self.create!(*args); create(*args); end
|
||||
|
||||
def self.clear_locks!(worker_name)
|
||||
all.select{|j| j.locked_by == worker_name}.each {|j| j.locked_by = nil; j.locked_at = nil}
|
||||
end
|
||||
|
||||
# Find a few candidate jobs to run (in case some immediately get locked by others).
|
||||
def self.find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
|
||||
jobs = all.select do |j|
|
||||
j.run_at <= db_time_now &&
|
||||
(j.locked_at.nil? || j.locked_at < db_time_now - max_run_time || j.locked_by == worker_name) &&
|
||||
!j.failed?
|
||||
end
|
||||
|
||||
jobs = jobs.select{|j| Worker.queues.include?(j.queue)} if Worker.queues.any?
|
||||
jobs = jobs.select{|j| j.priority >= Worker.min_priority} if Worker.min_priority
|
||||
jobs = jobs.select{|j| j.priority <= Worker.max_priority} if Worker.max_priority
|
||||
jobs.sort_by{|j| [j.priority, j.run_at]}[0..limit-1]
|
||||
end
|
||||
|
||||
# Lock this job for this worker.
|
||||
# Returns true if we have the lock, false otherwise.
|
||||
def lock_exclusively!(max_run_time, worker)
|
||||
now = self.class.db_time_now
|
||||
if locked_by != worker
|
||||
# We don't own this job so we will update the locked_by name and the locked_at
|
||||
self.locked_at = now
|
||||
self.locked_by = worker
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
def self.db_time_now
|
||||
Time.current
|
||||
end
|
||||
|
||||
def update_attributes(attrs = {})
|
||||
attrs.each{|k,v| send(:"#{k}=", v)}
|
||||
save
|
||||
end
|
||||
|
||||
def destroy
|
||||
self.class.all.delete(self)
|
||||
end
|
||||
|
||||
def save
|
||||
self.run_at ||= Time.current
|
||||
|
||||
self.class.all << self unless self.class.all.include?(self)
|
||||
true
|
||||
end
|
||||
|
||||
def save!; save; end
|
||||
|
||||
def reload
|
||||
reset
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
15
activejob/test/support/integration/adapters/backburner.rb
Normal file
15
activejob/test/support/integration/adapters/backburner.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
module BackburnerJobsManager
|
||||
def clear_jobs
|
||||
Backburner::Worker.connection.tubes.all.map &:clear
|
||||
end
|
||||
|
||||
def start_workers
|
||||
@thread = Thread.new { Backburner.work "active-jobs-default" }
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
@thread.kill
|
||||
end
|
||||
|
||||
end
|
||||
|
14
activejob/test/support/integration/adapters/delayed_job.rb
Normal file
14
activejob/test/support/integration/adapters/delayed_job.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
module DelayedJobJobsManager
|
||||
def clear_jobs
|
||||
Delayed::Job.delete_all
|
||||
end
|
||||
|
||||
def start_workers
|
||||
@worker = Delayed::Worker.new(quiet: false, sleep_delay: 0.5)
|
||||
@thread = Thread.new { @worker.start }
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
@worker.stop
|
||||
end
|
||||
end
|
14
activejob/test/support/integration/adapters/qu.rb
Normal file
14
activejob/test/support/integration/adapters/qu.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
module QuJobsManager
|
||||
def clear_jobs
|
||||
Qu.clear "active_jobs_default"
|
||||
end
|
||||
|
||||
def start_workers
|
||||
@thread = Thread.new { Qu::Worker.new("active_jobs_default").start }
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
@thread.kill
|
||||
end
|
||||
end
|
||||
|
19
activejob/test/support/integration/adapters/que.rb
Normal file
19
activejob/test/support/integration/adapters/que.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
module QueJobsManager
|
||||
def clear_jobs
|
||||
Que.clear!
|
||||
end
|
||||
|
||||
def start_workers
|
||||
@thread = Thread.new do
|
||||
loop do
|
||||
Que::Job.work("active_jobs_default")
|
||||
sleep 0.5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
@thread.kill
|
||||
end
|
||||
end
|
||||
|
21
activejob/test/support/integration/adapters/queue_classic.rb
Normal file
21
activejob/test/support/integration/adapters/queue_classic.rb
Normal file
|
@ -0,0 +1,21 @@
|
|||
module QC; WAIT_TIME = 0.5; end
|
||||
|
||||
module QueueClassicJobsManager
|
||||
def clear_jobs
|
||||
# disabling this as it locks
|
||||
# QC::Queue.new("active_jobs_default").delete_all
|
||||
end
|
||||
|
||||
def start_workers
|
||||
@pid = fork do
|
||||
QC::Conn.connection = QC::Conn.connect
|
||||
worker = QC::Worker.new(q_name: 'active_jobs_default')
|
||||
worker.start
|
||||
end
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
Process.kill 'HUP', @pid
|
||||
end
|
||||
end
|
||||
|
18
activejob/test/support/integration/adapters/resque.rb
Normal file
18
activejob/test/support/integration/adapters/resque.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module ResqueJobsManager
|
||||
def clear_jobs
|
||||
Resque.queues.each { |queue_name| Resque.redis.del "queue:#{queue_name}" }
|
||||
Resque.redis.keys("delayed:*").each { |key| Resque.redis.del "#{key}" }
|
||||
Resque.redis.del "delayed_queue_schedule"
|
||||
end
|
||||
|
||||
def start_workers
|
||||
@thread = Thread.new do
|
||||
Resque::Worker.new("*").work(0.5)
|
||||
end
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
@thread.kill
|
||||
end
|
||||
end
|
||||
|
19
activejob/test/support/integration/adapters/sidekiq.rb
Normal file
19
activejob/test/support/integration/adapters/sidekiq.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
require 'sidekiq/launcher'
|
||||
require 'sidekiq/api'
|
||||
|
||||
module SidekiqJobsManager
|
||||
def clear_jobs
|
||||
Sidekiq::Queue.new("active_jobs_default").clear
|
||||
end
|
||||
|
||||
def start_workers
|
||||
options = {:queues=>["active_jobs_default"], :concurrency=>1, :environment=>"test", :timeout=>8, :daemon=>true, :strict=>true}
|
||||
@launcher = Sidekiq::Launcher.new(options)
|
||||
@launcher.run
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
@launcher.stop
|
||||
end
|
||||
end
|
||||
|
18
activejob/test/support/integration/adapters/sneakers.rb
Normal file
18
activejob/test/support/integration/adapters/sneakers.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
require 'sneakers/runner'
|
||||
|
||||
module SneakersJobsManager
|
||||
def clear_jobs
|
||||
end
|
||||
|
||||
def start_workers
|
||||
cmd = %{cd #{Rails.root.to_s} && (RAILS_ENV=test AJADAPTER=sneakers WORKERS=ActiveJob::QueueAdapters::SneakersAdapter::JobWrapper bundle exec rake --trace sneakers:run)}
|
||||
`#{cmd}`
|
||||
while !Rails.root.join("tmp/sneakers.pid").exist? do
|
||||
sleep 0.5
|
||||
end
|
||||
end
|
||||
|
||||
def stop_workers
|
||||
Process.kill 'TERM', File.open(Rails.root.join("tmp/sneakers.pid").to_s).read.to_i
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
module SuckerPunchJobsManager
|
||||
def clear_jobs
|
||||
end
|
||||
end
|
||||
|
12
activejob/test/support/integration/helper.rb
Normal file
12
activejob/test/support/integration/helper.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
ENV["RAILS_ENV"] = "test"
|
||||
require File.expand_path("../../../dummy/config/environment.rb", __FILE__)
|
||||
require "rails/test_help"
|
||||
Rails.backtrace_cleaner.remove_silencers!
|
||||
|
||||
require_relative 'test_case_helpers'
|
||||
ActiveSupport::TestCase.send(:include, TestCaseHelpers)
|
||||
|
||||
JobsManager.current_manager.setup
|
||||
JobsManager.current_manager.start_workers
|
||||
Minitest.after_run { JobsManager.current_manager.stop_workers }
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue