deferred_job 0.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|