deferred_job 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +27 -15
- data/lib/adapters/resque_adapter.rb +19 -0
- data/lib/adapters/sidekiq_adapter.rb +19 -0
- data/lib/deferred_job.rb +60 -38
- data/lib/deferred_job/version.rb +5 -0
- metadata +28 -9
data/README.md
CHANGED
@@ -1,17 +1,29 @@
|
|
1
1
|
# DeferredJob
|
2
2
|
|
3
|
-
DeferredJob is a small library meant to work with Resque that allows
|
4
|
-
a set of pre-conditions that must be met before a
|
3
|
+
DeferredJob is a small library meant to work with Resque or Sidekiq that allows
|
4
|
+
you to add a set of pre-conditions that must be met before a job kicks off.
|
5
|
+
|
6
|
+
``` bash
|
7
|
+
$ gem install deferred_job
|
8
|
+
```
|
5
9
|
|
6
10
|
## Usage
|
7
11
|
|
12
|
+
### Configuration
|
13
|
+
|
14
|
+
You'll need to tell DeferredJob which message processing system you're using:
|
15
|
+
|
16
|
+
``` ruby
|
17
|
+
DeferredJob::Job.adapter = :sidekiq
|
18
|
+
```
|
19
|
+
|
8
20
|
### Creating a DeferredJob
|
9
21
|
|
10
22
|
To create a deferred job, you must give it an id, and the name/arguments
|
11
23
|
of a worker to kick off when the preconditions are met:
|
12
24
|
|
13
25
|
``` ruby
|
14
|
-
job =
|
26
|
+
job = DeferredJob::Job.create(id, SomeWorker, 'worker', 'args')
|
15
27
|
```
|
16
28
|
|
17
29
|
_NOTE:_ If you try to re-create an existing job, you'll clear it out.
|
@@ -22,9 +34,9 @@ To add preconditions, you can use `#wait_for`. So if you wanted to wait until
|
|
22
34
|
a few things are done, you can add them one at a time, or in bulk:
|
23
35
|
|
24
36
|
``` ruby
|
25
|
-
job.wait_for
|
26
|
-
job.wait_for
|
27
|
-
job.wait_for
|
37
|
+
job.wait_for('import-1-data')
|
38
|
+
job.wait_for('import-2-data')
|
39
|
+
job.wait_for('import-1-photos', 'import-2-photos')
|
28
40
|
```
|
29
41
|
|
30
42
|
### Checking preconditions
|
@@ -55,9 +67,9 @@ to finish things in the same order you put them in (and hopefully you
|
|
55
67
|
aren't):
|
56
68
|
|
57
69
|
``` ruby
|
58
|
-
job.done
|
59
|
-
job.done
|
60
|
-
job.done
|
70
|
+
job.done('import-1-data')
|
71
|
+
job.done('import-1-photos', 'import-2-photos')
|
72
|
+
job.done('import-2-data') # job kick off!
|
61
73
|
```
|
62
74
|
|
63
75
|
### Loading an existing job
|
@@ -68,24 +80,24 @@ In that case, load a previous job like so:
|
|
68
80
|
|
69
81
|
``` ruby
|
70
82
|
# Check existence if you'd like
|
71
|
-
|
83
|
+
DeferredJob::Job.exists? id # true
|
72
84
|
|
73
85
|
# Load the job up
|
74
|
-
job =
|
86
|
+
job = DeferredJob::Job.find id
|
75
87
|
```
|
76
88
|
|
77
89
|
_NOTE:_ If you try to find a job that does not exist, you'll raise an
|
78
|
-
exception (`
|
90
|
+
exception (`DeferredJob::NoSuchJob`).
|
79
91
|
|
80
92
|
## Advanced
|
81
93
|
|
82
94
|
### Redis Client
|
83
95
|
|
84
|
-
By default, `DeferredJob` will use the same redis instance as
|
96
|
+
By default, `DeferredJob` will use the same redis instance as your message processing tool.
|
85
97
|
If you'd like to change that, you can set the redis instace like so:
|
86
98
|
|
87
99
|
``` ruby
|
88
|
-
|
100
|
+
DeferredJob::Job.redis = your_instance
|
89
101
|
```
|
90
102
|
|
91
103
|
### Key Generation
|
@@ -95,7 +107,7 @@ like `deferred-job:#{id}`. It can be useful to change that, so you can
|
|
95
107
|
specify a new lambda expression for generating the keys:
|
96
108
|
|
97
109
|
``` ruby
|
98
|
-
|
110
|
+
DeferredJob.key_lambda = lambda { |id| "job:#{id}" }
|
99
111
|
```
|
100
112
|
|
101
113
|
## License
|
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'resque'
|
3
|
+
|
4
|
+
module DeferredJob
|
5
|
+
|
6
|
+
class ResqueAdapter
|
7
|
+
|
8
|
+
def enqueue(klass, *args)
|
9
|
+
::Resque.enqueue(klass, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_redis(&block)
|
13
|
+
block.call(::Resque.redis)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
# no mas
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
begin
|
2
|
+
require 'sidekiq'
|
3
|
+
|
4
|
+
module DeferredJob
|
5
|
+
|
6
|
+
class SidekiqAdapter
|
7
|
+
|
8
|
+
def enqueue(klass, *args)
|
9
|
+
klass.perform_async(*args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_redis(&block)
|
13
|
+
Sidekiq.redis(&block)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
# no mas
|
19
|
+
end
|
data/lib/deferred_job.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'bundler/setup'
|
2
|
-
require 'resque'
|
3
2
|
|
4
3
|
begin
|
5
4
|
require 'active_support/core_ext/string/inflections'
|
@@ -7,14 +6,17 @@ rescue LoadError
|
|
7
6
|
require 'active_support'
|
8
7
|
end
|
9
8
|
|
10
|
-
|
9
|
+
require_relative 'adapters/resque_adapter'
|
10
|
+
require_relative 'adapters/sidekiq_adapter'
|
11
11
|
|
12
|
-
|
13
|
-
|
12
|
+
module DeferredJob
|
13
|
+
|
14
|
+
autoload :VERSION, 'deferred_job/version'
|
14
15
|
|
15
|
-
class
|
16
|
+
class NoSuchJob < StandardError
|
17
|
+
end
|
16
18
|
|
17
|
-
|
19
|
+
class Job
|
18
20
|
|
19
21
|
attr_accessor :verbose
|
20
22
|
attr_reader :id, :klass, :args, :set_key
|
@@ -32,13 +34,15 @@ module Resque
|
|
32
34
|
|
33
35
|
# Clear all entries in the set
|
34
36
|
def clear
|
35
|
-
redis.del
|
37
|
+
with_redis { |redis| redis.del(@set_key) }
|
36
38
|
end
|
37
39
|
|
38
40
|
# Clear and then remove the key for this job
|
39
41
|
def destroy
|
40
|
-
redis
|
41
|
-
|
42
|
+
with_redis do |redis|
|
43
|
+
redis.del(@set_key)
|
44
|
+
redis.del(@id)
|
45
|
+
end
|
42
46
|
end
|
43
47
|
|
44
48
|
# Determine if the set is empty
|
@@ -50,7 +54,7 @@ module Resque
|
|
50
54
|
# Count the number of elements in the set
|
51
55
|
# @return [Fixnum] the count of the elements in the set
|
52
56
|
def count
|
53
|
-
redis.scard(@set_key).to_i
|
57
|
+
with_redis { |redis| redis.scard(@set_key).to_i }
|
54
58
|
end
|
55
59
|
|
56
60
|
# Wait for a thing before continuing
|
@@ -60,16 +64,16 @@ module Resque
|
|
60
64
|
def wait_for(*things)
|
61
65
|
things.each do |thing|
|
62
66
|
log "DeferredJob #{@id} will wait for #{thing.inspect}"
|
63
|
-
redis.sadd @set_key, thing
|
67
|
+
with_redis { |redis| redis.sadd @set_key, thing }
|
64
68
|
end
|
65
69
|
end
|
66
70
|
|
67
71
|
def waiting_for?(thing)
|
68
|
-
redis.sismember(@set_key, thing)
|
72
|
+
with_redis { |redis| redis.sismember(@set_key, thing) }
|
69
73
|
end
|
70
74
|
|
71
75
|
def waiting_for
|
72
|
-
redis.smembers(@set_key)
|
76
|
+
with_redis { |redis| redis.smembers(@set_key) }
|
73
77
|
end
|
74
78
|
|
75
79
|
# Mark a thing as finished
|
@@ -77,13 +81,16 @@ module Resque
|
|
77
81
|
# @return [Fixnum] the number of things removed
|
78
82
|
# NOTE >= 2.4 should use srem with multiple things
|
79
83
|
def done(*things)
|
80
|
-
results =
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
84
|
+
results = nil
|
85
|
+
with_redis do |redis|
|
86
|
+
results = redis.multi do
|
87
|
+
redis.scard @set_key
|
88
|
+
things.each do |thing|
|
89
|
+
log "DeferredJob #{id} done with #{thing.inspect}"
|
90
|
+
redis.srem @set_key, thing
|
91
|
+
end
|
92
|
+
redis.scard @set_key
|
85
93
|
end
|
86
|
-
redis.scard @set_key
|
87
94
|
end
|
88
95
|
if results.first > 0
|
89
96
|
if results.last.zero?
|
@@ -104,12 +111,16 @@ module Resque
|
|
104
111
|
|
105
112
|
private
|
106
113
|
|
107
|
-
# A helper
|
108
|
-
def
|
109
|
-
self.class.
|
114
|
+
# A helper
|
115
|
+
def with_redis(&block)
|
116
|
+
self.class.with_redis(&block)
|
117
|
+
end
|
118
|
+
|
119
|
+
def adapter
|
120
|
+
self.class.adapter
|
110
121
|
end
|
111
122
|
|
112
|
-
# How to log
|
123
|
+
# How to log
|
113
124
|
def log(msg)
|
114
125
|
if verbose
|
115
126
|
if defined?(Rails)
|
@@ -120,14 +131,14 @@ module Resque
|
|
120
131
|
end
|
121
132
|
end
|
122
133
|
|
123
|
-
# Execute the job with
|
134
|
+
# Execute the job with the adapter
|
124
135
|
def execute
|
125
|
-
|
136
|
+
adapter.enqueue klass, *args
|
126
137
|
end
|
127
138
|
|
128
139
|
class << self
|
129
140
|
|
130
|
-
attr_writer :redis, :key_lambda
|
141
|
+
attr_writer :redis, :key_lambda, :adapter
|
131
142
|
|
132
143
|
# The way we turn id into set_key
|
133
144
|
# @param [Object] id - the id of the job
|
@@ -141,10 +152,10 @@ module Resque
|
|
141
152
|
# @param [Object] id - the id of the job
|
142
153
|
# @param [Class, String] klass - The class of the job to run
|
143
154
|
# @param [Array] args - The args to send to the job
|
144
|
-
# @return [
|
155
|
+
# @return [DeferredJob] - the job, cleared
|
145
156
|
def create(id, klass, *args)
|
146
157
|
plan = [klass.to_s, args]
|
147
|
-
redis.set(id, MultiJson.encode(plan))
|
158
|
+
with_redis { |redis| redis.set(id, MultiJson.encode(plan)) }
|
148
159
|
# Return the job
|
149
160
|
job = new(id, klass, *args)
|
150
161
|
job.clear
|
@@ -153,12 +164,12 @@ module Resque
|
|
153
164
|
|
154
165
|
# Find an existing DeferredJob
|
155
166
|
# @param [Object] id - the id of the job
|
156
|
-
# @return [
|
167
|
+
# @return [DeferredJob] - the job
|
157
168
|
def find(id)
|
158
|
-
plan_data = redis.get(id)
|
159
|
-
# If found, return the job, otherwise raise
|
169
|
+
plan_data = with_redis { |redis| redis.get(id) }
|
170
|
+
# If found, return the job, otherwise raise NoSuchJob
|
160
171
|
if plan_data.nil?
|
161
|
-
raise
|
172
|
+
raise NoSuchJob.new "No Such DeferredJob: #{id}"
|
162
173
|
else
|
163
174
|
plan = MultiJson.decode(plan_data)
|
164
175
|
new(id, plan.first, *plan.last)
|
@@ -169,17 +180,28 @@ module Resque
|
|
169
180
|
# @param [Object] id - the id of the job to lookup
|
170
181
|
# @return [Boolean] - whether or not the job exists
|
171
182
|
def exists?(id)
|
172
|
-
!redis.get(id).nil?
|
183
|
+
with_redis { |redis| !redis.get(id).nil? }
|
173
184
|
end
|
174
185
|
|
175
|
-
# Our own redis instance in case people want to separate from
|
186
|
+
# Our own redis instance in case people want to separate from the message processor
|
176
187
|
# @return [Redis::Client] - a redis client
|
177
|
-
def
|
178
|
-
@redis
|
188
|
+
def with_redis(&block)
|
189
|
+
if @redis
|
190
|
+
block.call(@redis)
|
191
|
+
else
|
192
|
+
adapter.with_redis(&block)
|
193
|
+
end
|
179
194
|
end
|
180
195
|
|
196
|
+
def adapter
|
197
|
+
@adapter_instance ||= begin
|
198
|
+
if @adapter.nil? || @adapter == :resque
|
199
|
+
ResqueAdapter.new
|
200
|
+
elsif @adapter == :sidekiq
|
201
|
+
SidekiqAdapter.new
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
181
205
|
end
|
182
|
-
|
183
206
|
end
|
184
|
-
|
185
207
|
end
|
metadata
CHANGED
@@ -1,16 +1,33 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deferred_job
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- John Crepezzi
|
9
|
+
- Aubrey Holland
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2013-01-04 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: resque
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :development
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: '0'
|
14
31
|
- !ruby/object:Gem::Dependency
|
15
32
|
name: rspec
|
16
33
|
requirement: !ruby/object:Gem::Requirement
|
@@ -60,14 +77,14 @@ dependencies:
|
|
60
77
|
- !ruby/object:Gem::Version
|
61
78
|
version: '0'
|
62
79
|
- !ruby/object:Gem::Dependency
|
63
|
-
name:
|
80
|
+
name: sidekiq
|
64
81
|
requirement: !ruby/object:Gem::Requirement
|
65
82
|
none: false
|
66
83
|
requirements:
|
67
84
|
- - ! '>='
|
68
85
|
- !ruby/object:Gem::Version
|
69
86
|
version: '0'
|
70
|
-
type: :
|
87
|
+
type: :development
|
71
88
|
prerelease: false
|
72
89
|
version_requirements: !ruby/object:Gem::Requirement
|
73
90
|
none: false
|
@@ -76,7 +93,7 @@ dependencies:
|
|
76
93
|
- !ruby/object:Gem::Version
|
77
94
|
version: '0'
|
78
95
|
- !ruby/object:Gem::Dependency
|
79
|
-
name:
|
96
|
+
name: multi_json
|
80
97
|
requirement: !ruby/object:Gem::Requirement
|
81
98
|
none: false
|
82
99
|
requirements:
|
@@ -91,12 +108,15 @@ dependencies:
|
|
91
108
|
- - ! '>='
|
92
109
|
- !ruby/object:Gem::Version
|
93
110
|
version: '0'
|
94
|
-
description:
|
95
|
-
email:
|
111
|
+
description: Deferred Jobs
|
112
|
+
email: aubrey@brewster.com
|
96
113
|
executables: []
|
97
114
|
extensions: []
|
98
115
|
extra_rdoc_files: []
|
99
116
|
files:
|
117
|
+
- lib/adapters/resque_adapter.rb
|
118
|
+
- lib/adapters/sidekiq_adapter.rb
|
119
|
+
- lib/deferred_job/version.rb
|
100
120
|
- lib/deferred_job.rb
|
101
121
|
- README.md
|
102
122
|
- spec/spec_helper.rb
|
@@ -123,7 +143,6 @@ rubyforge_project:
|
|
123
143
|
rubygems_version: 1.8.24
|
124
144
|
signing_key:
|
125
145
|
specification_version: 3
|
126
|
-
summary: Resque
|
146
|
+
summary: Deferred job library for Resque or Sidekiq
|
127
147
|
test_files:
|
128
148
|
- spec/spec_helper.rb
|
129
|
-
has_rdoc:
|