jobba 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +9 -3
- data/lib/jobba.rb +1 -1
- data/lib/jobba/clause.rb +3 -3
- data/lib/jobba/clause_factory.rb +9 -6
- data/lib/jobba/status.rb +43 -14
- data/lib/jobba/statuses.rb +8 -3
- data/lib/jobba/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cb1d6250e365236cfdbe87245b5ccd520809fe5a
|
4
|
+
data.tar.gz: 24e9272312ad529d7ec0e33c4d21e8f06c4836b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 26f7a2a14a1de1761acec0c584bc3d3946ae23f955ba583e2a72dcd30ee3bd647cf2daa41f32b312729d8e451ed8ffbf5a3d7deaae191746f4b9f54bc106e0ab
|
7
|
+
data.tar.gz: ff3d42902f0094392848149d37379739c87b72a4cacd77f1e3e84343855defbd574b9dc8a1b9c3c2deefe08c0b150f776dc832228f8981edd6614a8aab52d366
|
data/README.md
CHANGED
@@ -127,7 +127,7 @@ The order of states is not enforced, and you do not have to use all states. How
|
|
127
127
|
|
128
128
|
Generally-speaking, you should only enter any state once. Jobba only records the timestamp the first time you enter a state.
|
129
129
|
|
130
|
-
The
|
130
|
+
The exception to this rule is that if call `started!` a second time, Jobba will note this as a restart. The current values in the status will be archived and your status will look like a `started` status, with the exception that the `attempt` count will be incremented. A restarted status can then enter `succeeded`, `failed`, or `killed` states and those timestamps will be stored. `job_name`, `job_args` and `provider_job_id` survive the restart.
|
131
131
|
|
132
132
|
The `attempt` field is zero-indexed, so the first attempt is attempt `0`.
|
133
133
|
|
@@ -171,7 +171,7 @@ my_status.save("some string")
|
|
171
171
|
|
172
172
|
Note that if you `save` or `add_error` contains a hash with symbol keys, those keys will be converted to strings. In fact, any argument passed in to these methods will be converted to JSON and parsed back again so that the `data` and `errors` attributes returns the same thing regardless of if they are retrieved immediately after being set or after being loaded from Redis.
|
173
173
|
|
174
|
-
## Setting Job Name and
|
174
|
+
## Setting Job Name, Arguments and Provider Job ID
|
175
175
|
|
176
176
|
If you want to be able to query for all statuses for a certain kind of job, you can set the job's name in the status:
|
177
177
|
|
@@ -191,6 +191,12 @@ You probably will only want to track complex arguments, e.g. models in your appl
|
|
191
191
|
|
192
192
|
Note that you can set job args with names that are either symbols or strings, but you can only read the args back by the string form of their name, e.g.
|
193
193
|
|
194
|
+
If you want to be able to query for the status for a specific job record or to find the job record associated with a status, you can set the job's provider_job_id in the status:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
my_status.set_provider_job_id(42)
|
198
|
+
```
|
199
|
+
|
194
200
|
```ruby
|
195
201
|
my_status.set_job_args(foo: "bar")
|
196
202
|
my_status.job_args['foo'] # => "bar"
|
@@ -333,7 +339,7 @@ Jobba.where(job_name: ["MySpecialBackgroundJob", "MyOtherJob"])
|
|
333
339
|
|
334
340
|
**Job Arguments**
|
335
341
|
|
336
|
-
(requires having called the optional `
|
342
|
+
(requires having called the optional `set_job_args` method)
|
337
343
|
|
338
344
|
```ruby
|
339
345
|
Jobba.where(job_arg: "gid://app/MyModel/42")
|
data/lib/jobba.rb
CHANGED
data/lib/jobba/clause.rb
CHANGED
@@ -6,18 +6,18 @@ class Jobba::Clause
|
|
6
6
|
# if `keys` or `suffixes` is an array, all entries will be included in the resulting set
|
7
7
|
def initialize(prefix: nil, suffixes: nil, keys: nil, min: nil, max: nil)
|
8
8
|
if keys.nil? && prefix.nil? && suffixes.nil?
|
9
|
-
raise ArgumentError, "Either `keys` or both `prefix` and `suffix` must be specified."
|
9
|
+
raise ArgumentError, "Either `keys` or both `prefix` and `suffix` must be specified.", caller
|
10
10
|
end
|
11
11
|
|
12
12
|
if (prefix.nil? && !suffixes.nil?) || (!prefix.nil? && suffixes.nil?)
|
13
|
-
raise ArgumentError, "When `prefix` is given, so must `suffix` be, and vice versa."
|
13
|
+
raise ArgumentError, "When `prefix` is given, so must `suffix` be, and vice versa.", caller
|
14
14
|
end
|
15
15
|
|
16
16
|
if keys
|
17
17
|
@keys = [keys].flatten
|
18
18
|
else
|
19
19
|
prefix = "#{prefix}:" unless prefix[-1] == ":"
|
20
|
-
@keys = [suffixes].flatten.collect{|suffix| prefix
|
20
|
+
@keys = [suffixes].flatten.collect{|suffix| "#{prefix}#{suffix}"}
|
21
21
|
end
|
22
22
|
|
23
23
|
@min = min
|
data/lib/jobba/clause_factory.rb
CHANGED
@@ -5,7 +5,7 @@ class Jobba::ClauseFactory
|
|
5
5
|
def self.new_clause(key, value)
|
6
6
|
if value.nil?
|
7
7
|
raise ArgumentError, "Nil search criteria are not currently " \
|
8
|
-
"accepted in a Jobba `where` call"
|
8
|
+
"accepted in a Jobba `where` call", caller
|
9
9
|
end
|
10
10
|
|
11
11
|
case key.to_sym
|
@@ -15,12 +15,14 @@ class Jobba::ClauseFactory
|
|
15
15
|
Jobba::Clause.new(prefix: "job_name", suffixes: value)
|
16
16
|
when :job_arg
|
17
17
|
Jobba::Clause.new(prefix: "job_arg", suffixes: value)
|
18
|
+
when :provider_job_id
|
19
|
+
Jobba::Clause.new(prefix: "provider_job_id", suffixes: value)
|
18
20
|
when :id
|
19
21
|
Jobba::IdClause.new(value)
|
20
22
|
when /.*_at/
|
21
23
|
timestamp_clause(key, value)
|
22
24
|
else
|
23
|
-
raise ArgumentError, "#{key} is not a valid key in a Jobba `where` call"
|
25
|
+
raise ArgumentError, "#{key} is not a valid key in a Jobba `where` call", caller
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
@@ -31,7 +33,7 @@ class Jobba::ClauseFactory
|
|
31
33
|
case options
|
32
34
|
when Array
|
33
35
|
if options.length != 2
|
34
|
-
raise ArgumentError, "Wrong number of array entries for '#{timestamp_name}'."
|
36
|
+
raise ArgumentError, "Wrong number of array entries for '#{timestamp_name}'.", caller
|
35
37
|
end
|
36
38
|
|
37
39
|
[options[0], options[1]]
|
@@ -40,7 +42,8 @@ class Jobba::ClauseFactory
|
|
40
42
|
else
|
41
43
|
raise ArgumentError,
|
42
44
|
"#{option_value} is not a valid value for a " +
|
43
|
-
"#{option_key} key in a Jobba `where` call"
|
45
|
+
"#{option_key} key in a Jobba `where` call",
|
46
|
+
caller
|
44
47
|
end
|
45
48
|
|
46
49
|
min = Jobba::Utils.time_to_usec_int(min)
|
@@ -68,14 +71,14 @@ class Jobba::ClauseFactory
|
|
68
71
|
def self.validate_state_name!(state_name)
|
69
72
|
[state_name].flatten.each do |name|
|
70
73
|
if Jobba::State::ALL.none?{|state| state.name == name.to_s}
|
71
|
-
raise ArgumentError, "'#{name}' is not a valid state name."
|
74
|
+
raise ArgumentError, "'#{name}' is not a valid state name.", caller
|
72
75
|
end
|
73
76
|
end
|
74
77
|
end
|
75
78
|
|
76
79
|
def self.validate_timestamp_name!(timestamp_name)
|
77
80
|
if Jobba::State::ALL.none?{|state| state.timestamp_name == timestamp_name.to_s}
|
78
|
-
raise ArgumentError, "'#{timestamp_name}' is not a valid timestamp."
|
81
|
+
raise ArgumentError, "'#{timestamp_name}' is not a valid timestamp.", caller
|
79
82
|
end
|
80
83
|
end
|
81
84
|
|
data/lib/jobba/status.rb
CHANGED
@@ -14,6 +14,10 @@ module Jobba
|
|
14
14
|
all.where(*args)
|
15
15
|
end
|
16
16
|
|
17
|
+
def self.find_by(*args)
|
18
|
+
all.where(*args).first
|
19
|
+
end
|
20
|
+
|
17
21
|
def self.create!
|
18
22
|
create(state: State::UNQUEUED)
|
19
23
|
end
|
@@ -36,8 +40,9 @@ module Jobba
|
|
36
40
|
end
|
37
41
|
|
38
42
|
def self.local_attrs
|
39
|
-
%w(id state progress errors data kill_requested_at
|
40
|
-
|
43
|
+
%w(id state progress errors data kill_requested_at
|
44
|
+
job_name job_args provider_job_id attempt prior_attempts) +
|
45
|
+
State::ALL.collect(&:timestamp_name)
|
41
46
|
end
|
42
47
|
|
43
48
|
def reload!
|
@@ -111,7 +116,8 @@ module Jobba
|
|
111
116
|
end
|
112
117
|
|
113
118
|
def set_job_name(job_name)
|
114
|
-
raise ArgumentError, "`job_name` must not be blank"
|
119
|
+
raise ArgumentError, "`job_name` must not be blank", caller \
|
120
|
+
if job_name.nil? || job_name.empty?
|
115
121
|
|
116
122
|
redis.multi do
|
117
123
|
redis.srem(job_name_key, id)
|
@@ -121,8 +127,9 @@ module Jobba
|
|
121
127
|
end
|
122
128
|
|
123
129
|
def set_job_args(args_hash={})
|
124
|
-
raise ArgumentError,
|
125
|
-
|
130
|
+
raise ArgumentError,
|
131
|
+
"All values in the hash passed to `set_job_args` must be strings",
|
132
|
+
caller if args_hash.values.any?{|val| !val.is_a?(String)}
|
126
133
|
|
127
134
|
args_hash = normalize_for_json(args_hash)
|
128
135
|
|
@@ -133,8 +140,19 @@ module Jobba
|
|
133
140
|
end
|
134
141
|
end
|
135
142
|
|
143
|
+
def set_provider_job_id(provider_job_id)
|
144
|
+
raise ArgumentError, "`provider_job_id` must not be blank", caller \
|
145
|
+
if provider_job_id.nil? || (provider_job_id.respond_to?(:empty?) && provider_job_id.empty?)
|
146
|
+
|
147
|
+
redis.multi do
|
148
|
+
redis.srem(provider_job_id_key, id)
|
149
|
+
set(provider_job_id: provider_job_id)
|
150
|
+
redis.sadd(provider_job_id_key, id)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
136
154
|
def add_error(error)
|
137
|
-
raise ArgumentError, "The argument to `add_error` cannot be nil" if error.nil?
|
155
|
+
raise ArgumentError, "The argument to `add_error` cannot be nil", caller if error.nil?
|
138
156
|
|
139
157
|
errors.push(normalize_for_json(error))
|
140
158
|
set(errors: errors)
|
@@ -162,7 +180,7 @@ module Jobba
|
|
162
180
|
end
|
163
181
|
|
164
182
|
def prior_attempts
|
165
|
-
[*0..attempt-1].collect{|ii| self.class.find!("#{id}:#{ii}")}
|
183
|
+
@prior_attempts ||= [*0..attempt-1].collect{|ii| self.class.find!("#{id}:#{ii}")}
|
166
184
|
end
|
167
185
|
|
168
186
|
protected
|
@@ -188,7 +206,8 @@ module Jobba
|
|
188
206
|
progress: 0,
|
189
207
|
errors: [],
|
190
208
|
job_name: job_name,
|
191
|
-
job_args: job_args
|
209
|
+
job_args: job_args,
|
210
|
+
provider_job_id: provider_job_id
|
192
211
|
}
|
193
212
|
|
194
213
|
archive_attempt!
|
@@ -223,6 +242,7 @@ module Jobba
|
|
223
242
|
@attempt = attrs[:attempt] || 0
|
224
243
|
@job_args = attrs[:job_args] || {}
|
225
244
|
@job_name = attrs[:job_name]
|
245
|
+
@provider_job_id = attrs[:provider_job_id]
|
226
246
|
|
227
247
|
if attrs[:persist]
|
228
248
|
redis.multi do
|
@@ -316,9 +336,12 @@ module Jobba
|
|
316
336
|
redis.srem(job_name_key, id)
|
317
337
|
|
318
338
|
delete_self_from_job_args_set!
|
339
|
+
|
340
|
+
redis.srem(provider_job_id_key, id)
|
319
341
|
end
|
320
342
|
|
321
343
|
prior_attempts.each(&:delete!)
|
344
|
+
@prior_attempts = nil
|
322
345
|
end
|
323
346
|
|
324
347
|
def delete_locally!
|
@@ -351,7 +374,7 @@ module Jobba
|
|
351
374
|
end
|
352
375
|
|
353
376
|
def self.job_key(id, attempt=nil)
|
354
|
-
raise
|
377
|
+
raise ArgumentError, "`id` cannot be nil", caller if id.nil?
|
355
378
|
attempt.nil? ? "id:#{id}" : "id:#{id}:#{attempt}"
|
356
379
|
end
|
357
380
|
|
@@ -359,20 +382,26 @@ module Jobba
|
|
359
382
|
"job_arg:#{arg}"
|
360
383
|
end
|
361
384
|
|
385
|
+
def provider_job_id_key
|
386
|
+
"provider_job_id:#{provider_job_id}"
|
387
|
+
end
|
388
|
+
|
362
389
|
def job_errors_key(id)
|
363
|
-
raise
|
390
|
+
raise ArgumentError, "`id` cannot be nil", caller if id.nil?
|
364
391
|
"#{id}:errors"
|
365
392
|
end
|
366
393
|
|
367
394
|
def compute_fractional_progress(at, out_of)
|
368
395
|
if at.nil?
|
369
|
-
raise ArgumentError, "Must specify at least `at` argument to `progress` call"
|
396
|
+
raise ArgumentError, "Must specify at least `at` argument to `progress` call", caller
|
370
397
|
elsif at < 0
|
371
|
-
raise ArgumentError, "progress cannot be negative (at=#{at})"
|
398
|
+
raise ArgumentError, "progress cannot be negative (at=#{at})", caller
|
372
399
|
elsif out_of && out_of < at
|
373
|
-
raise ArgumentError, "`out_of` must be greater than `at` in `progress` calls"
|
400
|
+
raise ArgumentError, "`out_of` must be greater than `at` in `progress` calls", caller
|
374
401
|
elsif out_of.nil? && (at < 0 || at > 1)
|
375
|
-
raise ArgumentError,
|
402
|
+
raise ArgumentError,
|
403
|
+
"If `out_of` not specified, `at` must be in the range [0.0, 1.0]",
|
404
|
+
caller
|
376
405
|
end
|
377
406
|
|
378
407
|
at.to_f / (out_of || 1).to_f
|
data/lib/jobba/statuses.rb
CHANGED
@@ -11,7 +11,8 @@ class Jobba::Statuses
|
|
11
11
|
|
12
12
|
def_delegators :@ids, :empty?
|
13
13
|
|
14
|
-
def_delegators :load, :any?, :none?, :all?, :count, :
|
14
|
+
def_delegators :load, :any?, :none?, :all?, :count, :length, :size,
|
15
|
+
:map, :collect, :reduce, :inject, :first, :last
|
15
16
|
|
16
17
|
def select!(&block)
|
17
18
|
modify!(:select!, &block)
|
@@ -25,14 +26,18 @@ class Jobba::Statuses
|
|
25
26
|
if any?(&:incomplete?)
|
26
27
|
raise(Jobba::NotCompletedError,
|
27
28
|
"This status cannot be deleted because it isn't complete. Use " \
|
28
|
-
"`
|
29
|
+
"`delete_all!` if you want to delete anyway.")
|
29
30
|
end
|
30
31
|
|
31
|
-
|
32
|
+
delete_all!
|
32
33
|
end
|
33
34
|
|
34
35
|
def delete_all!
|
35
36
|
load
|
37
|
+
|
38
|
+
# preload prior attempts because loading them is not `multi`-friendly
|
39
|
+
@cache.each(&:prior_attempts)
|
40
|
+
|
36
41
|
redis.multi do
|
37
42
|
@cache.each(&:delete!)
|
38
43
|
end
|
data/lib/jobba/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jobba
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- JP Slavinsky
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -161,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
161
|
version: '0'
|
162
162
|
requirements: []
|
163
163
|
rubyforge_project:
|
164
|
-
rubygems_version: 2.4.
|
164
|
+
rubygems_version: 2.4.5.1
|
165
165
|
signing_key:
|
166
166
|
specification_version: 4
|
167
167
|
summary: Redis-based background job status tracking.
|