active_job_status 0.0.5 → 1.0.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b846ef69f7e610e0606b9bce25fb64edc49f1aa
4
- data.tar.gz: bd3674f5d7c02c2d7ff7b2a935c3dc2920333bdc
3
+ metadata.gz: cc15ebe7a3c29ec3e37308d2e83d7c4689af9a0f
4
+ data.tar.gz: a2e70829324e590e583c1a41c8da55407d2ad243
5
5
  SHA512:
6
- metadata.gz: de63ad633ce940138e4255fd0484c7025d5e14034df2398f81f0202429a38e8a9fb1f2b4a432a4251a49aa6dfa772a06e696df5100bb47116bb370a805781be4
7
- data.tar.gz: 385e25254035bfd3f95d7652ac730df93427655b1d8a27dc896646121b7c835e6eed520bcee180619d9147a1642cd3663522375d62c6639be2a105214a4a164f
6
+ metadata.gz: 9f9a7e772e739f48e83a783a5b820963de6a16657f96f4617608c9ffbe3abc58e5ba1f0b92c9aa9521fe7d483dcb0dd2fc653bc578a5ce238757c60e12a32dc7
7
+ data.tar.gz: ab0a3f2f6d4abe1ab96a07376bae8aa7919733926dea32cb890d330eb7ff77386711402a71186cdef450c89a78bb3a2df90a8195dd6961a2222cf3831fb8bac7
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  /.bundle/
2
2
  /.yardoc
3
3
  /Gemfile.lock
4
+ /gemfiles/*.lock
4
5
  /_yardoc/
5
6
  /coverage/
6
7
  /doc/
data/.travis.yml CHANGED
@@ -3,6 +3,11 @@ cache: bundler
3
3
  rvm:
4
4
  - 2.2.0
5
5
  script: bundle exec rake
6
+ services:
7
+ - redis
8
+ gemfile:
9
+ - Gemfile
10
+ - gemfiles/redis-activesupport.gemfile
6
11
  notifications:
7
12
  email:
8
13
  recipients:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # ActiveJobStatus
2
2
 
3
+ ## 1.0.0
4
+ - Move TrackableJob inside ActiveJobStatus namespace. Bump version to 1.0.0, as
5
+ this may be a breaking change for some users.
6
+
3
7
  ## 0.0.5
4
8
  - Use ActiveSupport::Cache instead of Redis, reducing dependencies. Changes
5
9
  from Gabe Kopley.
data/README.md CHANGED
@@ -4,9 +4,7 @@
4
4
 
5
5
  # ActiveJobStatus
6
6
 
7
- Uses Redis to provide simple job status information for ActiveJob. This is a
8
- work in progress! Version 0.1.0 will probably be the first usable version. Until
9
- then please expect frequent breaking changes, chaos, etc (Jan. 2015).
7
+ Provides simple job status information for ActiveJob.
10
8
 
11
9
  This gem uses ActiveJob callbacks to set simple ActiveSupport::Cache
12
10
  values to track job status
@@ -32,29 +30,46 @@ Or install it yourself as:
32
30
 
33
31
  ## Configuration
34
32
 
35
- You need to tell ActiveJobStatus about your memory store. This is because
36
- we anticipate including options to use different key value stores. For now
37
- we only support ActiveSupport::Cache, so put this in an inializer. If you are
38
- using Rails, you could put this in config/initializers/active_job_status.rb
33
+ You need to tell ActiveJobStatus about your memory store. By default, tell
34
+ ActiveJobStatus to use Rails' built in memory store:
39
35
 
36
+ # config/initializers/active_job_status.rb
40
37
  ActiveJobStatus.store = ActiveSupport::Cache::MemoryStore.new
41
38
 
39
+ If you are using Resque or Sidekiq, or have Redis in your stack already for
40
+ another reason, it's a good idea to tell ActiveJobStatus to use Redis for
41
+ storing job metadata. To do so, you'll first need to configure
42
+ ActiveSupport::Cache to use Redis for it's store
43
+ (perhaps by using [this gem](https://github.com/redis-store/redis-rails)). Then
44
+ use the following initializer to tell ActiveJob to use the proper store.
45
+ ActiveJob status will detect Redis and use some nice optimizations.
46
+
47
+ # config/initializers/active_job_status.rb
48
+ ActiveJobStatus.store = ActiveSupport::Cache::RedisStore.new
49
+
42
50
  ## Usage
43
51
 
44
- Have your jobs descend from TrackableJob instead of ActiveJob::Base
52
+ Have your jobs inheret from ActiveJobStatus::TrackableJob instead of ActiveJob::Base:
53
+
54
+ *Note! Previous versions of this gem did not namespace TrackableJob inside of
55
+ ActiveJob Status -- it was in the global namespace. If
56
+ upgrading from versions < 1.0, you may need to update your code.*
45
57
 
46
- class MyJob < TrackableJob
58
+ class MyJob < ActiveJobStatus::TrackableJob
47
59
  end
48
60
 
61
+ ### Job Status
62
+
49
63
  Check the status of a job using the ActiveJob job_id. Status of a job will only
50
64
  be available for 72 hours after the job is queued. For right now you can't
51
- change that
65
+ change that.
52
66
 
53
67
  my_job = MyJob.perform_later
54
68
  ActiveJobStatus::JobStatus.get_status(job_id: my_job.job_id)
55
69
  # => :queued, :working, :complete
56
70
 
57
- Create job batches You an use any key you want (for example, you might use a
71
+ ### Job Batches
72
+ For job batches you an use any key you want (for example, you might use a
58
73
  primary key or UUID from your database). If another batch with the same key
59
74
  exists, its jobs will be overwritten with the supplied list.
60
75
 
@@ -71,24 +86,28 @@ You can change that by passing the initalizer an integer value (in seconds).
71
86
  job_ids: my_jobs,
72
87
  expire_in: 500000)
73
88
 
74
- You can easily add jobs to the batch.
89
+ You can easily add jobs to the batch:
75
90
 
76
91
  new_jobs = [some_new_job.job_id, another_new_job.job_id]
77
92
  my_batch.add_jobs(job_ids: new_jobs)
78
93
 
79
- And you can ask the batch if all the jobs are completed or not.
94
+ And you can ask the batch if all the jobs are completed or not:
80
95
 
81
96
  my_batch.completed?
82
97
  # => true, false
83
98
 
84
- You can ask the batch for other bits of information.
99
+ You can ask the batch for other bits of information:
85
100
 
86
101
  batch.batch_id
87
102
  # => "230923asdlkj230923"
88
103
  batch.job_ids
89
104
  # => ["b67af7a0-3ed2-4661-a2d5-ff6b6a254886", "6c0216b9-ea0c-4ee9-a3b2-501faa919a66"]
90
- batch.expire_in
91
- # => 259200
105
+
106
+ You can also search for batches:
107
+ ActiveJobStatus::JobBatch.find(batch_id: my_key)
108
+
109
+ This method will return nil no associated job ids can be found, otherwise it will
110
+ return an ActiveJobStatus::JobBatch object.
92
111
 
93
112
  ## Contributing
94
113
 
@@ -25,4 +25,8 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_runtime_dependency "activejob", "~>4.2"
27
27
  spec.add_runtime_dependency "activesupport", "~>4.2"
28
+
29
+ spec.post_install_message = "If updating from a version below 1.0, please note " \
30
+ "TrackabeJob is now namespaced inside of ActiveJob. " \
31
+ "You will need update your code."
28
32
  end
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: "#{__dir__}/.."
4
+
5
+ gem "redis-activesupport"
@@ -0,0 +1,8 @@
1
+ require 'rails'
2
+ class ConfigureRedis < Rails::Railtie
3
+ initializer "configure_redis.configure_rails_initializers" do
4
+ if defined? ActiveSupport::Cache::RedisStore
5
+ require "active_job_status/redis"
6
+ end
7
+ end
8
+ end
@@ -3,21 +3,34 @@ module ActiveJobStatus
3
3
 
4
4
  attr_reader :batch_id
5
5
  attr_reader :job_ids
6
- attr_reader :expire_in
7
6
 
8
- def initialize(batch_id:, job_ids:, expire_in: 259200)
7
+ def initialize(batch_id:, job_ids:, expire_in: 259200, store_data: true)
9
8
  @batch_id = batch_id
10
9
  @job_ids = job_ids
11
- @expire_in = expire_in
10
+ # the store_data flag is used by the ::find method return a JobBatch
11
+ # object without re-saving the data
12
+ self.store_data(expire_in: expire_in) if store_data
13
+ end
14
+
15
+ def store_data(expire_in:)
12
16
  ActiveJobStatus.store.delete(@batch_id) # delete any old batches
13
- ActiveJobStatus.store.write(@batch_id, @job_ids, expires_in: @expire_in)
17
+ if ActiveJobStatus.store.class.to_s == "ActiveSupport::Cache::RedisStore"
18
+ ActiveJobStatus.store.sadd(@batch_id, @job_ids)
19
+ ActiveJobStatus.store.expire(@batch_id, expire_in)
20
+ else
21
+ ActiveJobStatus.store.write(@batch_id, @job_ids, expires_in: expire_in)
22
+ end
14
23
  end
15
24
 
16
25
  def add_jobs(job_ids:)
17
26
  @job_ids = @job_ids + job_ids
18
- # TODO re-optimize for redis store with sadd
19
- existing_job_ids = ActiveJobStatus.store.fetch(@batch_id)
20
- ActiveJobStatus.store.write(@batch_id, existing_job_ids.to_a | job_ids)
27
+ if ActiveJobStatus.store.class.to_s == "ActiveSupport::Cache::RedisStore"
28
+ # Save an extra redis query and perform atomic operation
29
+ ActiveJobStatus.store.sadd(@batch_id, job_ids)
30
+ else
31
+ existing_job_ids = ActiveJobStatus.store.fetch(@batch_id)
32
+ ActiveJobStatus.store.write(@batch_id, existing_job_ids.to_a | job_ids)
33
+ end
21
34
  end
22
35
 
23
36
  def completed?
@@ -29,7 +42,23 @@ module ActiveJobStatus
29
42
  end
30
43
 
31
44
  def self.find(batch_id:)
32
- ActiveJobStatus.store.fetch(batch_id).to_a
45
+ if ActiveJobStatus.store.class.to_s == "ActiveSupport::Cache::RedisStore"
46
+ job_ids = ActiveJobStatus.store.smembers(batch_id)
47
+ else
48
+ job_ids = ActiveJobStatus.store.fetch(batch_id).to_a
49
+ end
50
+
51
+ if job_ids.any?
52
+ ActiveJobStatus::JobBatch.new(batch_id: batch_id,
53
+ job_ids: job_ids,
54
+ store_data: false)
55
+ end
56
+ end
57
+
58
+ private
59
+
60
+
61
+ def write(key, job_ids, expire_in=nil)
33
62
  end
34
63
  end
35
64
  end
@@ -0,0 +1,20 @@
1
+ module ActiveJobStatus
2
+ module Redis
3
+ def sadd(key, elements)
4
+ instrument(:sadd, key, elements: elements) do
5
+ @data.sadd key, elements
6
+ end
7
+ end
8
+
9
+ def smembers(key)
10
+ instrument(:smembers, key) do
11
+ @data.smembers key
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ ActiveSupport::Cache::RedisStore.include(
18
+ ActiveJobStatus::Redis
19
+ )
20
+
@@ -1,11 +1,11 @@
1
1
  require "active_job"
2
- class TrackableJob < ActiveJob::Base
2
+ module ActiveJobStatus
3
+ class TrackableJob < ActiveJob::Base
3
4
 
4
- before_enqueue { ActiveJobStatus::JobTracker.enqueue(job_id: @job_id) }
5
+ before_enqueue { ActiveJobStatus::JobTracker.enqueue(job_id: @job_id) }
5
6
 
6
- before_perform { ActiveJobStatus::JobTracker.update(job_id: @job_id, status: :working) }
7
+ before_perform { ActiveJobStatus::JobTracker.update(job_id: @job_id, status: :working) }
7
8
 
8
- after_perform { ActiveJobStatus::JobTracker.remove(job_id: @job_id) }
9
+ after_perform { ActiveJobStatus::JobTracker.remove(job_id: @job_id) }
10
+ end
9
11
  end
10
-
11
-
@@ -1,3 +1,3 @@
1
1
  module ActiveJobStatus
2
- VERSION = "0.0.5"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -3,6 +3,7 @@ require "active_job_status/job_tracker"
3
3
  require "active_job_status/job_status"
4
4
  require "active_job_status/job_batch"
5
5
  require "active_job_status/version"
6
+ require "active_job_status/configure_redis" if defined? Rails
6
7
 
7
8
  module ActiveJobStatus
8
9
  class << self
@@ -4,14 +4,12 @@ describe ActiveJobStatus::JobBatch do
4
4
 
5
5
  let!(:batch_id) { Time.now }
6
6
 
7
- let!(:store) {
8
- ActiveJobStatus.store = ActiveSupport::Cache::MemoryStore.new
9
- }
7
+ let!(:store) { ActiveJobStatus.store = new_store }
10
8
 
11
- let!(:job1) { TrackableJob.perform_later }
12
- let!(:job2) { TrackableJob.perform_later }
13
- let!(:job3) { TrackableJob.perform_later }
14
- let!(:job4) { TrackableJob.perform_later }
9
+ let!(:job1) { ActiveJobStatus::TrackableJob.perform_later }
10
+ let!(:job2) { ActiveJobStatus::TrackableJob.perform_later }
11
+ let!(:job3) { ActiveJobStatus::TrackableJob.perform_later }
12
+ let!(:job4) { ActiveJobStatus::TrackableJob.perform_later }
15
13
 
16
14
  let!(:first_jobs) { [job1.job_id, job2.job_id] }
17
15
  let!(:addl_jobs) { [job3.job_id, job4.job_id] }
@@ -20,13 +18,22 @@ describe ActiveJobStatus::JobBatch do
20
18
  let!(:batch) { ActiveJobStatus::JobBatch.new(batch_id: batch_id,
21
19
  job_ids: first_jobs) }
22
20
 
21
+
23
22
  describe "#initialize" do
24
23
  it "should create an object" do
25
24
  expect(batch).to be_an_instance_of ActiveJobStatus::JobBatch
26
25
  end
27
26
  it "should write to the cache store" do
28
- first_jobs.each do |job_id|
29
- expect(store.fetch(batch_id)).to include job_id
27
+ expect(
28
+ ActiveJobStatus::JobBatch.find(batch_id: batch_id).job_ids
29
+ ).to match_array(first_jobs)
30
+ end
31
+ end
32
+
33
+ describe "#job_ids" do
34
+ describe "when jobs are present" do
35
+ it "should return an array of job ids" do
36
+ expect(batch.job_ids).to match_array(first_jobs)
30
37
  end
31
38
  end
32
39
  end
@@ -35,7 +42,7 @@ describe ActiveJobStatus::JobBatch do
35
42
  it "should add jobs to the set" do
36
43
  batch.add_jobs(job_ids: addl_jobs)
37
44
  total_jobs.each do |job_id|
38
- expect(ActiveJobStatus::JobBatch.find(batch_id: batch_id)).to \
45
+ expect(ActiveJobStatus::JobBatch.find(batch_id: batch_id).job_ids).to \
39
46
  include job_id
40
47
  end
41
48
  end
@@ -57,16 +64,17 @@ describe ActiveJobStatus::JobBatch do
57
64
  end
58
65
 
59
66
  describe "::find" do
60
- it "should return an array of jobs when a batch exists" do
61
- expect(ActiveJobStatus::JobBatch.find(batch_id: batch_id)).to \
62
- be_an_instance_of Array
63
- end
64
- it "should return the correct jobs" do
65
- expect(ActiveJobStatus::JobBatch.find(batch_id: batch_id)).to \
66
- eq first_jobs
67
+ describe "when a batch is present" do
68
+ it "should return a JobBatch object" do
69
+ expect(ActiveJobStatus::JobBatch.find(batch_id: batch_id)).to \
70
+ be_an_instance_of ActiveJobStatus::JobBatch
71
+ end
67
72
  end
68
- it "should return nil when no batch exists" do
69
- expect(ActiveJobStatus::JobBatch.find(batch_id: "45")).to eq []
73
+
74
+ describe "when no batch is present" do
75
+ it "should return nil" do
76
+ expect(ActiveJobStatus::JobBatch.find(batch_id: "baz")).to be_nil
77
+ end
70
78
  end
71
79
  end
72
80
 
@@ -81,9 +89,11 @@ describe ActiveJobStatus::JobBatch do
81
89
  ActiveJobStatus::JobBatch.new(batch_id: "expiry",
82
90
  job_ids: first_jobs,
83
91
  expire_in: 1)
84
- sleep 1 # TODO replace with timecop, if possible
85
- expect(ActiveJobStatus::JobBatch.find(batch_id: "expiry")).to be_empty
86
-
92
+ travel(2.seconds) do
93
+ expect(
94
+ ActiveJobStatus::JobBatch.find(batch_id: "expiry")
95
+ ).to be_nil
96
+ end
87
97
  end
88
98
  end
89
99
 
@@ -101,4 +111,3 @@ describe ActiveJobStatus::JobBatch do
101
111
  end
102
112
  end
103
113
  end
104
-
@@ -5,7 +5,7 @@ describe ActiveJobStatus::JobStatus do
5
5
  describe "::get_status" do
6
6
 
7
7
  describe "for a queued job" do
8
- let(:job) { TrackableJob.new.enqueue }
8
+ let(:job) { ActiveJobStatus::TrackableJob.new.enqueue }
9
9
 
10
10
  it "should return :queued" do
11
11
  expect(ActiveJobStatus::JobStatus.get_status(job_id: job.job_id)).to eq :queued
@@ -14,7 +14,7 @@ describe ActiveJobStatus::JobStatus do
14
14
 
15
15
  describe "for a complete job" do
16
16
 
17
- let!(:job) { TrackableJob.perform_later }
17
+ let!(:job) { ActiveJobStatus::TrackableJob.perform_later }
18
18
  sleep(10)
19
19
  #clear_performed_jobs
20
20
  it "should return :complete", pending: true do
@@ -2,10 +2,8 @@ require "spec_helper"
2
2
 
3
3
  describe ActiveJobStatus::JobTracker do
4
4
 
5
- let!(:store) {
6
- ActiveJobStatus.store = ActiveSupport::Cache::MemoryStore.new
7
- }
8
- let(:job) { TrackableJob.new.enqueue }
5
+ let!(:store) { ActiveJobStatus.store = new_store }
6
+ let(:job) { ActiveJobStatus::TrackableJob.new.enqueue }
9
7
 
10
8
  describe "::enqueue" do
11
9
  it "should enqueue a job" do
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,18 @@
1
- require "codeclimate-test-reporter"
1
+ require 'bundler'
2
+
3
+ Bundler.require(:default, :development)
4
+
2
5
  CodeClimate::TestReporter.start
3
- require "active_job_status"
6
+ Dir["#{__dir__}/support/*.rb"].each {|file| require file }
7
+
4
8
  include ActiveJob::TestHelper
9
+
5
10
  ActiveJob::Base.queue_adapter = :test
11
+
12
+ RSpec.configure do |c|
13
+ c.include Helpers
14
+ end
15
+
16
+ if defined? ActiveSupport::Cache::RedisStore
17
+ require "active_job_status/redis"
18
+ end
@@ -0,0 +1,11 @@
1
+ module Helpers
2
+ def new_store
3
+ if defined? ActiveSupport::Cache::RedisStore
4
+ puts "Using RedisStore"
5
+ ActiveSupport::Cache::RedisStore.new
6
+ else
7
+ puts "Using MemoryStore"
8
+ ActiveSupport::Cache::MemoryStore.new
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ if defined? ActiveSupport::Cache::RedisStore
2
+ # For redis we need to sleep to test
3
+ def travel(interval)
4
+ sleep interval
5
+ yield
6
+ end
7
+ else
8
+ require "active_support/testing/time_helpers"
9
+ include ActiveSupport::Testing::TimeHelpers
10
+ end
@@ -1,18 +1,18 @@
1
1
  require "spec_helper"
2
2
 
3
- describe TrackableJob do
3
+ describe ActiveJobStatus::TrackableJob do
4
4
 
5
5
  describe "#initialize" do
6
6
 
7
- let(:trackable_job) { TrackableJob.new }
7
+ let(:trackable_job) { ActiveJobStatus::TrackableJob.new }
8
8
 
9
9
  it "should create an object" do
10
- expect(trackable_job).to be_an_instance_of TrackableJob
10
+ expect(trackable_job).to be_an_instance_of ActiveJobStatus::TrackableJob
11
11
  end
12
12
  end
13
13
 
14
14
  describe 'queueing' do
15
- let(:trackable_job) { TrackableJob.new.enqueue }
15
+ let(:trackable_job) { ActiveJobStatus::TrackableJob.new.enqueue }
16
16
 
17
17
  it "should have a job id" do
18
18
  expect(trackable_job.job_id).to_not be_blank
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_job_status
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brad Johnson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-03-19 00:00:00.000000000 Z
11
+ date: 2016-01-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -110,22 +110,28 @@ files:
110
110
  - README.md
111
111
  - Rakefile
112
112
  - active_job_status.gemspec
113
+ - gemfiles/redis-activesupport.gemfile
113
114
  - lib/active_job_status.rb
115
+ - lib/active_job_status/configure_redis.rb
114
116
  - lib/active_job_status/job_batch.rb
115
117
  - lib/active_job_status/job_status.rb
116
118
  - lib/active_job_status/job_tracker.rb
119
+ - lib/active_job_status/redis.rb
117
120
  - lib/active_job_status/trackable_job.rb
118
121
  - lib/active_job_status/version.rb
119
122
  - spec/job_batch_spec.rb
120
123
  - spec/job_status_spec.rb
121
124
  - spec/job_tracker_spec.rb
122
125
  - spec/spec_helper.rb
126
+ - spec/support/helpers.rb
127
+ - spec/support/time_helpers.rb
123
128
  - spec/trackable_job_spec.rb
124
129
  homepage: https://github.com/cdale77/active_job_status
125
130
  licenses:
126
131
  - MIT
127
132
  metadata: {}
128
- post_install_message:
133
+ post_install_message: If updating from a version below 1.0, please note TrackabeJob
134
+ is now namespaced inside of ActiveJob. You will need update your code.
129
135
  rdoc_options: []
130
136
  require_paths:
131
137
  - lib
@@ -141,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
147
  version: '0'
142
148
  requirements: []
143
149
  rubyforge_project:
144
- rubygems_version: 2.4.5
150
+ rubygems_version: 2.4.5.1
145
151
  signing_key:
146
152
  specification_version: 4
147
153
  summary: Job status and batches for ActiveJob
@@ -150,4 +156,6 @@ test_files:
150
156
  - spec/job_status_spec.rb
151
157
  - spec/job_tracker_spec.rb
152
158
  - spec/spec_helper.rb
159
+ - spec/support/helpers.rb
160
+ - spec/support/time_helpers.rb
153
161
  - spec/trackable_job_spec.rb