active_job_metadata 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/README.md +128 -0
- data/Rakefile +14 -0
- data/active_job_metadata.gemspec +27 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/lib/active_job_metadata.rb +54 -0
- data/lib/active_job_metadata/all.rb +7 -0
- data/lib/active_job_metadata/lifecycle.rb +19 -0
- data/lib/active_job_metadata/metadata.rb +58 -0
- data/lib/active_job_metadata/timing.rb +44 -0
- data/lib/active_job_metadata/version.rb +3 -0
- metadata +140 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 843028f1e40916f667c6bae2fa228919eb0ed5d3
|
4
|
+
data.tar.gz: 068b6ec80c5f3560a907d3fa609fa4b6408482a5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2fe763b81691b7fa827e4dd41b2a37185a13d65205f4b9a03057d789600780f0925a50f21adf1004afce8b41071c1304c0e60284332e6f817cdeac6c9cc9a416
|
7
|
+
data.tar.gz: 25ef63615d7e34c1b91bca5d5baeb37e792ad729d4ae7a3275f7b29770d680bc84d10a5408c377c05a4a7a0ebe9ea6198eaa2c0393d55878056295f94ef1756e
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
# ActiveJobMetadata
|
2
|
+
|
3
|
+
ActiveJobMetadata lets you store and retrieve metadata associated with ActiveJob jobs regardless of the queue processing library you use.
|
4
|
+
|
5
|
+
Primary use cases include:
|
6
|
+
|
7
|
+
- Providing job status clients
|
8
|
+
- Tracking job performance
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'active_job_metadata'
|
16
|
+
```
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
You can use as much or as little of ActiveJobMetadata as you need.
|
21
|
+
|
22
|
+
Use **Lifecyle** to track the current status of your job:
|
23
|
+
|
24
|
+
class MyJob < ActiveJob::Base
|
25
|
+
include ActiveJobMetadata::Lifecycle
|
26
|
+
|
27
|
+
def perform
|
28
|
+
#...
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
job = MyJob.new
|
33
|
+
job.enque
|
34
|
+
job.status #=> "enqueued"
|
35
|
+
ActiveJobMetadata.find(job.job_id) #=> {status: "enqueued"}
|
36
|
+
|
37
|
+
You can use this in RESTful controllers to let clients query for a job's status:
|
38
|
+
|
39
|
+
class JobsController
|
40
|
+
def create
|
41
|
+
job = MyJob.new
|
42
|
+
job.enque
|
43
|
+
|
44
|
+
render json: {id: job.job_id}
|
45
|
+
end
|
46
|
+
|
47
|
+
def show
|
48
|
+
metadata = ActiveJobMetadata.find(params[:id])
|
49
|
+
|
50
|
+
if metadata
|
51
|
+
render json: metadata
|
52
|
+
else
|
53
|
+
render json: {message: "Not Found"}, status: 404
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Use the **Timing** module to track and report on execution times:
|
59
|
+
|
60
|
+
class TimedJob < ActiveJob::Base
|
61
|
+
include ActiveJobMetadata::Timing
|
62
|
+
after_peform :report_timing
|
63
|
+
|
64
|
+
def perform
|
65
|
+
#...
|
66
|
+
end
|
67
|
+
|
68
|
+
def report_timing
|
69
|
+
Rails.logger.info "Queue Duration: #{queue_duration}"
|
70
|
+
Rails.logger.info "Processing Duration: #{working_duration}"
|
71
|
+
Rails.logger.info "Total Duration: #{total_duration}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
Of course you could hook this up to [statsd](https://github.com/reinh/statsd), or any other place you collect metrics.
|
76
|
+
|
77
|
+
Use the **Metadata** module to track custom information. For instance a long running job might report the percent complete and the name of the last file it processed:
|
78
|
+
|
79
|
+
class LongRunningJob < ActiveJob::Base
|
80
|
+
include ActiveJobMetadata::Metadata
|
81
|
+
metadata :percent_complete, :current_file
|
82
|
+
|
83
|
+
def perform(files)
|
84
|
+
files.each_with_index do |file, i|
|
85
|
+
self.percent_complete = (files.length / i.to_f)
|
86
|
+
self.current_file = file
|
87
|
+
|
88
|
+
IO.open(file) do |io|
|
89
|
+
#...
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
Use this approach to enrich metadata you send back to your client.
|
97
|
+
|
98
|
+
## Configuration
|
99
|
+
|
100
|
+
Although ActiveJobMetadata should mostly work out of the box in a development environment, you will probably want to customize the backing store. ActiveJobMetadata reads and writes to an [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html). If you use more than one web server, which is likely, you will probably want to use something like [Readthis](https://github.com/sorentwo/readthis) which provides a shared interface via Redis. If you want to use a different backend for ActiveJobMetadata than Rails, create an initializer with your custom store:
|
101
|
+
|
102
|
+
# initializers/active_job_metadata.rb
|
103
|
+
|
104
|
+
# Configure ActiveJobMetadata to use Readthis:
|
105
|
+
ActiveJobMetadata.store = Readthis::Cache.new(
|
106
|
+
expires_in: 2.days.to_i
|
107
|
+
)
|
108
|
+
|
109
|
+
Currently ActiveJobMetadata only uses the `read` and `write` methods, so you can easily store your metadata wherever all your servers can easily access it if you don't mind implementing something that quacks like a [ActiveSupport::Cache::Store](http://api.rubyonrails.org/classes/ActiveSupport/Cache/Store.html).
|
110
|
+
|
111
|
+
## Alternatives
|
112
|
+
|
113
|
+
It is always wise to consider your alternatives:
|
114
|
+
|
115
|
+
* [active_job_status](https://github.com/cdale77/active_job_status)
|
116
|
+
* [resque-status](https://github.com/quirkey/resque-status) for Resque
|
117
|
+
* [sidekiq-status](https://github.com/utgarda/sidekiq-status) for Sidekiq
|
118
|
+
|
119
|
+
## Development
|
120
|
+
|
121
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
122
|
+
|
123
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
124
|
+
|
125
|
+
## Contributing
|
126
|
+
|
127
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/adamsanderson/active_job_metadata.
|
128
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
4
|
+
Rake::TestTask.new(:test) do |t|
|
5
|
+
t.libs << "test"
|
6
|
+
t.libs << "lib"
|
7
|
+
|
8
|
+
# Disable warnings to avoid circular load warnings in dependencies
|
9
|
+
t.warning = false
|
10
|
+
|
11
|
+
t.test_files = FileList['test/**/*_test.rb']
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => :test
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'active_job_metadata/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "active_job_metadata"
|
8
|
+
spec.version = ActiveJobMetadata::VERSION
|
9
|
+
spec.authors = ["adam sanderson"]
|
10
|
+
spec.email = ["netghost@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = "Store status and metadata for ActiveJobs"
|
13
|
+
spec.description = "ActiveJobMetadata lets you store and retrieve metadata associated with ActiveJob jobs regardless of the queue processing library you use."
|
14
|
+
spec.homepage = "https://github.com/adamsanderson/active_job_metadata"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency "activejob", ">= 4.2", "< 5.1"
|
22
|
+
spec.add_dependency "activesupport", ">= 4.2", "< 5.1"
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
25
|
+
spec.add_development_dependency "rake", "~> 11.0"
|
26
|
+
spec.add_development_dependency "minitest", "~> 5.9"
|
27
|
+
end
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "active_job_metadata"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require "active_job_metadata/version"
|
2
|
+
require "active_support"
|
3
|
+
|
4
|
+
module ActiveJobMetadata
|
5
|
+
|
6
|
+
# Prefix used by ActiveJobMetadata for finding and setting metadata
|
7
|
+
# by job id.
|
8
|
+
mattr_accessor(:prefix) do
|
9
|
+
"ActiveJobMetadata"
|
10
|
+
end
|
11
|
+
|
12
|
+
# ActiveSupport::Cache::Store used to save metadata. By default this uses the Rails cache,
|
13
|
+
# though you may want to use a special store if metadata is likely to fall out of the cache.
|
14
|
+
#
|
15
|
+
# Consider adjusting the retention policies to be long enough to last the total lifetime of
|
16
|
+
# a job plus some time afterwards if client code may check it at a later date.
|
17
|
+
mattr_accessor(:store) do
|
18
|
+
Rails.cache if defined? Rails
|
19
|
+
end
|
20
|
+
|
21
|
+
# Same as find, but will raise an ActiveJobMetadata::MetadataNotFound exception if
|
22
|
+
# the job's metadata is not found.
|
23
|
+
def self.find!(job_id)
|
24
|
+
find(job_id) || raise(MetadataNotFound.new("Could not find metadata: #{job_id.inspect}"))
|
25
|
+
end
|
26
|
+
|
27
|
+
# Finds a job's metadata, otherwise returns nil. Note that depending on how your store is
|
28
|
+
# configured, metadata may not always be available. For instance, if your store is configured
|
29
|
+
# to expire data after one day, then that metadata will no longer be available.
|
30
|
+
def self.find(job_id)
|
31
|
+
metadata_key = self.key(job_id)
|
32
|
+
store.read(metadata_key)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Writes metadata for a job directly to the cache. Typically you should use accessors defined
|
36
|
+
# via `metadata` on a class. See ActiveJobMetadata::Metdadata for more information.
|
37
|
+
def self.write(job_id, metadata)
|
38
|
+
metadata_key = self.key(job_id)
|
39
|
+
store.write(metadata_key, metadata)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Generates a key for a given job id. You generally shouldn't need this.
|
43
|
+
def self.key(job_id)
|
44
|
+
"#{ActiveJobMetadata.prefix}-#{job_id}"
|
45
|
+
end
|
46
|
+
|
47
|
+
class MetadataNotFound < StandardError
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
require "active_job_metadata/metadata"
|
52
|
+
require "active_job_metadata/lifecycle"
|
53
|
+
require "active_job_metadata/timing"
|
54
|
+
require "active_job_metadata/all"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Use Lifecyle to track the current status of your job.
|
2
|
+
#
|
3
|
+
module ActiveJobMetadata::Lifecycle
|
4
|
+
ENQUEUED = "enqueued"
|
5
|
+
RUNNING = "running"
|
6
|
+
DONE = "done"
|
7
|
+
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
include ActiveJobMetadata::Metadata
|
10
|
+
|
11
|
+
included do
|
12
|
+
metadata :status
|
13
|
+
|
14
|
+
after_enqueue { self.status = "enqueued" }
|
15
|
+
before_perform { self.status = "running" }
|
16
|
+
after_perform { self.status = "done" }
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# Use Metadata to define custom metadata for your job.
|
2
|
+
#
|
3
|
+
module ActiveJobMetadata::Metadata
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
# No-op
|
8
|
+
end
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
|
12
|
+
# Defines metadata accessors for each specified attribute.
|
13
|
+
#
|
14
|
+
# class LongRunningJob < ActiveJob::Base
|
15
|
+
# include ActiveJobMetadata::Metadata
|
16
|
+
# metadata :percent_complete, :current_file
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# job = LongRunningJob.new
|
20
|
+
# job.percent_complete = 80
|
21
|
+
# job.metadata #=> {percent_complete: 80}
|
22
|
+
#
|
23
|
+
def metadata *names
|
24
|
+
names.each do |name|
|
25
|
+
|
26
|
+
define_method(name) do
|
27
|
+
self.metadata[name.to_sym]
|
28
|
+
end
|
29
|
+
|
30
|
+
define_method("#{name}=") do |value|
|
31
|
+
self.metadata[name.to_sym] = value
|
32
|
+
save_metadata
|
33
|
+
value
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns all metadata for the current job.
|
41
|
+
def metadata
|
42
|
+
@metadata ||= ActiveJobMetadata.find(job_id) || {}
|
43
|
+
end
|
44
|
+
|
45
|
+
# Merges data into the current job's metdata.
|
46
|
+
def metadata= hash
|
47
|
+
metadata.merge!(hash)
|
48
|
+
save_metadata
|
49
|
+
end
|
50
|
+
|
51
|
+
# Writes metadata to `ActiveJobMetadata.store`
|
52
|
+
def save_metadata
|
53
|
+
ActiveJobMetadata.write(job_id, metadata)
|
54
|
+
|
55
|
+
metadata
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Use Timing to track and report on execution times.
|
2
|
+
#
|
3
|
+
module ActiveJobMetadata::Timing
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
include ActiveJobMetadata::Metadata
|
6
|
+
|
7
|
+
included do
|
8
|
+
metadata :enqueued_at
|
9
|
+
metadata :started_at
|
10
|
+
metadata :done_at
|
11
|
+
|
12
|
+
after_enqueue { self.enqueued_at = Time.now }
|
13
|
+
before_perform { self.started_at = Time.now }
|
14
|
+
after_perform { self.done_at = Time.now }
|
15
|
+
end
|
16
|
+
|
17
|
+
# The queue duration is the time in seconds a job spent in the queue before
|
18
|
+
# it was processed. If it has not been enqueued or processing
|
19
|
+
# has not yet begun, it will return nil.
|
20
|
+
def queue_duration
|
21
|
+
return nil unless enqueued_at && started_at
|
22
|
+
started_at - enqueued_at
|
23
|
+
end
|
24
|
+
|
25
|
+
# The working duration is the time in seconds a job spent in the process
|
26
|
+
# method. If process has not yet been called, or process has not finished
|
27
|
+
# it will return nil.
|
28
|
+
def working_duration
|
29
|
+
return nil unless done_at && started_at
|
30
|
+
done_at - started_at
|
31
|
+
end
|
32
|
+
|
33
|
+
# The total duration is the sum of the queue and working duration. This
|
34
|
+
# gives a measure of how long it took from enqueuing the job to completing
|
35
|
+
# all processing.
|
36
|
+
def total_duration
|
37
|
+
q = queue_duration
|
38
|
+
w = working_duration
|
39
|
+
return nil unless q && w
|
40
|
+
|
41
|
+
queue_duration + working_duration
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,140 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_job_metadata
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- adam sanderson
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-09-20 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activejob
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5.1'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.2'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5.1'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: activesupport
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.2'
|
40
|
+
- - "<"
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '5.1'
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '4.2'
|
50
|
+
- - "<"
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '5.1'
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: bundler
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.10'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1.10'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rake
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '11.0'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '11.0'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: minitest
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '5.9'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '5.9'
|
95
|
+
description: ActiveJobMetadata lets you store and retrieve metadata associated with
|
96
|
+
ActiveJob jobs regardless of the queue processing library you use.
|
97
|
+
email:
|
98
|
+
- netghost@gmail.com
|
99
|
+
executables: []
|
100
|
+
extensions: []
|
101
|
+
extra_rdoc_files: []
|
102
|
+
files:
|
103
|
+
- ".gitignore"
|
104
|
+
- ".travis.yml"
|
105
|
+
- Gemfile
|
106
|
+
- README.md
|
107
|
+
- Rakefile
|
108
|
+
- active_job_metadata.gemspec
|
109
|
+
- bin/console
|
110
|
+
- bin/setup
|
111
|
+
- lib/active_job_metadata.rb
|
112
|
+
- lib/active_job_metadata/all.rb
|
113
|
+
- lib/active_job_metadata/lifecycle.rb
|
114
|
+
- lib/active_job_metadata/metadata.rb
|
115
|
+
- lib/active_job_metadata/timing.rb
|
116
|
+
- lib/active_job_metadata/version.rb
|
117
|
+
homepage: https://github.com/adamsanderson/active_job_metadata
|
118
|
+
licenses: []
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - ">="
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.4.5.1
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Store status and metadata for ActiveJobs
|
140
|
+
test_files: []
|