pwwka 0.13.3 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile.lock +22 -21
- data/README.md +2 -2
- data/Rakefile +10 -1
- data/lib/pwwka/configuration.rb +1 -1
- data/lib/pwwka/error_handlers/chain.rb +1 -1
- data/lib/pwwka/error_handlers/ignore_payload_format_errors.rb +17 -0
- data/lib/pwwka/error_handlers.rb +1 -0
- data/lib/pwwka/version.rb +1 -1
- data/spec/integration/unhandled_errors_in_receivers_spec.rb +58 -17
- data/spec/unit/configuration_spec.rb +4 -4
- data/spec/unit/logging_spec.rb +3 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 92357bbf204f0558fb03ce13a7f13d8143d5259a
|
4
|
+
data.tar.gz: e10916ec0e829f164c26daa13ea0dcad72076001
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 45252ff1d13c6c001ac445d9e50fea106e0c1043b442391cf71a7c59571a54e560fca9fb638772bb5a78da1455616456ee8ebb3125fba6f95c96c3cb9f08f9ef
|
7
|
+
data.tar.gz: 269ef0814b600537de72bff6033b47e037629430b4108b75f41843adb5d3acc8ab79492b577877e5ea24b7730fd78869f33471cb62f84bc360099ac07533fab5
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pwwka (0.
|
4
|
+
pwwka (0.14.0)
|
5
5
|
activemodel
|
6
6
|
activesupport
|
7
7
|
bunny
|
@@ -23,21 +23,22 @@ GEM
|
|
23
23
|
concurrent-ruby (1.0.5)
|
24
24
|
diff-lcs (1.3)
|
25
25
|
docile (1.1.5)
|
26
|
-
et-orbi (1.0.
|
26
|
+
et-orbi (1.0.7)
|
27
27
|
tzinfo
|
28
|
-
i18n (0.
|
28
|
+
i18n (0.9.0)
|
29
|
+
concurrent-ruby (~> 1.0)
|
29
30
|
json (2.1.0)
|
30
31
|
minitest (5.10.3)
|
31
32
|
mono_logger (1.1.0)
|
32
|
-
multi_json (1.12.
|
33
|
-
mustermann (1.0.
|
33
|
+
multi_json (1.12.2)
|
34
|
+
mustermann (1.0.1)
|
34
35
|
rack (2.0.3)
|
35
36
|
rack-protection (2.0.0)
|
36
37
|
rack
|
37
38
|
rainbow (2.2.2)
|
38
39
|
rake
|
39
|
-
rake (12.
|
40
|
-
redis (3.3.
|
40
|
+
rake (12.1.0)
|
41
|
+
redis (3.3.5)
|
41
42
|
redis-namespace (1.5.3)
|
42
43
|
redis (~> 3.0, >= 3.0.4)
|
43
44
|
resque (1.27.4)
|
@@ -56,33 +57,33 @@ GEM
|
|
56
57
|
rufus-scheduler (~> 3.2)
|
57
58
|
resqutils (1.2.1)
|
58
59
|
resque
|
59
|
-
rspec (3.
|
60
|
-
rspec-core (~> 3.
|
61
|
-
rspec-expectations (~> 3.
|
62
|
-
rspec-mocks (~> 3.
|
63
|
-
rspec-core (3.
|
64
|
-
rspec-support (~> 3.
|
65
|
-
rspec-expectations (3.
|
60
|
+
rspec (3.7.0)
|
61
|
+
rspec-core (~> 3.7.0)
|
62
|
+
rspec-expectations (~> 3.7.0)
|
63
|
+
rspec-mocks (~> 3.7.0)
|
64
|
+
rspec-core (3.7.0)
|
65
|
+
rspec-support (~> 3.7.0)
|
66
|
+
rspec-expectations (3.7.0)
|
66
67
|
diff-lcs (>= 1.2.0, < 2.0)
|
67
|
-
rspec-support (~> 3.
|
68
|
-
rspec-mocks (3.
|
68
|
+
rspec-support (~> 3.7.0)
|
69
|
+
rspec-mocks (3.7.0)
|
69
70
|
diff-lcs (>= 1.2.0, < 2.0)
|
70
|
-
rspec-support (~> 3.
|
71
|
-
rspec-support (3.
|
71
|
+
rspec-support (~> 3.7.0)
|
72
|
+
rspec-support (3.7.0)
|
72
73
|
rufus-scheduler (3.4.2)
|
73
74
|
et-orbi (~> 1.0)
|
74
|
-
simplecov (0.
|
75
|
+
simplecov (0.15.1)
|
75
76
|
docile (~> 1.1.0)
|
76
77
|
json (>= 1.8, < 3)
|
77
78
|
simplecov-html (~> 0.10.0)
|
78
|
-
simplecov-html (0.10.
|
79
|
+
simplecov-html (0.10.2)
|
79
80
|
sinatra (2.0.0)
|
80
81
|
mustermann (~> 1.0)
|
81
82
|
rack (~> 2.0)
|
82
83
|
rack-protection (= 2.0.0)
|
83
84
|
tilt (~> 2.0)
|
84
85
|
thread_safe (0.3.6)
|
85
|
-
tilt (2.0.
|
86
|
+
tilt (2.0.8)
|
86
87
|
tzinfo (1.2.3)
|
87
88
|
thread_safe (~> 0.1)
|
88
89
|
vegas (0.1.11)
|
data/README.md
CHANGED
@@ -260,8 +260,8 @@ end
|
|
260
260
|
|
261
261
|
#### Errors From Your Handler
|
262
262
|
|
263
|
-
By default,
|
264
|
-
restarted after a crash.
|
263
|
+
By default, handlers will log and ignore garbled payloads (basically payloads that fail to be parsed as JSON). All other errors
|
264
|
+
will crash the handler, under the assumption that it will restart. This is good, because it allows you to recover from most intermittent things. Just be aware of this when configuring your handler so that it gets restarted after a crash.
|
265
265
|
|
266
266
|
What happens to the message you received during the error depends:
|
267
267
|
|
data/Rakefile
CHANGED
@@ -11,5 +11,14 @@ Gem::PackageTask.new(gemspec) {}
|
|
11
11
|
RSpec::Core::RakeTask.new(:spec)
|
12
12
|
Bundler::GemHelper.install_tasks
|
13
13
|
|
14
|
-
task :
|
14
|
+
task default: :spec
|
15
15
|
|
16
|
+
task :tag do
|
17
|
+
require "pwwka/version"
|
18
|
+
version = "v#{Pwwka::VERSION}"
|
19
|
+
sh("git tag #{version}") { |ok,res| fail res.inspect unless ok }
|
20
|
+
sh("git push --tags origin") { |ok,res| fail res.inspect unless ok }
|
21
|
+
end
|
22
|
+
task release: [ :build, :tag ] do
|
23
|
+
sh("gem push --key rubygems_stitchfix_api_key pkg/pwwka-#{Pwwka::VERSION}.gem") { |ok,res| fail res.inspect unless ok }
|
24
|
+
end
|
data/lib/pwwka/configuration.rb
CHANGED
@@ -8,7 +8,7 @@ module Pwwka
|
|
8
8
|
@error_handlers = default_handler_chain
|
9
9
|
end
|
10
10
|
def handle_error(message_handler_klass,receiver,queue_name,payload,delivery_info,exception)
|
11
|
-
logf "%{message_handler_klass}
|
11
|
+
logf "Error Processing Message in %{message_handler_klass} due to %{exception} from payload '%{payload}'", at: :error, message_handler_klass: message_handler_klass, exception: exception.message, payload: payload
|
12
12
|
if message_handler_klass.respond_to?(:error_handler)
|
13
13
|
@error_handlers.unshift(message_handler_klass.send(:error_handler))
|
14
14
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "base_error_handler"
|
2
|
+
module Pwwka
|
3
|
+
module ErrorHandlers
|
4
|
+
class IgnorePayloadFormatErrors < BaseErrorHandler
|
5
|
+
def handle_error(receiver,queue_name,payload,delivery_info,exception)
|
6
|
+
if exception.kind_of?(JSON::JSONError)
|
7
|
+
log("Ignoring JSON error",queue_name,payload,delivery_info,exception)
|
8
|
+
receiver.nack(delivery_info.delivery_tag)
|
9
|
+
abort_chain
|
10
|
+
else
|
11
|
+
keep_going
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/pwwka/error_handlers.rb
CHANGED
data/lib/pwwka/version.rb
CHANGED
@@ -1,17 +1,31 @@
|
|
1
|
-
require
|
1
|
+
require "spec_helper.rb"
|
2
|
+
require "logger"
|
3
|
+
require "stringio"
|
2
4
|
require_relative "support/integration_test_setup"
|
3
5
|
require_relative "support/logging_receiver"
|
4
6
|
require_relative "support/integration_test_helpers"
|
5
7
|
|
8
|
+
class EvilPayload
|
9
|
+
def to_json
|
10
|
+
"This is not JSON by any stretch"
|
11
|
+
end
|
12
|
+
end
|
6
13
|
describe "receivers with unhandled errors", :integration do
|
7
14
|
include IntegrationTestHelpers
|
8
15
|
|
16
|
+
let(:log_data) { StringIO.new }
|
17
|
+
let(:payload) {
|
18
|
+
{ "sample" => "payload", "has" => { "deeply" => true, "nested" => 4 }}
|
19
|
+
}
|
20
|
+
|
9
21
|
before do
|
10
22
|
@testing_setup = IntegrationTestSetup.new
|
11
23
|
Pwwka.configuration.instance_variable_set("@error_handling_chain",nil)
|
12
24
|
Pwwka.configure do |c|
|
13
25
|
c.requeue_on_error = false
|
14
26
|
c.keep_alive_on_handler_klass_exceptions = false
|
27
|
+
c.logger = Logger.new(log_data)
|
28
|
+
c.payload_logging = :error
|
15
29
|
end
|
16
30
|
end
|
17
31
|
|
@@ -29,25 +43,45 @@ describe "receivers with unhandled errors", :integration do
|
|
29
43
|
end
|
30
44
|
|
31
45
|
it "an error in one receiver doesn't prevent others from getting messages" do
|
32
|
-
Pwwka::Transmitter.send_message!(
|
33
|
-
"pwwka.testing.foo")
|
46
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
34
47
|
allow_receivers_to_process_queues
|
35
48
|
|
36
49
|
expect(WellBehavedReceiver.messages_received.size).to eq(1)
|
37
50
|
expect(ExceptionThrowingReceiver.messages_received.size).to eq(1)
|
38
51
|
end
|
52
|
+
|
53
|
+
it "logs the payload in the error in the log" do
|
54
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
55
|
+
allow_receivers_to_process_queues
|
56
|
+
expect(log_data.string).to match(/ERROR.*error processing message.*#{Regexp.escape(payload.inspect)}/i)
|
57
|
+
end
|
58
|
+
|
39
59
|
it "crashes the receiver that received an error" do
|
40
|
-
Pwwka::Transmitter.send_message!(
|
41
|
-
"pwwka.testing.foo")
|
60
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
42
61
|
allow_receivers_to_process_queues
|
43
62
|
|
44
63
|
expect(@testing_setup.threads[ExceptionThrowingReceiver].alive?).to eq(false)
|
45
64
|
end
|
46
|
-
|
47
|
-
|
65
|
+
|
66
|
+
it "does not crash the receiver on a borked payload, but doesn't call handlers either" do
|
67
|
+
Pwwka.configure do |c|
|
68
|
+
c.requeue_on_error = true
|
69
|
+
end
|
70
|
+
Pwwka::Transmitter.send_message!(EvilPayload.new,
|
48
71
|
"pwwka.testing.foo")
|
49
72
|
allow_receivers_to_process_queues
|
50
73
|
|
74
|
+
expect(@testing_setup.threads[ExceptionThrowingReceiver].alive?).to eq(true)
|
75
|
+
expect(@testing_setup.threads[WellBehavedReceiver].alive?).to eq(true)
|
76
|
+
expect(@testing_setup.threads[IntermittentErrorReceiver].alive?).to eq(true)
|
77
|
+
expect(WellBehavedReceiver.messages_received.size).to eq(0)
|
78
|
+
expect(ExceptionThrowingReceiver.messages_received.size).to eq(0)
|
79
|
+
end
|
80
|
+
|
81
|
+
it "does not crash the receiver that successfully processed a message" do
|
82
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
83
|
+
allow_receivers_to_process_queues
|
84
|
+
|
51
85
|
expect(@testing_setup.threads[WellBehavedReceiver].alive?).to eq(true)
|
52
86
|
end
|
53
87
|
|
@@ -55,8 +89,7 @@ describe "receivers with unhandled errors", :integration do
|
|
55
89
|
Pwwka.configure do |c|
|
56
90
|
c.requeue_on_error = true
|
57
91
|
end
|
58
|
-
Pwwka::Transmitter.send_message!(
|
59
|
-
"pwwka.testing.foo")
|
92
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
60
93
|
allow_receivers_to_process_queues
|
61
94
|
|
62
95
|
expect(@testing_setup.threads[IntermittentErrorReceiver].alive?).to eq(false)
|
@@ -70,17 +103,21 @@ describe "receivers with unhandled errors", :integration do
|
|
70
103
|
ExceptionThrowingReceiver.reset!
|
71
104
|
IntermittentErrorReceiver.reset!
|
72
105
|
ExceptionThrowingReceiverWithErrorHook.reset!
|
73
|
-
end
|
74
|
-
it "does not crash the receiver that received an error" do
|
75
106
|
Pwwka.configure do |c|
|
76
107
|
c.keep_alive_on_handler_klass_exceptions = true
|
77
108
|
end
|
78
|
-
|
79
|
-
|
109
|
+
end
|
110
|
+
it "does not crash the receiver that received an error" do
|
111
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
80
112
|
allow_receivers_to_process_queues
|
81
113
|
|
82
114
|
expect(@testing_setup.threads[ExceptionThrowingReceiver].alive?).to eq(true)
|
83
115
|
end
|
116
|
+
it "logs the payload in the error in the log" do
|
117
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
118
|
+
allow_receivers_to_process_queues
|
119
|
+
expect(log_data.string).to match(/ERROR.*error processing message.*#{Regexp.escape(payload.inspect)}/i)
|
120
|
+
end
|
84
121
|
end
|
85
122
|
|
86
123
|
context "configured to requeue failed messages" do
|
@@ -90,14 +127,13 @@ describe "receivers with unhandled errors", :integration do
|
|
90
127
|
ExceptionThrowingReceiver.reset!
|
91
128
|
IntermittentErrorReceiver.reset!
|
92
129
|
ExceptionThrowingReceiverWithErrorHook.reset!
|
93
|
-
end
|
94
|
-
it "requeues the message exactly once" do
|
95
130
|
Pwwka.configure do |c|
|
96
131
|
c.requeue_on_error = true
|
97
132
|
c.keep_alive_on_handler_klass_exceptions = true # only so we can check that the requeued message got sent; otherwise the receiver crashes and we can't test that
|
98
133
|
end
|
99
|
-
|
100
|
-
|
134
|
+
end
|
135
|
+
it "requeues the message exactly once" do
|
136
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
101
137
|
allow_receivers_to_process_queues
|
102
138
|
|
103
139
|
expect(WellBehavedReceiver.messages_received.size).to eq(1)
|
@@ -105,6 +141,11 @@ describe "receivers with unhandled errors", :integration do
|
|
105
141
|
expect(ExceptionThrowingReceiver.messages_received[1][0].redelivered).to eq(true)
|
106
142
|
expect(ExceptionThrowingReceiver.messages_received[1][2]).to eq(ExceptionThrowingReceiver.messages_received[0][2])
|
107
143
|
end
|
144
|
+
it "logs the payload in the error in the log" do
|
145
|
+
Pwwka::Transmitter.send_message!(payload, "pwwka.testing.foo")
|
146
|
+
allow_receivers_to_process_queues
|
147
|
+
expect(log_data.string).to match(/ERROR.*error processing message.*#{Regexp.escape(payload.inspect)}/i)
|
148
|
+
end
|
108
149
|
end
|
109
150
|
|
110
151
|
context "handler with a custom error handler that ignores the exception" do
|
@@ -90,14 +90,14 @@ describe Pwwka::Configuration do
|
|
90
90
|
it "is NackAndRequeueOnce" do
|
91
91
|
configuration.requeue_on_error = true
|
92
92
|
configuration.keep_alive_on_handler_klass_exceptions = true
|
93
|
-
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::NackAndRequeueOnce])
|
93
|
+
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::IgnorePayloadFormatErrors,Pwwka::ErrorHandlers::NackAndRequeueOnce])
|
94
94
|
end
|
95
95
|
end
|
96
96
|
context "when not keep_alive_on_handler_klass_exceptions" do
|
97
97
|
it "is NackAndRequeueOnce,Crash" do
|
98
98
|
configuration.requeue_on_error = true
|
99
99
|
configuration.keep_alive_on_handler_klass_exceptions = false
|
100
|
-
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::NackAndRequeueOnce,Pwwka::ErrorHandlers::Crash])
|
100
|
+
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::IgnorePayloadFormatErrors,Pwwka::ErrorHandlers::NackAndRequeueOnce,Pwwka::ErrorHandlers::Crash])
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
@@ -106,14 +106,14 @@ describe Pwwka::Configuration do
|
|
106
106
|
it "is NackAndIgnore" do
|
107
107
|
configuration.requeue_on_error = false
|
108
108
|
configuration.keep_alive_on_handler_klass_exceptions = true
|
109
|
-
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::NackAndIgnore])
|
109
|
+
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::IgnorePayloadFormatErrors,Pwwka::ErrorHandlers::NackAndIgnore])
|
110
110
|
end
|
111
111
|
end
|
112
112
|
context "when not keep_alive_on_handler_klass_exceptions" do
|
113
113
|
it "is NackAndIgnore,Crash" do
|
114
114
|
configuration.requeue_on_error = false
|
115
115
|
configuration.keep_alive_on_handler_klass_exceptions = false
|
116
|
-
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::NackAndIgnore,Pwwka::ErrorHandlers::Crash])
|
116
|
+
expect(configuration.error_handling_chain).to eq([Pwwka::ErrorHandlers::IgnorePayloadFormatErrors,Pwwka::ErrorHandlers::NackAndIgnore,Pwwka::ErrorHandlers::Crash])
|
117
117
|
end
|
118
118
|
end
|
119
119
|
end
|
data/spec/unit/logging_spec.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pwwka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Stitch Fix Engineering
|
@@ -15,7 +15,7 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date: 2017-10-
|
18
|
+
date: 2017-10-26 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: bunny
|
@@ -210,6 +210,7 @@ files:
|
|
210
210
|
- lib/pwwka/error_handlers/base_error_handler.rb
|
211
211
|
- lib/pwwka/error_handlers/chain.rb
|
212
212
|
- lib/pwwka/error_handlers/crash.rb
|
213
|
+
- lib/pwwka/error_handlers/ignore_payload_format_errors.rb
|
213
214
|
- lib/pwwka/error_handlers/nack_and_ignore.rb
|
214
215
|
- lib/pwwka/error_handlers/nack_and_requeue_once.rb
|
215
216
|
- lib/pwwka/handling.rb
|
@@ -265,7 +266,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
265
266
|
version: '0'
|
266
267
|
requirements: []
|
267
268
|
rubyforge_project:
|
268
|
-
rubygems_version: 2.6.
|
269
|
+
rubygems_version: 2.6.13
|
269
270
|
signing_key:
|
270
271
|
specification_version: 4
|
271
272
|
summary: Send and receive messages via RabbitMQ
|