active_job_status 0.0.5 → 1.0.0

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