resque-clues 0.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.
@@ -0,0 +1,100 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resque::Plugins::Clues::JobExtension do
4
+ def base_item(overrides={})
5
+ {"class" => TestWorker.to_s, "args" => [1,2]}.merge!(overrides)
6
+ end
7
+
8
+ before do
9
+ Resque::Plugins::Clues.event_publisher = nil
10
+ @job = Resque::Job.new(:test_queue, base_item('clues_metadata' => {}))
11
+ end
12
+
13
+ it "should pass Resque lint detection" do
14
+ Resque::Plugin.lint(Resque::Plugins::Clues::JobExtension)
15
+ end
16
+
17
+ context "with clues not configured" do
18
+ describe "#perform" do
19
+ it "should delegate to original perform" do
20
+ @job.should_receive(:_base_perform)
21
+ @job.perform
22
+ end
23
+ end
24
+
25
+ describe "#fail" do
26
+ it "should delegate to original fail" do
27
+ @job.should_receive(:_base_fail)
28
+ @job.fail(Exception.new)
29
+ end
30
+ end
31
+ end
32
+
33
+ context "with clues configured" do
34
+ let(:publisher) {TestPublisher.new}
35
+
36
+ before do
37
+ Resque::Plugins::Clues.event_publisher = publisher
38
+ end
39
+
40
+ describe "#perform" do
41
+ it "should publish a perform_started event" do
42
+ @job.perform
43
+ verify_event :perform_started, event_index: -2
44
+ end
45
+
46
+ it "should publish a perform_finished event that includes the time_to_perform" do
47
+ @job.perform
48
+ verify_event :perform_finished do |metadata|
49
+ metadata['time_to_perform'].nil?.should == false
50
+ end
51
+ end
52
+ end
53
+
54
+ describe "#fail" do
55
+ it "should publish a perform_failed event" do
56
+ @job.fail(Exception.new)
57
+ verify_event :failed
58
+ end
59
+
60
+ it "should delegate to original fail" do
61
+ @job.should_receive(:_base_fail)
62
+ @job.fail(Exception.new)
63
+ end
64
+
65
+ context "includes metadata in the perform_failed event that should" do
66
+ it "should include the time_to_perform" do
67
+ @job.fail(Exception.new)
68
+ verify_event :failed do |metadata|
69
+ metadata['time_to_perform'].nil?.should == false
70
+ end
71
+ end
72
+
73
+ it "should include the exception class" do
74
+ @job.fail(Exception.new)
75
+ verify_event :failed do |metadata|
76
+ metadata['exception'].should == Exception
77
+ end
78
+ end
79
+
80
+ it "should include the exception message" do
81
+ @job.fail(Exception.new('test'))
82
+ verify_event :failed do |metadata|
83
+ metadata['message'].should == 'test'
84
+ end
85
+ end
86
+
87
+ it "should include the exception backtrace" do
88
+ begin
89
+ raise 'test'
90
+ rescue => e
91
+ @job.fail(e)
92
+ verify_event :failed do |metadata|
93
+ metadata['backtrace'].nil?.should == false
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,137 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resque::Plugins::Clues::QueueExtension do
4
+ it "should pass Resque lint detection" do
5
+ Resque::Plugin.lint(Resque::Plugins::Clues::QueueExtension)
6
+ end
7
+
8
+ it "should expose original push method as _base_push" do
9
+ Resque.respond_to?(:_base_push).should == true
10
+ end
11
+
12
+ it "should expose original pop method as _base_pop" do
13
+ Resque.respond_to?(:_base_pop).should == true
14
+ end
15
+
16
+ context "with clues not configured" do
17
+ before {Resque::Plugins::Clues.event_publisher = nil}
18
+ describe "#push" do
19
+ it "should delegate directly to original Resque push method" do
20
+ Resque.should_receive(:_base_push).with(:test_queue, {})
21
+ Resque.push(:test_queue, {})
22
+ end
23
+ end
24
+
25
+ describe "#pop" do
26
+ it "should delegate directly to original Resque pop method" do
27
+ Resque.stub(:_base_pop) do |queue|
28
+ queue.should == :test_queue
29
+ {}
30
+ end
31
+ Resque.pop(:test_queue).should == {}
32
+ end
33
+ end
34
+ end
35
+
36
+ context "with clues properly configured" do
37
+ let(:publisher) {TestPublisher.new}
38
+
39
+ before do
40
+ Resque::Plugins::Clues.event_publisher = publisher
41
+ end
42
+
43
+ describe "#push" do
44
+ def base_item(overrides={})
45
+ {:class => TestWorker.to_s, :args => [1,2]}.merge!(overrides)
46
+ end
47
+
48
+ it "should invoke _base_push with a queue and item args and return the result" do
49
+ Resque.should_receive(:_base_push)
50
+ Resque.push(:test_queue, base_item)
51
+ end
52
+
53
+ context "adds metadata to item stored in redis that" do
54
+ it "should contain an event_hash identifying the job entering the queue" do
55
+ Resque.push(:test_queue, base_item)
56
+ verify_event :enqueued do |metadata|
57
+ metadata['event_hash'].nil?.should == false
58
+ end
59
+ end
60
+
61
+ it "should contain the host's hostname" do
62
+ Resque.push(:test_queue, base_item)
63
+ verify_event :enqueued do |metadata|
64
+ metadata['hostname'].should == `hostname`.strip
65
+ end
66
+ end
67
+
68
+ it "should contain the process id" do
69
+ Resque.push(:test_queue, base_item)
70
+ verify_event :enqueued do |metadata|
71
+ metadata['process'].should == $$
72
+ end
73
+ end
74
+
75
+ it "should allow an item_preprocessor to inject arbitrary data" do
76
+ Resque::Plugins::Clues.item_preprocessor = proc {|queue, item| item['clues_metadata']['employer_id'] = 1}
77
+ Resque.push(:test_queue, base_item)
78
+ verify_event :enqueued do |metadata|
79
+ metadata['employer_id'].should == 1
80
+ end
81
+ end
82
+ end
83
+ end
84
+
85
+ describe "#pop" do
86
+ def base_item(overrides={})
87
+ {'class' => TestWorker.to_s, 'args' => [1,2]}.merge!(overrides)
88
+ end
89
+
90
+ it "should invoke _base_pop with a queue arg and return the result" do
91
+ Resque.should_receive(:_base_pop)
92
+ Resque.pop(:test_queue)
93
+ end
94
+
95
+ context "when nothing is in the queue" do
96
+ it "should not die horribly" do
97
+ expect{Resque.pop(:test_queue)}.to_not raise_error
98
+ end
99
+ end
100
+
101
+ context "when retrieving an item without metadata" do
102
+ it "should delegate directly to _base_pop" do
103
+ result = base_item 'clues_metadata' => {}
104
+ Resque.stub(:_base_pop) {|queue| result}
105
+ Resque.pop(:test_queue).should == result
106
+ end
107
+ end
108
+
109
+ context "metadata in the item retrieved from redis" do
110
+ before do
111
+ Resque.stub(:_base_pop){ base_item 'clues_metadata' => {}}
112
+ end
113
+
114
+ it "should contain the hostname" do
115
+ Resque.pop(:test_queue)
116
+ verify_event :dequeued do |metadata|
117
+ metadata['hostname'].should == `hostname`.chop
118
+ end
119
+ end
120
+
121
+ it "should contain the process id" do
122
+ Resque.pop(:test_queue)
123
+ verify_event :dequeued do |metadata|
124
+ metadata['process'].should == $$
125
+ end
126
+ end
127
+
128
+ it "should contain an enqueued_time" do
129
+ Resque.pop(:test_queue)
130
+ verify_event :dequeued do |metadata|
131
+ metadata['time_in_queue'].nil?.should == false
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,73 @@
1
+ require 'rspec'
2
+ require 'pry'
3
+ require 'resque-clues'
4
+ require 'test_worker'
5
+ require 'test_publisher'
6
+
7
+ def base_item(overrides={})
8
+ {"class" => TestWorker.to_s, "args" => [1,2]}.merge!(overrides)
9
+ end
10
+
11
+ RSpec.configure do |config|
12
+ config.before(:each) do
13
+ reset_redis
14
+ end
15
+ end
16
+
17
+ def reset_redis
18
+ Resque.redis.select 15
19
+ Resque.redis.flushdb
20
+ end
21
+
22
+ def verify_event(event_type, opts={event_index: -1})
23
+ publisher.event_type(opts[:event_index]).should == event_type
24
+ publisher.timestamp(opts[:event_index]).should_not be_empty
25
+ publisher.queue(opts[:event_index]).should == :test_queue
26
+ publisher.klass(opts[:event_index]).should == 'TestWorker'
27
+ publisher.args(opts[:event_index]).should == [1, 2]
28
+ yield(publisher.metadata(opts[:event_index])) if block_given?
29
+ end
30
+
31
+ def unpatch_resque
32
+ Resque.instance_exec do
33
+ def push(queue, item)
34
+ _base_push(queue, item)
35
+ end
36
+
37
+ def pop(queue)
38
+ _base_pop(queue)
39
+ end
40
+ end
41
+
42
+ Resque::Job.class_exec do
43
+ def perform
44
+ _base_perform
45
+ end
46
+
47
+ def fail(exception)
48
+ _base_fail(exception)
49
+ end
50
+ end
51
+ end
52
+
53
+ def repatch_resque
54
+ Resque.instance_exec do
55
+ def push(queue, item)
56
+ _clues_push(queue, item)
57
+ end
58
+
59
+ def pop(queue)
60
+ _clues_pop(queue)
61
+ end
62
+ end
63
+
64
+ Resque::Job.class_exec do
65
+ def perform
66
+ _clues_perform
67
+ end
68
+
69
+ def fail(exception)
70
+ _clues_fail(exception)
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,42 @@
1
+ class TestPublisher
2
+ attr_reader :events
3
+
4
+ def initialize
5
+ @events = []
6
+ end
7
+
8
+ def publish(event_type, timestamp, queue, metadata, klass, *args)
9
+ events << {
10
+ event_type: event_type,
11
+ timestamp: timestamp,
12
+ queue: queue,
13
+ metadata: metadata,
14
+ klass: klass,
15
+ args: args
16
+ }
17
+ end
18
+
19
+ def event_type(tail=-1)
20
+ @events[tail][:event_type]
21
+ end
22
+
23
+ def timestamp(tail=-1)
24
+ @events[tail][:timestamp]
25
+ end
26
+
27
+ def queue(tail=-1)
28
+ @events[tail][:queue]
29
+ end
30
+
31
+ def metadata(tail=-1)
32
+ @events[tail][:metadata]
33
+ end
34
+
35
+ def klass(tail=-1)
36
+ @events[tail][:klass]
37
+ end
38
+
39
+ def args(tail=-1)
40
+ @events[tail][:args]
41
+ end
42
+ end
@@ -0,0 +1,6 @@
1
+ class TestWorker
2
+ @queue = :test_queue
3
+
4
+ def self.perform(first, second)
5
+ end
6
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+
3
+ describe Resque::Plugins::Clues do
4
+ describe "#event_hash" do
5
+ it "should generate different hashes for different times" do
6
+ hash1 = Resque::Plugins::Clues.event_hash
7
+ sleep(1)
8
+ hash2 = Resque::Plugins::Clues.event_hash
9
+ (hash1 == hash2).should == false
10
+ end
11
+
12
+ it "should generate different hashes for different processes" do
13
+ hash = Resque::Plugins::Clues.event_hash
14
+ fork {(hash == Resque::Plugins::Clues.event_hash).should == false}
15
+ Process.wait
16
+ end
17
+ end
18
+
19
+ describe "#time_delta_since" do
20
+ it "should detect ~1 second run time" do
21
+ start = Time.now.utc
22
+ sleep(1)
23
+ Resque::Plugins::Clues.time_delta_since(start).between?(0.99, 1.01).should == true
24
+ end
25
+
26
+ it "should not allow negative numbers (time sync)" do
27
+ start = Time.now.utc + 1
28
+ Resque::Plugins::Clues.time_delta_since(start).should == 0.0
29
+ end
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resque-clues
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Lance Woodson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ version_requirements: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.20.0
20
+ none: false
21
+ prerelease: false
22
+ name: resque
23
+ requirement: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ! '>='
26
+ - !ruby/object:Gem::Version
27
+ version: 1.20.0
28
+ none: false
29
+ type: :runtime
30
+ - !ruby/object:Gem::Dependency
31
+ version_requirements: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ~>
34
+ - !ruby/object:Gem::Version
35
+ version: 1.7.4
36
+ none: false
37
+ prerelease: false
38
+ name: multi_json
39
+ requirement: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.7.4
44
+ none: false
45
+ type: :runtime
46
+ - !ruby/object:Gem::Dependency
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ requirements:
49
+ - - ~>
50
+ - !ruby/object:Gem::Version
51
+ version: 0.9.2.2
52
+ none: false
53
+ prerelease: false
54
+ name: rake
55
+ requirement: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ~>
58
+ - !ruby/object:Gem::Version
59
+ version: 0.9.2.2
60
+ none: false
61
+ type: :development
62
+ - !ruby/object:Gem::Dependency
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ none: false
69
+ prerelease: false
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ none: false
77
+ type: :development
78
+ - !ruby/object:Gem::Dependency
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ none: false
85
+ prerelease: false
86
+ name: pry
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ! '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ none: false
93
+ type: :development
94
+ - !ruby/object:Gem::Dependency
95
+ version_requirements: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ none: false
101
+ prerelease: false
102
+ name: pry-debugger
103
+ requirement: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ! '>='
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ none: false
109
+ type: :development
110
+ - !ruby/object:Gem::Dependency
111
+ version_requirements: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ! '>='
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ none: false
117
+ prerelease: false
118
+ name: cane
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ none: false
125
+ type: :development
126
+ description: Adds event publishing and job tracking ability to Resque
127
+ email:
128
+ - lance.woodson@peopleadmin.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - .travis.yml
135
+ - Gemfile
136
+ - LICENSE.txt
137
+ - README.md
138
+ - Rakefile
139
+ - TODO
140
+ - lib/resque-clues.rb
141
+ - lib/resque/plugins/clues/event_publisher.rb
142
+ - lib/resque/plugins/clues/job_extension.rb
143
+ - lib/resque/plugins/clues/queue_extension.rb
144
+ - lib/resque/plugins/clues/util.rb
145
+ - lib/resque/plugins/clues/version.rb
146
+ - resque-clues.gemspec
147
+ - spec/event_publisher_spec.rb
148
+ - spec/integration_spec.rb
149
+ - spec/job_extension_spec.rb
150
+ - spec/queue_extension_spec.rb
151
+ - spec/spec_helper.rb
152
+ - spec/test_publisher.rb
153
+ - spec/test_worker.rb
154
+ - spec/util_spec.rb
155
+ homepage: https://github.com/PeopleAdmin/resque-clues
156
+ licenses: []
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ segments:
167
+ - 0
168
+ hash: -3444382190622690926
169
+ none: false
170
+ required_rubygems_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ! '>='
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ segments:
176
+ - 0
177
+ hash: -3444382190622690926
178
+ none: false
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 1.8.24
182
+ signing_key:
183
+ specification_version: 3
184
+ summary: Adds event publishing and job tracking
185
+ test_files:
186
+ - spec/event_publisher_spec.rb
187
+ - spec/integration_spec.rb
188
+ - spec/job_extension_spec.rb
189
+ - spec/queue_extension_spec.rb
190
+ - spec/spec_helper.rb
191
+ - spec/test_publisher.rb
192
+ - spec/test_worker.rb
193
+ - spec/util_spec.rb