activejob_backport 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -0
- data/MIT-LICENSE +21 -0
- data/README.md +17 -0
- data/lib/active_job.rb +39 -0
- data/lib/active_job/arguments.rb +81 -0
- data/lib/active_job/base.rb +21 -0
- data/lib/active_job/callbacks.rb +144 -0
- data/lib/active_job/configured_job.rb +16 -0
- data/lib/active_job/core.rb +89 -0
- data/lib/active_job/enqueuing.rb +75 -0
- data/lib/active_job/execution.rb +41 -0
- data/lib/active_job/gem_version.rb +15 -0
- data/lib/active_job/logging.rb +121 -0
- data/lib/active_job/queue_adapter.rb +29 -0
- data/lib/active_job/queue_adapters.rb +17 -0
- data/lib/active_job/queue_adapters/backburner_adapter.rb +26 -0
- data/lib/active_job/queue_adapters/delayed_job_adapter.rb +23 -0
- data/lib/active_job/queue_adapters/inline_adapter.rb +15 -0
- data/lib/active_job/queue_adapters/qu_adapter.rb +29 -0
- data/lib/active_job/queue_adapters/que_adapter.rb +23 -0
- data/lib/active_job/queue_adapters/queue_classic_adapter.rb +40 -0
- data/lib/active_job/queue_adapters/resque_adapter.rb +41 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +35 -0
- data/lib/active_job/queue_adapters/sneakers_adapter.rb +34 -0
- data/lib/active_job/queue_adapters/sucker_punch_adapter.rb +25 -0
- data/lib/active_job/queue_adapters/test_adapter.rb +37 -0
- data/lib/active_job/queue_name.rb +39 -0
- data/lib/active_job/railtie.rb +23 -0
- data/lib/active_job/test_case.rb +7 -0
- data/lib/active_job/test_helper.rb +196 -0
- data/lib/active_job/version.rb +8 -0
- data/lib/activejob_backport.rb +1 -0
- data/lib/global_id.rb +6 -0
- data/lib/global_id/global_id.rb +93 -0
- data/lib/global_id/identification.rb +13 -0
- data/lib/global_id/locator.rb +83 -0
- data/lib/rails/generators/job/job_generator.rb +24 -0
- data/lib/rails/generators/job/templates/job.rb +9 -0
- metadata +124 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2d443ef108536b2070d997a09d65c038ce0d67f1
|
4
|
+
data.tar.gz: 222e88e76594124766adefcad4b53195d33b8a2e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 24e46886f1267b394bb8278352c005cf2eb2ed9930b1f674abe8d3f0dd0f26a4317e0bd94052b9ce2eb2bfcf32325611f0a85abf9745516a37a773fee5c05882
|
7
|
+
data.tar.gz: 2f827a68356e4e15d563658b0b3522ff7c637a377bfc1978da2216e06eb921ff0b0e21a5c62e9ed6cc3d6e9d972be1564390d67e957d4240c7b3f405a89e9286
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* Started project.
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2014 David Heinemeier Hansson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# Active Job
|
2
|
+
|
3
|
+
Active Job backported to Rails 4.0 and 4.1
|
4
|
+
|
5
|
+
```ruby
|
6
|
+
gem 'activejob_backport'
|
7
|
+
```
|
8
|
+
|
9
|
+
And create `config/initializers/active_job.rb` with:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
ActiveJob::Base.queue_adapter = :inline # default queue adapter
|
13
|
+
# Adapters currently supported: :backburner, :delayed_job, :qu, :que, :queue_classic,
|
14
|
+
# :resque, :sidekiq, :sneakers, :sucker_punch
|
15
|
+
```
|
16
|
+
|
17
|
+
See [how to use Active Job](http://edgeguides.rubyonrails.org/active_job_basics.html) and the [official repo](https://github.com/rails/rails/tree/master/activejob)
|
data/lib/active_job.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2014 David Heinemeier Hansson
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require 'active_support'
|
25
|
+
require 'active_support/rails'
|
26
|
+
require 'active_job/version'
|
27
|
+
require 'global_id' if !defined?(GlobalId)
|
28
|
+
require 'active_job/railtie' if defined?(Rails)
|
29
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
30
|
+
|
31
|
+
module ActiveJob
|
32
|
+
extend ActiveSupport::Autoload
|
33
|
+
|
34
|
+
autoload :Base
|
35
|
+
autoload :QueueAdapters
|
36
|
+
autoload :ConfiguredJob
|
37
|
+
autoload :TestCase
|
38
|
+
autoload :TestHelper
|
39
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
# Raised when an exception is raised during job arguments deserialization.
|
3
|
+
#
|
4
|
+
# Wraps the original exception raised as +original_exception+.
|
5
|
+
class DeserializationError < StandardError
|
6
|
+
attr_reader :original_exception
|
7
|
+
|
8
|
+
def initialize(e) #:nodoc:
|
9
|
+
super("Error while trying to deserialize arguments: #{e.message}")
|
10
|
+
@original_exception = e
|
11
|
+
set_backtrace e.backtrace
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Raised when an unsupported argument type is being set as job argument. We
|
16
|
+
# currently support NilClass, Fixnum, Float, String, TrueClass, FalseClass,
|
17
|
+
# Bignum and object that can be represented as GlobalIDs (ex: Active Record).
|
18
|
+
# Also raised if you set the key for a Hash something else than a string or
|
19
|
+
# a symbol.
|
20
|
+
class SerializationError < ArgumentError
|
21
|
+
end
|
22
|
+
|
23
|
+
module Arguments
|
24
|
+
extend self
|
25
|
+
TYPE_WHITELIST = [ NilClass, Fixnum, Float, String, TrueClass, FalseClass, Bignum ]
|
26
|
+
|
27
|
+
def serialize(arguments)
|
28
|
+
arguments.map { |argument| serialize_argument(argument) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def deserialize(arguments)
|
32
|
+
arguments.map { |argument| deserialize_argument(argument) }
|
33
|
+
rescue => e
|
34
|
+
raise DeserializationError.new(e)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def serialize_argument(argument)
|
39
|
+
case argument
|
40
|
+
when *TYPE_WHITELIST
|
41
|
+
argument
|
42
|
+
when GlobalID::Identification
|
43
|
+
argument.to_global_id.to_s
|
44
|
+
when Array
|
45
|
+
argument.map { |arg| serialize_argument(arg) }
|
46
|
+
when Hash
|
47
|
+
argument.each_with_object({}) do |(key, value), hash|
|
48
|
+
hash[serialize_hash_key(key)] = serialize_argument(value)
|
49
|
+
end
|
50
|
+
else
|
51
|
+
raise SerializationError.new("Unsupported argument type: #{argument.class.name}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def deserialize_argument(argument)
|
56
|
+
case argument
|
57
|
+
when String
|
58
|
+
GlobalID::Locator.locate(argument) || argument
|
59
|
+
when *TYPE_WHITELIST
|
60
|
+
argument
|
61
|
+
when Array
|
62
|
+
argument.map { |arg| deserialize_argument(arg) }
|
63
|
+
when Hash
|
64
|
+
argument.each_with_object({}.with_indifferent_access) do |(key, value), hash|
|
65
|
+
hash[key] = deserialize_argument(value)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
raise ArgumentError, "Can only deserialize primitive arguments: #{argument.inspect}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def serialize_hash_key(key)
|
73
|
+
case key
|
74
|
+
when String, Symbol
|
75
|
+
key.to_s
|
76
|
+
else
|
77
|
+
raise SerializationError.new("Only string and symbol hash keys may be serialized as job arguments, but #{key.inspect} is a #{key.class}")
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'active_job/core'
|
2
|
+
require 'active_job/queue_adapter'
|
3
|
+
require 'active_job/queue_name'
|
4
|
+
require 'active_job/enqueuing'
|
5
|
+
require 'active_job/execution'
|
6
|
+
require 'active_job/callbacks'
|
7
|
+
require 'active_job/logging'
|
8
|
+
|
9
|
+
module ActiveJob
|
10
|
+
class Base
|
11
|
+
include Core
|
12
|
+
include QueueAdapter
|
13
|
+
include QueueName
|
14
|
+
include Enqueuing
|
15
|
+
include Execution
|
16
|
+
include Callbacks
|
17
|
+
include Logging
|
18
|
+
|
19
|
+
ActiveSupport.run_load_hooks(:active_job, self)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'active_support/callbacks'
|
2
|
+
|
3
|
+
module ActiveJob
|
4
|
+
# = Active Job Callbacks
|
5
|
+
#
|
6
|
+
# Active Job provides hooks during the lifecycle of a job. Callbacks allow you
|
7
|
+
# to trigger logic during the lifecycle of a job. Available callbacks are:
|
8
|
+
#
|
9
|
+
# * <tt>before_enqueue</tt>
|
10
|
+
# * <tt>around_enqueue</tt>
|
11
|
+
# * <tt>after_enqueue</tt>
|
12
|
+
# * <tt>before_perform</tt>
|
13
|
+
# * <tt>around_perform</tt>
|
14
|
+
# * <tt>after_perform</tt>
|
15
|
+
#
|
16
|
+
module Callbacks
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
include ActiveSupport::Callbacks
|
19
|
+
|
20
|
+
included do
|
21
|
+
define_callbacks :perform
|
22
|
+
define_callbacks :enqueue
|
23
|
+
end
|
24
|
+
|
25
|
+
module ClassMethods
|
26
|
+
# Defines a callback that will get called right before the
|
27
|
+
# job's perform method is executed.
|
28
|
+
#
|
29
|
+
# class VideoProcessJob < ActiveJob::Base
|
30
|
+
# queue_as :default
|
31
|
+
#
|
32
|
+
# before_perform do |job|
|
33
|
+
# UserMailer.notify_video_started_processing(job.arguments.first)
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# def perform(video_id)
|
37
|
+
# Video.find(video_id).process
|
38
|
+
# end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
def before_perform(*filters, &blk)
|
42
|
+
set_callback(:perform, :before, *filters, &blk)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Defines a callback that will get called right after the
|
46
|
+
# job's perform method has finished.
|
47
|
+
#
|
48
|
+
# class VideoProcessJob < ActiveJob::Base
|
49
|
+
# queue_as :default
|
50
|
+
#
|
51
|
+
# after_perform do |job|
|
52
|
+
# UserMailer.notify_video_processed(job.arguments.first)
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# def perform(video_id)
|
56
|
+
# Video.find(video_id).process
|
57
|
+
# end
|
58
|
+
# end
|
59
|
+
#
|
60
|
+
def after_perform(*filters, &blk)
|
61
|
+
set_callback(:perform, :after, *filters, &blk)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Defines a callback that will get called around the job's perform method.
|
65
|
+
#
|
66
|
+
# class VideoProcessJob < ActiveJob::Base
|
67
|
+
# queue_as :default
|
68
|
+
#
|
69
|
+
# around_perform do |job, block|
|
70
|
+
# UserMailer.notify_video_started_processing(job.arguments.first)
|
71
|
+
# block.call
|
72
|
+
# UserMailer.notify_video_processed(job.arguments.first)
|
73
|
+
# end
|
74
|
+
#
|
75
|
+
# def perform(video_id)
|
76
|
+
# Video.find(video_id).process
|
77
|
+
# end
|
78
|
+
# end
|
79
|
+
#
|
80
|
+
def around_perform(*filters, &blk)
|
81
|
+
set_callback(:perform, :around, *filters, &blk)
|
82
|
+
end
|
83
|
+
|
84
|
+
# Defines a callback that will get called right before the
|
85
|
+
# job is enqueued.
|
86
|
+
#
|
87
|
+
# class VideoProcessJob < ActiveJob::Base
|
88
|
+
# queue_as :default
|
89
|
+
#
|
90
|
+
# before_enqueue do |job|
|
91
|
+
# $statsd.increment "enqueue-video-job.try"
|
92
|
+
# end
|
93
|
+
#
|
94
|
+
# def perform(video_id)
|
95
|
+
# Video.find(video_id).process
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
def before_enqueue(*filters, &blk)
|
100
|
+
set_callback(:enqueue, :before, *filters, &blk)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Defines a callback that will get called right after the
|
104
|
+
# job is enqueued.
|
105
|
+
#
|
106
|
+
# class VideoProcessJob < ActiveJob::Base
|
107
|
+
# queue_as :default
|
108
|
+
#
|
109
|
+
# after_enqueue do |job|
|
110
|
+
# $statsd.increment "enqueue-video-job.success"
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# def perform(video_id)
|
114
|
+
# Video.find(video_id).process
|
115
|
+
# end
|
116
|
+
# end
|
117
|
+
#
|
118
|
+
def after_enqueue(*filters, &blk)
|
119
|
+
set_callback(:enqueue, :after, *filters, &blk)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Defines a callback that will get called before and after the
|
123
|
+
# job is enqueued.
|
124
|
+
#
|
125
|
+
# class VideoProcessJob < ActiveJob::Base
|
126
|
+
# queue_as :default
|
127
|
+
#
|
128
|
+
# around_enqueue do |job, block|
|
129
|
+
# $statsd.time "video-job.process" do
|
130
|
+
# block.call
|
131
|
+
# end
|
132
|
+
# end
|
133
|
+
#
|
134
|
+
# def perform(video_id)
|
135
|
+
# Video.find(video_id).process
|
136
|
+
# end
|
137
|
+
# end
|
138
|
+
#
|
139
|
+
def around_enqueue(*filters, &blk)
|
140
|
+
set_callback(:enqueue, :around, *filters, &blk)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
class ConfiguredJob #:nodoc:
|
3
|
+
def initialize(job_class, options={})
|
4
|
+
@options = options
|
5
|
+
@job_class = job_class
|
6
|
+
end
|
7
|
+
|
8
|
+
def perform_now(*args)
|
9
|
+
@job_class.new(*args).perform_now
|
10
|
+
end
|
11
|
+
|
12
|
+
def perform_later(*args)
|
13
|
+
@job_class.new(*args).enqueue @options
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module ActiveJob
|
2
|
+
module Core
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
# Job arguments
|
7
|
+
attr_accessor :arguments
|
8
|
+
attr_writer :serialized_arguments
|
9
|
+
|
10
|
+
# Timestamp when the job should be performed
|
11
|
+
attr_accessor :scheduled_at
|
12
|
+
|
13
|
+
# Job Identifier
|
14
|
+
attr_accessor :job_id
|
15
|
+
|
16
|
+
# Queue on which the job should be run on.
|
17
|
+
attr_writer :queue_name
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
# Creates a new job instance from a hash created with +serialize+
|
22
|
+
def deserialize(job_data)
|
23
|
+
job = job_data['job_class'].constantize.new
|
24
|
+
job.job_id = job_data['job_id']
|
25
|
+
job.queue_name = job_data['queue_name']
|
26
|
+
job.serialized_arguments = job_data['arguments']
|
27
|
+
job
|
28
|
+
end
|
29
|
+
|
30
|
+
# Creates a job preconfigured with the given options. You can call
|
31
|
+
# perform_later with the job arguments to enqueue the job with the
|
32
|
+
# preconfigured options
|
33
|
+
#
|
34
|
+
# ==== Options
|
35
|
+
# * <tt>:wait</tt> - Enqueues the job with the specified delay
|
36
|
+
# * <tt>:wait_until</tt> - Enqueues the job at the time specified
|
37
|
+
# * <tt>:queue</tt> - Enqueues the job on the specified queue
|
38
|
+
#
|
39
|
+
# ==== Examples
|
40
|
+
#
|
41
|
+
# VideoJob.set(queue: :some_queue).perform_later(Video.last)
|
42
|
+
# VideoJob.set(wait: 5.minutes).perform_later(Video.last)
|
43
|
+
# VideoJob.set(wait_until: Time.tomorroe).perform_later(Video.last)
|
44
|
+
# VideoJob.set(queue: :some_queue, wait: 5.minutes).perform_later(Video.last)
|
45
|
+
# VideoJob.set(queue: :some_queue, wait_until: Time.tomorroe).perform_later(Video.last)
|
46
|
+
def set(options={})
|
47
|
+
ConfiguredJob.new(self, options)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Creates a new job instance. Takes as arguments the arguments that
|
52
|
+
# will be passed to the perform method.
|
53
|
+
def initialize(*arguments)
|
54
|
+
@arguments = arguments
|
55
|
+
@job_id = SecureRandom.uuid
|
56
|
+
@queue_name = self.class.queue_name
|
57
|
+
end
|
58
|
+
|
59
|
+
# Returns a hash with the job data that can safely be passed to the
|
60
|
+
# queueing adapter.
|
61
|
+
def serialize
|
62
|
+
{
|
63
|
+
'job_class' => self.class.name,
|
64
|
+
'job_id' => job_id,
|
65
|
+
'queue_name' => queue_name,
|
66
|
+
'arguments' => serialize_arguments(arguments)
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def deserialize_arguments_if_needed
|
72
|
+
if defined?(@serialized_arguments) && @serialized_arguments.present?
|
73
|
+
@arguments = deserialize_arguments(@serialized_arguments)
|
74
|
+
@serialized_arguments = nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def serialize_arguments(serialized_args)
|
79
|
+
Arguments.serialize(serialized_args)
|
80
|
+
end
|
81
|
+
|
82
|
+
def deserialize_arguments(serialized_args)
|
83
|
+
Arguments.deserialize(serialized_args)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
|
89
|
+
|