action_subscriber 5.0.3.pre1-java → 5.1.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +6 -1
- data/action_subscriber.gemspec +1 -0
- data/lib/action_subscriber/bunny/subscriber.rb +1 -0
- data/lib/action_subscriber/dsl.rb +2 -44
- data/lib/action_subscriber/march_hare/subscriber.rb +1 -0
- data/lib/action_subscriber/middleware.rb +19 -3
- data/lib/action_subscriber/middleware/active_record/connection_management.rb +1 -1
- data/lib/action_subscriber/middleware/decoder.rb +1 -1
- data/lib/action_subscriber/middleware/env.rb +40 -4
- data/lib/action_subscriber/middleware/error_handler.rb +6 -4
- data/lib/action_subscriber/middleware/router.rb +22 -3
- data/lib/action_subscriber/railtie.rb +2 -2
- data/lib/action_subscriber/route_set.rb +16 -13
- data/lib/action_subscriber/rspec.rb +5 -0
- data/lib/action_subscriber/version.rb +1 -1
- data/spec/integration/manual_acknowledgement_spec.rb +6 -4
- data/spec/lib/action_subscriber/middleware/error_handler_spec.rb +23 -5
- metadata +18 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83a060130b450c10189a3016180bb83c106ce9a09e22a3ea13aab674552117e7
|
4
|
+
data.tar.gz: e5da3d9bfa655d51abb1a290db3d2ca9a8e9c821a5fd2fa9db1c3346cf14c6d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e57c7ba81153c42043c3b7ca8e4ccc1a83a2d8d80c5e72e867bfbae0fcefb00c67f200ba6c0c7a714353826d2df69f39baaee90727c65a5589ce1a9a9fd00221
|
7
|
+
data.tar.gz: 9b46cc26440fc1309636adf6ca728c8577f085298022359523e9f20a6264ef902335e626a9f2f0fcf4348aa2c5d75557aff2d1cf4ba1abfefc5e3db8ebe448f7
|
data/README.md
CHANGED
@@ -160,7 +160,7 @@ This also allows the broker to send messages as quickly as it wants down to your
|
|
160
160
|
|
161
161
|
### manual_acknowledgement!
|
162
162
|
|
163
|
-
This mode leaves it up to the subscriber to handle acknowledging or rejecting messages. In your subscriber you can just call <code>acknowledge</code> or <code>
|
163
|
+
This mode leaves it up to the subscriber to handle acknowledging or rejecting messages. In your subscriber you can just call <code>acknowledge</code>, <code>reject</code>, or <code>nack</code>.
|
164
164
|
|
165
165
|
### at_most_once!
|
166
166
|
|
@@ -172,6 +172,11 @@ Rabbit is told to expect message acknowledgements, but sending the acknowledgeme
|
|
172
172
|
We send the acknowledgement right after calling your subscriber.
|
173
173
|
If an error is raised your message will be retried on a sent back to rabbitmq and retried on an exponential backoff schedule.
|
174
174
|
|
175
|
+
### safe_nack
|
176
|
+
If you turn on acknowledgements and a message is not acknowledged by your code manually or using one of the filters above the `ErrorHandler` middleware
|
177
|
+
which wraps the entire block with call <code>nack</code> this is a last resort so the connection does not get backed up in cases of unexpected or
|
178
|
+
unhandled errors.
|
179
|
+
|
175
180
|
### redeliver
|
176
181
|
|
177
182
|
A message can be sent to "redeliver" with `::ActionSubscriber::MessageRetry.redeliver_message_with_backoff` or the DSL method `redeliver` and optionally
|
data/action_subscriber.gemspec
CHANGED
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
|
|
33
33
|
spec.add_development_dependency "active_publisher", "~> 0.1.5"
|
34
34
|
spec.add_development_dependency "activerecord", ">= 3.2"
|
35
35
|
spec.add_development_dependency "bundler", ">= 1.6"
|
36
|
+
spec.add_development_dependency "pry-coolline"
|
36
37
|
spec.add_development_dependency "pry-nav"
|
37
38
|
spec.add_development_dependency "rabbitmq_http_api_client", "~> 1.2.0"
|
38
39
|
spec.add_development_dependency "rspec", "~> 3.0"
|
@@ -44,6 +44,7 @@ module ActionSubscriber
|
|
44
44
|
:message_id => properties.message_id,
|
45
45
|
:routing_key => delivery_info.routing_key,
|
46
46
|
:queue => queue.name,
|
47
|
+
:uses_acknowledgements => route.acknowledgements?,
|
47
48
|
}
|
48
49
|
env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
|
49
50
|
run_env(env, threadpool)
|
@@ -9,10 +9,9 @@ module ActionSubscriber
|
|
9
9
|
!!@_at_least_once
|
10
10
|
end
|
11
11
|
|
12
|
-
def at_most_once!
|
12
|
+
def at_most_once!
|
13
13
|
@_acknowledge_messages = true
|
14
14
|
@_at_most_once = true
|
15
|
-
@_ack_every_n_messages = ack_every_n_messages
|
16
15
|
end
|
17
16
|
|
18
17
|
def at_most_once?
|
@@ -55,10 +54,6 @@ module ActionSubscriber
|
|
55
54
|
!!@_manual_acknowedgement
|
56
55
|
end
|
57
56
|
|
58
|
-
def ack_every_n_messages
|
59
|
-
@_ack_every_n_messages || 1
|
60
|
-
end
|
61
|
-
|
62
57
|
def no_acknowledgement!
|
63
58
|
@_acknowledge_messages = false
|
64
59
|
end
|
@@ -136,41 +131,6 @@ module ActionSubscriber
|
|
136
131
|
end
|
137
132
|
end
|
138
133
|
|
139
|
-
def _run_action_at_most_once_multiple_with_filters(env, action)
|
140
|
-
processed_acknowledgement = false
|
141
|
-
rejected_message = false
|
142
|
-
if env.delivery_tag % ack_every_n_messages == 0 # tags are monotonically increasing integers
|
143
|
-
processed_acknowledgement = env.acknowledge(true)
|
144
|
-
else
|
145
|
-
processed_acknowledgement = true # we are not acknowledging on this message and will wait for the offset to acknowledge
|
146
|
-
end
|
147
|
-
|
148
|
-
_run_action_with_filters(env, action)
|
149
|
-
ensure
|
150
|
-
rejected_message = env.reject if !processed_acknowledgement
|
151
|
-
|
152
|
-
if !rejected_message && !processed_acknowledgement
|
153
|
-
$stdout << <<-UNREJECTABLE
|
154
|
-
CANNOT ACKNOWLEDGE OR REJECT THE MESSAGE
|
155
|
-
|
156
|
-
This is a exceptional state for ActionSubscriber to enter and puts the current
|
157
|
-
Process in the position of "I can't get new work from RabbitMQ, but also
|
158
|
-
can't acknowledge or reject the work that I currently have" ... While rare
|
159
|
-
this state can happen.
|
160
|
-
|
161
|
-
Instead of continuing to try to process the message ActionSubscriber is
|
162
|
-
sending a Kill signal to the current running process to gracefully shutdown
|
163
|
-
so that the RabbitMQ server will purge any outstanding acknowledgements. If
|
164
|
-
you are running a process monitoring tool (like Upstart) the Subscriber
|
165
|
-
process will be restarted and be able to take on new work.
|
166
|
-
|
167
|
-
** Running a process monitoring tool like Upstart is recommended for this reason **
|
168
|
-
UNREJECTABLE
|
169
|
-
|
170
|
-
Process.kill(:TERM, Process.pid)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
134
|
def _run_action_at_least_once_with_filters(env, action)
|
175
135
|
processed_acknowledgement = false
|
176
136
|
rejected_message = false
|
@@ -212,10 +172,8 @@ module ActionSubscriber
|
|
212
172
|
case
|
213
173
|
when at_least_once?
|
214
174
|
_run_action_at_least_once_with_filters(env, action)
|
215
|
-
when at_most_once?
|
175
|
+
when at_most_once?
|
216
176
|
_run_action_at_most_once_with_filters(env, action)
|
217
|
-
when at_most_once? && ack_every_n_messages > 1 # Acknowledging messages in offset groups (every 10 messages or whatever the offset is)
|
218
|
-
_run_action_at_most_once_multiple_with_filters(env, action)
|
219
177
|
else
|
220
178
|
_run_action_with_filters(env, action)
|
221
179
|
end
|
@@ -42,6 +42,7 @@ module ActionSubscriber
|
|
42
42
|
:message_id => metadata.message_id,
|
43
43
|
:routing_key => metadata.routing_key,
|
44
44
|
:queue => queue.name,
|
45
|
+
:uses_acknowledgements => route.acknowledgements?,
|
45
46
|
}
|
46
47
|
env = ::ActionSubscriber::Middleware::Env.new(route.subscriber, encoded_payload, properties)
|
47
48
|
run_env(env, threadpool)
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "action_subscriber/logging"
|
1
2
|
require "action_subscriber/middleware/decoder"
|
2
3
|
require "action_subscriber/middleware/env"
|
3
4
|
require "action_subscriber/middleware/error_handler"
|
@@ -6,11 +7,26 @@ require "action_subscriber/middleware/runner"
|
|
6
7
|
|
7
8
|
module ActionSubscriber
|
8
9
|
module Middleware
|
10
|
+
|
11
|
+
class Builder < ::Middleware::Builder
|
12
|
+
include ::ActionSubscriber::Logging
|
13
|
+
|
14
|
+
def print_middleware_stack
|
15
|
+
logger.info "Middlewares ["
|
16
|
+
|
17
|
+
stack.each do |middleware|
|
18
|
+
logger.info "#{middleware}"
|
19
|
+
end
|
20
|
+
|
21
|
+
logger.info "]"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
9
25
|
def self.initialize_stack
|
10
|
-
builder = ::Middleware::Builder.new(:runner_class => ::ActionSubscriber::Middleware::Runner)
|
26
|
+
builder = ::ActionSubscriber::Middleware::Builder.new(:runner_class => ::ActionSubscriber::Middleware::Runner)
|
11
27
|
|
12
|
-
builder.use ErrorHandler
|
13
|
-
builder.use Decoder
|
28
|
+
builder.use ::ActionSubscriber::Middleware::ErrorHandler
|
29
|
+
builder.use ::ActionSubscriber::Middleware::Decoder
|
14
30
|
|
15
31
|
builder
|
16
32
|
end
|
@@ -7,7 +7,6 @@ module ActionSubscriber
|
|
7
7
|
|
8
8
|
attr_reader :action,
|
9
9
|
:content_type,
|
10
|
-
:delivery_tag,
|
11
10
|
:encoded_payload,
|
12
11
|
:exchange,
|
13
12
|
:headers,
|
@@ -34,26 +33,54 @@ module ActionSubscriber
|
|
34
33
|
@delivery_tag = properties.fetch(:delivery_tag)
|
35
34
|
@encoded_payload = encoded_payload
|
36
35
|
@exchange = properties.fetch(:exchange)
|
37
|
-
@
|
38
|
-
@
|
36
|
+
@has_been_acked = false
|
37
|
+
@has_been_nacked = false
|
38
|
+
@has_been_rejected = false
|
39
|
+
@headers = properties.fetch(:headers, {})
|
40
|
+
@message_id = properties.fetch(:message_id, ::SecureRandom.hex(3))
|
39
41
|
@queue = properties.fetch(:queue)
|
40
42
|
@routing_key = properties.fetch(:routing_key)
|
41
43
|
@subscriber = subscriber
|
44
|
+
@uses_acknowledgements = properties.fetch(:uses_acknowledgements, false)
|
42
45
|
end
|
43
46
|
|
44
|
-
def acknowledge
|
47
|
+
def acknowledge
|
45
48
|
fail ::RuntimeError, "you can't acknowledge messages under the polling API" unless @channel
|
49
|
+
acknowledge_multiple_messages = false
|
50
|
+
@has_been_acked = true
|
46
51
|
@channel.ack(@delivery_tag, acknowledge_multiple_messages)
|
47
52
|
true
|
48
53
|
end
|
49
54
|
|
55
|
+
def nack
|
56
|
+
fail ::RuntimeError, "you can't acknowledge messages under the polling API" unless @channel
|
57
|
+
nack_multiple_messages = false
|
58
|
+
requeue_message = true
|
59
|
+
@has_been_nacked = true
|
60
|
+
@channel.nack(@delivery_tag, nack_multiple_messages, requeue_message)
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
50
64
|
def reject
|
51
65
|
fail ::RuntimeError, "you can't acknowledge messages under the polling API" unless @channel
|
52
66
|
requeue_message = true
|
67
|
+
@has_been_rejected = true
|
53
68
|
@channel.reject(@delivery_tag, requeue_message)
|
54
69
|
true
|
55
70
|
end
|
56
71
|
|
72
|
+
def safe_acknowledge
|
73
|
+
acknowledge if uses_acknowledgements? && @channel && !has_used_delivery_tag?
|
74
|
+
end
|
75
|
+
|
76
|
+
def safe_nack
|
77
|
+
nack if uses_acknowledgements? && @channel && !has_used_delivery_tag?
|
78
|
+
end
|
79
|
+
|
80
|
+
def safe_reject
|
81
|
+
reject if uses_acknowledgements? && @channel && !has_used_delivery_tag?
|
82
|
+
end
|
83
|
+
|
57
84
|
def to_hash
|
58
85
|
{
|
59
86
|
:action => action,
|
@@ -65,6 +92,15 @@ module ActionSubscriber
|
|
65
92
|
end
|
66
93
|
alias_method :to_h, :to_hash
|
67
94
|
|
95
|
+
private
|
96
|
+
|
97
|
+
def has_used_delivery_tag?
|
98
|
+
@has_been_acked || @has_been_nacked || @has_been_rejected
|
99
|
+
end
|
100
|
+
|
101
|
+
def uses_acknowledgements?
|
102
|
+
@uses_acknowledgements
|
103
|
+
end
|
68
104
|
end
|
69
105
|
end
|
70
106
|
end
|
@@ -9,8 +9,8 @@ module ActionSubscriber
|
|
9
9
|
|
10
10
|
def call(env)
|
11
11
|
@app.call(env)
|
12
|
-
rescue => error
|
13
|
-
logger.error "FAILED #{env.message_id}"
|
12
|
+
rescue Exception => error # make sure we capture any exception from the top of the hierarchy
|
13
|
+
logger.error { "FAILED #{env.message_id}" }
|
14
14
|
|
15
15
|
# There is more to this rescue than meets the eye. MarchHare's java library will rescue errors
|
16
16
|
# and attempt to close the channel with its default exception handler. To avoid this, we will
|
@@ -18,9 +18,11 @@ module ActionSubscriber
|
|
18
18
|
# it should not re-raise. As a bonus, not killing these threads is better for your runtime :).
|
19
19
|
begin
|
20
20
|
::ActionSubscriber.configuration.error_handler.call(error, env.to_h)
|
21
|
-
rescue =>
|
22
|
-
logger.error "ActionSubscriber error handler raised error, but should never raise. Error: #{
|
21
|
+
rescue Exception => inner_error
|
22
|
+
logger.error { "ActionSubscriber error handler raised error, but should never raise. Error: #{inner_error}" }
|
23
23
|
end
|
24
|
+
ensure
|
25
|
+
env.safe_nack # Make sure we attempt to `nack` a message that did not get processed if something fails
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module ActionSubscriber
|
2
2
|
module Middleware
|
3
3
|
class Router
|
4
|
+
INSTRUMENT_KEY = "process_event.action_subscriber".freeze
|
4
5
|
include ::ActionSubscriber::Logging
|
5
6
|
|
6
7
|
def initialize(app)
|
@@ -8,9 +9,27 @@ module ActionSubscriber
|
|
8
9
|
end
|
9
10
|
|
10
11
|
def call(env)
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
action = env.action
|
13
|
+
message_id = env.message_id
|
14
|
+
queue = env.queue
|
15
|
+
routing_key = env.routing_key
|
16
|
+
subscriber = env.subscriber
|
17
|
+
|
18
|
+
logger.info { "START #{message_id} #{subscriber}##{action}" }
|
19
|
+
|
20
|
+
instrument_call(subscriber, routing_key, queue) do
|
21
|
+
subscriber.run_action_with_filters(env, action)
|
22
|
+
end
|
23
|
+
|
24
|
+
logger.info { "FINISHED #{message_id}" }
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def instrument_call(subscriber, routing_key, queue)
|
30
|
+
::ActiveSupport::Notifications.instrument INSTRUMENT_KEY, :subscriber => subscriber.to_s, :routing_key => routing_key, :queue => queue do
|
31
|
+
yield
|
32
|
+
end
|
14
33
|
end
|
15
34
|
end
|
16
35
|
end
|
@@ -6,8 +6,8 @@ module ActionSubscriber
|
|
6
6
|
require "action_subscriber/middleware/active_record/connection_management"
|
7
7
|
require "action_subscriber/middleware/active_record/query_cache"
|
8
8
|
|
9
|
-
::ActionSubscriber.config.middleware.
|
10
|
-
::ActionSubscriber.config.middleware.
|
9
|
+
::ActionSubscriber.config.middleware.insert_after ::ActionSubscriber::Middleware::Decoder, ::ActionSubscriber::Middleware::ActiveRecord::ConnectionManagement
|
10
|
+
::ActionSubscriber.config.middleware.insert_after ::ActionSubscriber::Middleware::ActiveRecord::ConnectionManagement, ::ActionSubscriber::Middleware::ActiveRecord::QueryCache
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -12,7 +12,12 @@ module ActionSubscriber
|
|
12
12
|
@routes = routes
|
13
13
|
end
|
14
14
|
|
15
|
+
def print_middleware_stack
|
16
|
+
::ActionSubscriber.config.middleware.print_middleware_stack
|
17
|
+
end
|
18
|
+
|
15
19
|
def print_subscriptions
|
20
|
+
print_middleware_stack
|
16
21
|
routes.group_by(&:subscriber).each do |subscriber, routes|
|
17
22
|
logger.info subscriber.name
|
18
23
|
routes.each do |route|
|
@@ -23,11 +28,6 @@ module ActionSubscriber
|
|
23
28
|
logger.info " -- queue: #{route.queue}"
|
24
29
|
logger.info " -- routing_key: #{route.routing_key}"
|
25
30
|
logger.info " -- prefetch: #{route.prefetch}"
|
26
|
-
if subscriber.at_most_once? && (route.prefetch < subscriber.ack_every_n_messages || subscriber.ack_every_n_messages <= 0)
|
27
|
-
# https://www.rabbitmq.com/blog/2011/09/24/sizing-your-rabbits/
|
28
|
-
logger.error "ERROR Subscriber has ack_every_n_messages as #{subscriber.ack_every_n_messages} and route has prefetch as #{route.prefetch}"
|
29
|
-
fail "prefetch < ack_every_n_messages, deadlock will occur"
|
30
|
-
end
|
31
31
|
if route.acknowledgements != subscriber.acknowledge_messages?
|
32
32
|
logger.error "WARNING subscriber has acknowledgements as #{subscriber.acknowledge_messages?} and route has acknowledgements as #{route.acknowledgements}"
|
33
33
|
end
|
@@ -44,15 +44,20 @@ module ActionSubscriber
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def wait_to_finish_with_timeout(timeout)
|
47
|
+
finisher_threads = []
|
48
|
+
|
47
49
|
::ActionSubscriber::ThreadPools.threadpools.map do |name, threadpool|
|
48
50
|
logger.info " -- Threadpool #{name} (queued: #{threadpool.queue_length})"
|
49
|
-
::Thread.new do
|
50
|
-
completed =
|
51
|
+
finisher_threads << ::Thread.new(threadpool, timeout, name) do |internal_pool, internal_timeout, internal_name|
|
52
|
+
completed = internal_pool.wait_for_termination(internal_timeout)
|
53
|
+
|
51
54
|
unless completed
|
52
|
-
logger.error " -- FAILED #{
|
55
|
+
logger.error " -- FAILED #{internal_name} did not finish shutting down within #{internal_timeout}sec"
|
53
56
|
end
|
54
57
|
end
|
55
|
-
end
|
58
|
+
end
|
59
|
+
|
60
|
+
finisher_threads.each(&:join)
|
56
61
|
end
|
57
62
|
|
58
63
|
private
|
@@ -63,10 +68,8 @@ module ActionSubscriber
|
|
63
68
|
|
64
69
|
def run_env(env, threadpool)
|
65
70
|
logger.info "RECEIVED #{env.message_id} from #{env.queue}"
|
66
|
-
|
67
|
-
|
68
|
-
::ActionSubscriber.config.middleware.call(env)
|
69
|
-
end
|
71
|
+
threadpool << lambda do
|
72
|
+
::ActionSubscriber.config.middleware.call(env)
|
70
73
|
end
|
71
74
|
end
|
72
75
|
end
|
@@ -7,6 +7,10 @@ module ActionSubscriber
|
|
7
7
|
true
|
8
8
|
end
|
9
9
|
|
10
|
+
def nack(delivery_tag, acknowledge_multiple, requeue_message)
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
10
14
|
def reject(delivery_tag, requeue_message)
|
11
15
|
true
|
12
16
|
end
|
@@ -22,6 +26,7 @@ module ActionSubscriber
|
|
22
26
|
:message_id => "MSG-123",
|
23
27
|
:routing_key => "amigo.user.created",
|
24
28
|
:queue => "test.amigo.user.created",
|
29
|
+
:uses_acknoledgements => false,
|
25
30
|
}.freeze
|
26
31
|
|
27
32
|
# Create a new subscriber instance. Available options are:
|
@@ -3,8 +3,10 @@ class BaconSubscriber < ActionSubscriber::Base
|
|
3
3
|
|
4
4
|
def served
|
5
5
|
$messages << "#{payload}::#{$messages.size}"
|
6
|
-
if $messages.size >
|
6
|
+
if $messages.size > 3
|
7
7
|
acknowledge
|
8
|
+
elsif $messages.size > 2
|
9
|
+
nack
|
8
10
|
else
|
9
11
|
reject
|
10
12
|
end
|
@@ -20,12 +22,12 @@ describe "Manual Message Acknowledgment", :integration => true do
|
|
20
22
|
end
|
21
23
|
let(:subscriber) { BaconSubscriber }
|
22
24
|
|
23
|
-
it "retries rejected messages and stops retrying acknowledged messages" do
|
25
|
+
it "retries rejected/nacked messages and stops retrying acknowledged messages" do
|
24
26
|
::ActionSubscriber.start_subscribers!
|
25
27
|
::ActivePublisher.publish("bacon.served", "BACON!", "events")
|
26
28
|
|
27
|
-
verify_expectation_within(2.
|
28
|
-
expect($messages).to eq(Set.new(["BACON!::0", "BACON!::1", "BACON!::2"]))
|
29
|
+
verify_expectation_within(2.5) do
|
30
|
+
expect($messages).to eq(Set.new(["BACON!::0", "BACON!::1", "BACON!::2", "BACON!::3"]))
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -7,14 +7,32 @@ describe ActionSubscriber::Middleware::ErrorHandler do
|
|
7
7
|
|
8
8
|
it_behaves_like 'an action subscriber middleware'
|
9
9
|
|
10
|
-
let(:
|
10
|
+
let(:load_error) { ::LoadError.new("Boom!") }
|
11
|
+
let(:runtime_error) { ::RuntimeError.new("Boom!") }
|
11
12
|
|
12
13
|
context "when an exception occurs" do
|
13
|
-
|
14
|
+
context "LoadError" do
|
15
|
+
before { allow(app).to receive(:call).and_raise(load_error) }
|
16
|
+
it "calls the exception handler with a LoadError" do
|
17
|
+
handler = ::ActionSubscriber.configuration.error_handler
|
18
|
+
expect(handler).to receive(:call).with(load_error, env.to_h)
|
14
19
|
|
15
|
-
|
16
|
-
|
17
|
-
|
20
|
+
subject.call(env)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "RuntimError" do
|
25
|
+
before { allow(app).to receive(:call).and_raise(runtime_error) }
|
26
|
+
it "calls the exception handler with a RuntimeError" do
|
27
|
+
handler = ::ActionSubscriber.configuration.error_handler
|
28
|
+
expect(handler).to receive(:call).with(runtime_error, env.to_h)
|
29
|
+
|
30
|
+
subject.call(env)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "calls safe_nack after execution" do
|
35
|
+
expect(env).to receive(:safe_nack)
|
18
36
|
|
19
37
|
subject.call(env)
|
20
38
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: action_subscriber
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0
|
4
|
+
version: 5.1.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- Brian Stien
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date:
|
15
|
+
date: 2018-01-26 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
requirement: !ruby/object:Gem::Requirement
|
@@ -126,6 +126,20 @@ dependencies:
|
|
126
126
|
- - ">="
|
127
127
|
- !ruby/object:Gem::Version
|
128
128
|
version: '1.6'
|
129
|
+
- !ruby/object:Gem::Dependency
|
130
|
+
requirement: !ruby/object:Gem::Requirement
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: '0'
|
135
|
+
name: pry-coolline
|
136
|
+
prerelease: false
|
137
|
+
type: :development
|
138
|
+
version_requirements: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
129
143
|
- !ruby/object:Gem::Dependency
|
130
144
|
requirement: !ruby/object:Gem::Requirement
|
131
145
|
requirements:
|
@@ -278,9 +292,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
278
292
|
version: '0'
|
279
293
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
294
|
requirements:
|
281
|
-
- - "
|
295
|
+
- - ">="
|
282
296
|
- !ruby/object:Gem::Version
|
283
|
-
version:
|
297
|
+
version: '0'
|
284
298
|
requirements: []
|
285
299
|
rubyforge_project:
|
286
300
|
rubygems_version: 2.6.11
|