resque-clues 0.1.0

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