resqutils 1.0.0 → 1.1.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: 63c56aed110c280ee955278e9d007f242482e15e
4
- data.tar.gz: 07eac3dc61ff36df991829d3002d805da88bd3d3
3
+ metadata.gz: 2663293b0ffb13621afe5b4d29b2a98a0505452a
4
+ data.tar.gz: 0cdd0723fab6b23d274c5f40e62181d1e1d9fc8a
5
5
  SHA512:
6
- metadata.gz: 91fc61241a2cd1c0b623f9473fab38ecfcc19f1d7b83c92a1c5c91f72e62c8378ce614950e530f7b535987dec8f3029f62cef0c1e573d139f6d3e8dc885481c2
7
- data.tar.gz: 2f5f870492b27271bd29ebc34e4b9d6f24c0117dcf443a479175ca545a514cb881352168e12095a807ce54670f8af685a6388bca85cdf18bb07c6d86fa7b90d7
6
+ metadata.gz: 4db81ced533e45a6892a8940f9b11f6c4b0b4933fbec2117bec8b302230f9ce79a670d775dc8982d634223cb740347f412a6520b8f5f70a68de662ed1c208dbc
7
+ data.tar.gz: c502717b9ff99592aca62f89df365c27c7689e1b2e81eac5fd976d1a66a6c164d110584e3e013b8f49224d7483b6290cc2d9782102bc08effe23b26c2a8ee549
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.2.0
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- resqutils (1.0.0)
4
+ resqutils (1.1.0)
5
5
  resque
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -33,17 +33,21 @@ failed handling (which is hopefully to restart your jobs).
33
33
  You need a means of identifying these workers, and then killing them.
34
34
 
35
35
  ```ruby
36
- Resqutils::StaleWorkers.new.each do |worker|
37
- # this worker is still considered running but has started over an hour ago
38
- Resque.enqueue(WorkerKillerJob,worker.id)
39
- end
36
+ Resqutils::StaleWorkersKiller.kill_stale_workers
40
37
  ```
41
38
 
42
- `Resqutils::StaleWorkers`'s default of an hour can be overridden either in the constructor or by setting the
43
- `RESQUTILS_SECONDS_TO_BE_CONSIDERED_STALE` environment variable.
39
+ This will queue a `WorkerKillerJob` for each stale worker. This uses `Resqutils::StaleWorkers` under the covers to identify
40
+ which are stale. You can pass it in to `StaleWorkersKiller`'s constructor, or configure it using the environment. By
41
+ default, a worker running for more than an hour is considered stale.
42
+
43
+ Setting the `RESQUTILS_SECONDS_TO_BE_CONSIDERED_STALE` environment variable, you can override that.
44
+
45
+ The queue that `WorkerKillerJob` will queue to is `worker_killer_job` by default, but can be changed by setting the `RESQUTILS_WORKER_KILLER_JOB_QUEUE` environment variable.
46
+
47
+ `Resqutils::StaleWorkersKiller` is also itself a resque job, so you can use this class directly in your resque-scheduler
48
+ implementation to kill stale jobs on a schedule.
44
49
 
45
- The queue that `WorkerKillerJob` will queue to is `worker_killer_job` by default, but can either be set during the `enqueue`
46
- call or by setting the `RESQUTILS_WORKER_KILLER_JOB_QUEUE` environment variable.
50
+ You can, of course, use these building blocks on your own for other purposes.
47
51
 
48
52
  ## Spec Helpers
49
53
 
data/lib/resqutils.rb CHANGED
@@ -4,4 +4,5 @@ end
4
4
  require 'resqutils/do_not_auto_retry'
5
5
  require 'resqutils/worker_killer_job'
6
6
  require 'resqutils/stale_workers'
7
+ require 'resqutils/stale_workers_killer'
7
8
  require 'resqutils/version'
@@ -0,0 +1,18 @@
1
+ module Resqutils
2
+ # Vends stale workers that have been running "too long"
3
+ class StaleWorkersKiller
4
+
5
+ def self.perform
6
+ self.new.kill_stale_workers
7
+ end
8
+
9
+ def initialize(stale_workers: nil)
10
+ @stale_workers = stale_workers || Resqutils::StaleWorkers.new
11
+ end
12
+ def kill_stale_workers
13
+ @stale_workers.each do |worker|
14
+ Resque.enqueue(Resqutils::WorkerKillerJob,worker.id)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,3 +1,3 @@
1
1
  module Resqutils
2
- VERSION='1.0.0'
2
+ VERSION='1.1.0'
3
3
  end
@@ -10,7 +10,7 @@ module Resqutils
10
10
  end
11
11
  end
12
12
  def self.perform(worker_id)
13
- Resque.workers.detect { |_| _.id == worker_id }.unregister_worker
13
+ Resque.workers.select { |_| _.id == worker_id }.each(&:unregister_worker)
14
14
  end
15
15
  end
16
16
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'support/worker_helper'
3
+
4
+ describe Resqutils::StaleWorkersKiller do
5
+ include WorkerHelper
6
+ let(:stale_workers) {
7
+ [
8
+ worker,
9
+ worker,
10
+ worker,
11
+ ]
12
+ }
13
+ before do
14
+ allow(Resque).to receive(:enqueue)
15
+ end
16
+ describe "kill_stale_workers" do
17
+ before do
18
+
19
+ described_class.new(stale_workers: stale_workers).kill_stale_workers
20
+ end
21
+ it "queues a job for all stale workers" do
22
+ stale_workers.each do |worker|
23
+ expect(Resque).to have_received(:enqueue).with(Resqutils::WorkerKillerJob,worker.id)
24
+ end
25
+ end
26
+ end
27
+ describe "::perform" do
28
+ before do
29
+ allow(Resqutils::StaleWorkers).to receive(:new).and_return(stale_workers)
30
+ described_class.perform
31
+ end
32
+ it "queues a job for all stale workers" do
33
+ stale_workers.each do |worker|
34
+ expect(Resque).to have_received(:enqueue).with(Resqutils::WorkerKillerJob,worker.id)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
+ require 'support/worker_helper'
2
3
 
3
4
  describe Resqutils::StaleWorkers do
5
+ include WorkerHelper
4
6
  describe "each" do
5
7
  let(:workers) {
6
8
  [
@@ -139,10 +141,4 @@ describe Resqutils::StaleWorkers do
139
141
  end
140
142
  end
141
143
  end
142
-
143
- def worker(run_at = Time.now)
144
- double("resque worker", id: SecureRandom.uuid, job: { "queue" => "whatever",
145
- "run_at" => run_at.to_s,
146
- "payload" => { "class" => "Foo", "args" => [] } })
147
- end
148
144
  end
@@ -0,0 +1,7 @@
1
+ module WorkerHelper
2
+ def worker(run_at = Time.now)
3
+ double("resque worker", id: SecureRandom.uuid, job: { "queue" => "whatever",
4
+ "run_at" => run_at.to_s,
5
+ "payload" => { "class" => "Foo", "args" => [] } })
6
+ end
7
+ end
@@ -23,37 +23,48 @@ describe Resqutils::WorkerKillerJob do
23
23
  end
24
24
  end
25
25
  describe "::perform" do
26
- let(:workers) {
27
- [
28
- double(id: worker_id),
29
- double(id: worker_id),
30
- double(id: worker_id),
31
- double(id: worker_id),
32
- double(id: worker_id),
33
- double(id: worker_id),
34
- ]
35
- }
36
-
37
- let(:worker_to_kill) { workers[2] }
26
+ context "worker to kill exists" do
27
+ let(:workers) {
28
+ [
29
+ double(id: worker_id),
30
+ double(id: worker_id),
31
+ double(id: worker_id),
32
+ double(id: worker_id),
33
+ double(id: worker_id),
34
+ double(id: worker_id),
35
+ ]
36
+ }
38
37
 
39
- before do
40
- allow(Resque).to receive(:workers).and_return(workers)
41
- workers.each do |worker|
42
- allow(worker).to receive(:unregister_worker)
38
+ let(:worker_to_kill) { workers[2] }
39
+
40
+ before do
41
+ allow(Resque).to receive(:workers).and_return(workers)
42
+ workers.each do |worker|
43
+ allow(worker).to receive(:unregister_worker)
44
+ end
45
+ described_class.perform(worker_to_kill.id)
43
46
  end
44
- described_class.perform(worker_to_kill.id)
45
- end
46
47
 
47
- it "unregisters the worker we want to kill" do
48
- expect(worker_to_kill).to have_received(:unregister_worker)
49
- end
48
+ it "unregisters the worker we want to kill" do
49
+ expect(worker_to_kill).to have_received(:unregister_worker)
50
+ end
50
51
 
51
- it "doesn't touch the other workers" do
52
- workers.reject { |_| _ == worker_to_kill }.each do |worker|
53
- expect(worker).not_to have_received(:unregister_worker)
52
+ it "doesn't touch the other workers" do
53
+ workers.reject { |_| _ == worker_to_kill }.each do |worker|
54
+ expect(worker).not_to have_received(:unregister_worker)
55
+ end
56
+ end
57
+ end
58
+ context "worker to doesn't exist" do
59
+ before do
60
+ allow(Resque).to receive(:workers).and_return([])
61
+ end
62
+ it "doesn't blow up" do
63
+ expect {
64
+ described_class.perform(worker_id)
65
+ }.not_to raise_error
54
66
  end
55
67
  end
56
-
57
68
  end
58
69
 
59
70
  def worker_id
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: resqutils
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stitch Fix Engineering
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-04 00:00:00.000000000 Z
11
+ date: 2015-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: resque
@@ -62,6 +62,7 @@ files:
62
62
  - ".gitignore"
63
63
  - ".ruby-gemset"
64
64
  - ".ruby-version"
65
+ - ".travis.yml"
65
66
  - Gemfile
66
67
  - Gemfile.lock
67
68
  - LICENSE.txt
@@ -73,12 +74,15 @@ files:
73
74
  - lib/resqutils/spec/resque_helpers.rb
74
75
  - lib/resqutils/spec/resque_matchers.rb
75
76
  - lib/resqutils/stale_workers.rb
77
+ - lib/resqutils/stale_workers_killer.rb
76
78
  - lib/resqutils/version.rb
77
79
  - lib/resqutils/worker_killer_job.rb
78
80
  - lib/resqutils/worker_task.rb
79
81
  - resqutils.gemspec
80
82
  - spec/spec_helper.rb
83
+ - spec/stale_workers_killer_spec.rb
81
84
  - spec/stale_workers_spec.rb
85
+ - spec/support/worker_helper.rb
82
86
  - spec/worker_killer_job_spec.rb
83
87
  homepage: http://tech.stitchfix.com
84
88
  licenses: []
@@ -105,5 +109,7 @@ specification_version: 4
105
109
  summary: Utilities for using Resque in a Rails app
106
110
  test_files:
107
111
  - spec/spec_helper.rb
112
+ - spec/stale_workers_killer_spec.rb
108
113
  - spec/stale_workers_spec.rb
114
+ - spec/support/worker_helper.rb
109
115
  - spec/worker_killer_job_spec.rb