philotic 0.8.1 → 1.0.1
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 +7 -7
- data/.travis.yml +5 -6
- data/README.md +10 -13
- data/examples/creating_named_queues/manually.rb +4 -4
- data/examples/creating_named_queues/with_rake.rb +4 -1
- data/examples/publishing/publish.rb +14 -14
- data/examples/simple_instance.rb +4 -4
- data/examples/simple_singleton.rb +3 -3
- data/examples/subscribing/acks.rb +6 -6
- data/examples/subscribing/anonymous_queue.rb +2 -2
- data/examples/subscribing/consumer.rb +47 -0
- data/examples/subscribing/multiple_named_queues.rb +4 -4
- data/examples/subscribing/named_queue.rb +3 -3
- data/lib/philotic.rb +2 -3
- data/lib/philotic/config.rb +1 -1
- data/lib/philotic/connection.rb +1 -0
- data/lib/philotic/constants.rb +1 -1
- data/lib/philotic/consumer.rb +93 -0
- data/lib/philotic/{dummy_event.rb → dummy_message.rb} +3 -3
- data/lib/philotic/logging.rb +1 -1
- data/lib/philotic/logging/logger.rb +6 -6
- data/lib/philotic/logging/{event.rb → message.rb} +2 -2
- data/lib/philotic/message.rb +146 -0
- data/lib/philotic/publisher.rb +24 -24
- data/lib/philotic/subscriber.rb +9 -12
- data/lib/philotic/version.rb +1 -1
- data/philotic.gemspec +8 -11
- data/philotic_queues.yml.example +8 -8
- data/spec/philotic/connection_spec.rb +2 -0
- data/spec/philotic/consumer_spec.rb +186 -0
- data/spec/philotic/logging/logger_spec.rb +15 -15
- data/spec/philotic/message_spec.rb +147 -0
- data/spec/philotic/publisher_spec.rb +39 -38
- data/spec/philotic/subscriber_spec.rb +6 -3
- metadata +173 -144
- data/lib/philotic/event.rb +0 -100
- data/lib/philotic/routable.rb +0 -98
- data/spec/philotic/event_spec.rb +0 -109
- data/spec/philotic/routable_spec.rb +0 -54
@@ -1,10 +1,10 @@
|
|
1
|
-
require 'philotic/
|
1
|
+
require 'philotic/message'
|
2
2
|
|
3
3
|
module Philotic
|
4
|
-
class
|
4
|
+
class DummyMessage < Philotic::Message
|
5
5
|
attr_payload :subject
|
6
6
|
attr_payload :message
|
7
|
-
attr_routable :
|
7
|
+
attr_routable :hue
|
8
8
|
attr_routable :available
|
9
9
|
end
|
10
10
|
end
|
data/lib/philotic/logging.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
require 'logger'
|
2
|
-
require 'philotic/logging/
|
2
|
+
require 'philotic/logging/message'
|
3
3
|
|
4
4
|
module Philotic
|
5
5
|
module Logging
|
6
6
|
class Logger < ::Logger
|
7
7
|
|
8
|
-
attr_writer :
|
8
|
+
attr_writer :message_class
|
9
9
|
attr_accessor :connection
|
10
10
|
|
11
|
-
def
|
12
|
-
@
|
11
|
+
def message_class
|
12
|
+
@message_class ||= Philotic::Logging::Message
|
13
13
|
end
|
14
14
|
|
15
15
|
def add(severity, message = nil, progname = nil)
|
@@ -28,8 +28,8 @@ module Philotic
|
|
28
28
|
end
|
29
29
|
@logdev.write(format_message(format_severity(severity), Time.now, progname, message))
|
30
30
|
begin
|
31
|
-
|
32
|
-
connection.publish
|
31
|
+
message = message_class.new(severity, message, progname)
|
32
|
+
connection.publish message if connection
|
33
33
|
rescue => e
|
34
34
|
@logdev.write(format_message(format_severity(Logger::ERROR), Time.now, progname, e.message))
|
35
35
|
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'philotic/constants'
|
2
|
+
require 'philotic/singleton'
|
3
|
+
|
4
|
+
module Philotic
|
5
|
+
class Message
|
6
|
+
|
7
|
+
attr_accessor :connection, :publish_error, :delivery_info
|
8
|
+
attr_writer :published
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def attr_routable_accessors
|
12
|
+
@attr_routable_accessors ||= Set.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def attr_payload_accessors
|
16
|
+
@attr_payload_accessors ||= Set.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def attr_routable(*names)
|
20
|
+
attr_routable_accessors.merge(names)
|
21
|
+
attr_accessor(*names)
|
22
|
+
end
|
23
|
+
|
24
|
+
def attr_payload(*names)
|
25
|
+
attr_payload_accessors.merge(names)
|
26
|
+
attr_accessor(*names)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(routables={}, payloads={}, connection=nil)
|
31
|
+
self.timestamp = Time.now.to_i
|
32
|
+
self.philotic_firehose = true
|
33
|
+
self.connection = connection
|
34
|
+
|
35
|
+
# dynamically insert any passed in routables into both attr_routable
|
36
|
+
# and attr_payload
|
37
|
+
# result: ability to arbitrarily send a easily routable hash
|
38
|
+
# over into the bus
|
39
|
+
_set_routables_or_payloads(:routable, routables)
|
40
|
+
_set_routables_or_payloads(:payload, payloads)
|
41
|
+
|
42
|
+
@published = false
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.inherited(sub_class)
|
46
|
+
sub_class.attr_routable(*Philotic::PHILOTIC_HEADERS)
|
47
|
+
sub_class.attr_routable(*self.attr_routable_accessors.dup)
|
48
|
+
sub_class.attr_payload(*self.attr_payload_accessors.dup)
|
49
|
+
end
|
50
|
+
|
51
|
+
self.inherited(self)
|
52
|
+
|
53
|
+
Philotic::MESSAGE_OPTIONS.each do |message_option|
|
54
|
+
attr_reader message_option
|
55
|
+
define_method :"#{message_option}=" do |val|
|
56
|
+
instance_variable_set(:"@#{message_option}", val)
|
57
|
+
self.metadata[message_option] = val
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def connection
|
62
|
+
@connection ||= Philotic.connection
|
63
|
+
end
|
64
|
+
|
65
|
+
def published?
|
66
|
+
!!@published
|
67
|
+
end
|
68
|
+
|
69
|
+
def publish
|
70
|
+
connection.publish self
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.publish(*args)
|
74
|
+
self.new(*args).publish
|
75
|
+
end
|
76
|
+
|
77
|
+
def delivery_tag
|
78
|
+
delivery_info.try(:delivery_tag)
|
79
|
+
end
|
80
|
+
|
81
|
+
def payload
|
82
|
+
_payload_or_headers(:payload)
|
83
|
+
end
|
84
|
+
|
85
|
+
def headers
|
86
|
+
_payload_or_headers(:routable)
|
87
|
+
end
|
88
|
+
|
89
|
+
def attributes
|
90
|
+
payload.merge headers
|
91
|
+
end
|
92
|
+
|
93
|
+
def metadata
|
94
|
+
@metadata ||= {}
|
95
|
+
end
|
96
|
+
|
97
|
+
def metadata=(options)
|
98
|
+
@metadata ||= {}
|
99
|
+
@metadata.merge! options
|
100
|
+
end
|
101
|
+
|
102
|
+
private
|
103
|
+
|
104
|
+
def _payload_or_headers(payload_or_headers)
|
105
|
+
attribute_hash = {}
|
106
|
+
self.class.send("attr_#{payload_or_headers}_accessors").each do |attr|
|
107
|
+
attr = attr.to_sym
|
108
|
+
attribute_hash[attr] = send(attr)
|
109
|
+
end
|
110
|
+
attribute_hash
|
111
|
+
end
|
112
|
+
|
113
|
+
def _set_routables_or_payloads(type, attrs)
|
114
|
+
attrs.each do |key, value|
|
115
|
+
if self.respond_to?(:"#{key}=")
|
116
|
+
send(:"#{key}=", value)
|
117
|
+
elsif self.class == Philotic::Message
|
118
|
+
_set_message_attribute(type, key, value)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def _set_message_attribute(type, key, value)
|
124
|
+
self.class.send("attr_#{type}_accessors").merge([key])
|
125
|
+
_set_message_attribute_accessor(key, value)
|
126
|
+
end
|
127
|
+
|
128
|
+
def _set_message_attribute_accessor(attr, value)
|
129
|
+
_set_message_attribute_getter(attr)
|
130
|
+
_set_message_attribute_setter(attr)
|
131
|
+
self.send(:"#{attr}=", value)
|
132
|
+
end
|
133
|
+
|
134
|
+
def _set_message_attribute_getter(attr)
|
135
|
+
self.define_singleton_method :"#{attr}" do
|
136
|
+
instance_variable_get(:"@#{attr}")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def _set_message_attribute_setter(attr)
|
141
|
+
self.define_singleton_method :"#{attr}=" do |v|
|
142
|
+
instance_variable_set(:"@#{attr}", v)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
data/lib/philotic/publisher.rb
CHANGED
@@ -4,7 +4,7 @@ module Philotic
|
|
4
4
|
class Publisher
|
5
5
|
|
6
6
|
attr_accessor :connection
|
7
|
-
attr_accessor :
|
7
|
+
attr_accessor :log_message_handler
|
8
8
|
|
9
9
|
def initialize(connection)
|
10
10
|
@connection = connection
|
@@ -18,16 +18,16 @@ module Philotic
|
|
18
18
|
connection.config
|
19
19
|
end
|
20
20
|
|
21
|
-
def publish(
|
22
|
-
|
23
|
-
|
21
|
+
def publish(message)
|
22
|
+
metadata = {headers: message.headers}
|
23
|
+
metadata.merge!(message.metadata) if message.metadata
|
24
24
|
begin
|
25
|
-
|
25
|
+
message.published = _publish(message.payload, metadata)
|
26
26
|
rescue => e
|
27
|
-
|
27
|
+
message.publish_error = e
|
28
28
|
logger.error e.message
|
29
29
|
end
|
30
|
-
|
30
|
+
message
|
31
31
|
end
|
32
32
|
|
33
33
|
def normalize_payload_times(payload)
|
@@ -41,45 +41,45 @@ module Philotic
|
|
41
41
|
end
|
42
42
|
|
43
43
|
private
|
44
|
-
def _publish(payload,
|
44
|
+
def _publish(payload, metadata = {})
|
45
45
|
if config.disable_publish
|
46
|
-
|
46
|
+
log_message_published(:warn, metadata, payload, 'attempted to publish a message when publishing is disabled.')
|
47
47
|
return false
|
48
48
|
end
|
49
49
|
connection.connect!
|
50
50
|
unless connection.connected?
|
51
|
-
|
51
|
+
log_message_published(:error, metadata, payload, 'unable to publish message, not connected to RabbitMQ')
|
52
52
|
return false
|
53
53
|
end
|
54
|
-
|
54
|
+
metadata = merge_metadata(metadata)
|
55
55
|
|
56
56
|
payload = normalize_payload_times(payload)
|
57
57
|
|
58
|
-
connection.exchange.publish(payload.to_json,
|
59
|
-
|
58
|
+
connection.exchange.publish(payload.to_json, metadata)
|
59
|
+
log_message_published(:debug, metadata, payload, 'published message')
|
60
60
|
true
|
61
61
|
end
|
62
62
|
|
63
|
-
def merge_metadata(
|
63
|
+
def merge_metadata(metadata)
|
64
64
|
publish_defaults = {}
|
65
65
|
Philotic::MESSAGE_OPTIONS.each do |key|
|
66
66
|
publish_defaults[key] = config.send(key.to_s)
|
67
67
|
end
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
68
|
+
metadata = publish_defaults.merge metadata
|
69
|
+
metadata[:headers] ||= {}
|
70
|
+
metadata[:headers] = {philotic_firehose: true}.merge(metadata[:headers])
|
71
|
+
metadata
|
72
72
|
end
|
73
73
|
|
74
|
-
def
|
75
|
-
@
|
74
|
+
def on_publish_message(&block)
|
75
|
+
@log_message_handler = block
|
76
76
|
end
|
77
77
|
|
78
|
-
def
|
79
|
-
if @
|
80
|
-
@
|
78
|
+
def log_message_published(severity, metadata, payload, message)
|
79
|
+
if @log_message_handler
|
80
|
+
@log_message_handler.call(severity, metadata, payload, message)
|
81
81
|
else
|
82
|
-
logger.send(severity, "#{message};
|
82
|
+
logger.send(severity, "#{message}; metadata:#{metadata}, payload:#{payload.to_json}")
|
83
83
|
end
|
84
84
|
end
|
85
85
|
end
|
data/lib/philotic/subscriber.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'philotic/constants'
|
2
|
+
require 'philotic/message'
|
2
3
|
|
3
4
|
module Philotic
|
4
5
|
class Subscriber
|
@@ -17,18 +18,14 @@ module Philotic
|
|
17
18
|
connection.config
|
18
19
|
end
|
19
20
|
|
20
|
-
def subscription_callback(
|
21
|
+
def subscription_callback(&block)
|
21
22
|
lambda do |delivery_info, metadata, payload|
|
22
23
|
hash_payload = JSON.parse payload
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
headers: metadata[:headers],
|
27
|
-
delivery_info: delivery_info,
|
28
|
-
attributes: metadata[:headers] ? hash_payload.merge(metadata[:headers]) : hash_payload
|
29
|
-
}
|
25
|
+
message = Philotic::Message.new(metadata[:headers], hash_payload)
|
26
|
+
message.delivery_info = delivery_info
|
30
27
|
|
31
|
-
instance_exec(
|
28
|
+
instance_exec(message, &block)
|
32
29
|
end
|
33
30
|
end
|
34
31
|
|
@@ -40,7 +37,7 @@ module Philotic
|
|
40
37
|
|
41
38
|
queue = initialize_queue(subscription_settings)
|
42
39
|
|
43
|
-
queue.subscribe(subscription_settings[:subscribe_options], &subscription_callback(
|
40
|
+
queue.subscribe(subscription_settings[:subscribe_options], &subscription_callback(&block))
|
44
41
|
|
45
42
|
end
|
46
43
|
|
@@ -53,7 +50,7 @@ module Philotic
|
|
53
50
|
|
54
51
|
def get_subscription_settings(subscription, subscribe_options)
|
55
52
|
|
56
|
-
if
|
53
|
+
if [Symbol, String].include? subscription.class
|
57
54
|
queue_name = subscription
|
58
55
|
subscription = subscribe_options
|
59
56
|
queue_options = Philotic::DEFAULT_NAMED_QUEUE_OPTIONS
|
@@ -79,11 +76,11 @@ module Philotic
|
|
79
76
|
end
|
80
77
|
|
81
78
|
def acknowledge(message, up_to_and_including=false)
|
82
|
-
connection.channel.acknowledge(message
|
79
|
+
connection.channel.acknowledge(message.delivery_tag, up_to_and_including)
|
83
80
|
end
|
84
81
|
|
85
82
|
def reject(message, requeue=true)
|
86
|
-
connection.channel.reject(message
|
83
|
+
connection.channel.reject(message.delivery_tag, requeue)
|
87
84
|
end
|
88
85
|
|
89
86
|
def subscribe_to_any(options = {})
|
data/lib/philotic/version.rb
CHANGED
data/philotic.gemspec
CHANGED
@@ -16,20 +16,17 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Philotic::VERSION
|
17
17
|
gem.licenses = ['MIT']
|
18
18
|
|
19
|
-
|
20
19
|
gem.add_development_dependency 'codeclimate-test-reporter'
|
21
|
-
gem.add_development_dependency 'bundler', '
|
22
|
-
gem.add_development_dependency '
|
23
|
-
gem.add_development_dependency '
|
24
|
-
gem.add_development_dependency '
|
25
|
-
gem.add_development_dependency 'rspec', '
|
26
|
-
gem.add_development_dependency '
|
27
|
-
gem.add_development_dependency 'timecop', '~> 0.7'
|
20
|
+
gem.add_development_dependency 'bundler', '>= 1.6'
|
21
|
+
gem.add_development_dependency 'pry', '>= 0.10'
|
22
|
+
gem.add_development_dependency 'rake', '>= 10.3'
|
23
|
+
gem.add_development_dependency 'rspec', '>= 3.1'
|
24
|
+
gem.add_development_dependency 'rspec-its', '>= 1.1'
|
25
|
+
gem.add_development_dependency 'timecop', '>= 0.7'
|
28
26
|
gem.add_development_dependency 'simplecov'
|
29
27
|
|
30
28
|
gem.add_dependency 'activesupport', '>= 3.2'
|
31
|
-
gem.add_dependency '
|
32
|
-
gem.add_dependency 'awesome_print', '~> 1.2'
|
29
|
+
gem.add_dependency 'awesome_print', '>= 1.2'
|
33
30
|
gem.add_dependency 'bunny', '>= 1.6'
|
34
|
-
gem.add_dependency 'json', '
|
31
|
+
gem.add_dependency 'json', '>= 1.8'
|
35
32
|
end
|
data/philotic_queues.yml.example
CHANGED
@@ -1,19 +1,19 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
available_or_mauve:
|
2
|
+
hue: Mauve
|
3
3
|
available: true
|
4
4
|
x-match: any
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
available_mauve:
|
7
|
+
hue: Mauve
|
8
8
|
available: true
|
9
9
|
x-match: all
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
available_or_fuchsia:
|
12
|
+
hue: Fuchsia
|
13
13
|
available: true
|
14
14
|
x-match: any
|
15
15
|
|
16
|
-
|
17
|
-
|
16
|
+
available_fuchsia:
|
17
|
+
hue: Fuchsia
|
18
18
|
available: true
|
19
19
|
x-match: all
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'philotic/consumer'
|
4
|
+
require 'philotic/connection'
|
5
|
+
require 'philotic/subscriber'
|
6
|
+
|
7
|
+
|
8
|
+
describe Philotic::Consumer do
|
9
|
+
let(:named_queue) { :named_queue }
|
10
|
+
let(:anonymous_subscription) { {
|
11
|
+
header_1: :value_1,
|
12
|
+
header_2: :value_2,
|
13
|
+
header_3: :value_3,
|
14
|
+
} }
|
15
|
+
subject { Class.new Philotic::Consumer }
|
16
|
+
|
17
|
+
describe '.subscribe_to' do
|
18
|
+
it 'sets the class variable @subscription' do
|
19
|
+
|
20
|
+
expect(subject.subscription).not_to be
|
21
|
+
|
22
|
+
subject.subscribe_to named_queue
|
23
|
+
expect(subject.subscription).to eq named_queue
|
24
|
+
|
25
|
+
subject.subscribe_to anonymous_subscription
|
26
|
+
expect(subject.subscription).to eq anonymous_subscription
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe '.ack_messages' do
|
31
|
+
it 'sets the class variable @ack_messages' do
|
32
|
+
expect(subject.ack_messages?).not_to be true
|
33
|
+
subject.ack_messages
|
34
|
+
expect(subject.ack_messages?).to be true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '.exclusive' do
|
39
|
+
it 'sets the class variable @exclusive' do
|
40
|
+
expect(subject).not_to be_exclusive
|
41
|
+
subject.exclusive
|
42
|
+
expect(subject).to be_exclusive
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '.requeueable_errors' do
|
47
|
+
it 'maintains a set of requeueable errors' do
|
48
|
+
expect(subject.requeueable_errors).to be_empty
|
49
|
+
expect(subject.requeueable_errors(RuntimeError).size).to be 1
|
50
|
+
expect(subject.requeueable_errors).to include(RuntimeError)
|
51
|
+
|
52
|
+
expect(subject.requeueable_errors(RuntimeError, NotImplementedError).size).to be 2
|
53
|
+
expect(subject.requeueable_errors).to include(NotImplementedError)
|
54
|
+
|
55
|
+
|
56
|
+
# don't allow dupes
|
57
|
+
expect(subject.requeueable_errors(RuntimeError, NotImplementedError).size).to be 2
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '.rejectable_errors' do
|
63
|
+
it 'maintains a set of rejectable errors' do
|
64
|
+
expect(subject.rejectable_errors).to be_empty
|
65
|
+
expect(subject.rejectable_errors(RuntimeError).size).to be 1
|
66
|
+
expect(subject.rejectable_errors).to include(RuntimeError)
|
67
|
+
|
68
|
+
expect(subject.rejectable_errors(RuntimeError, NotImplementedError).size).to be 2
|
69
|
+
expect(subject.rejectable_errors).to include(NotImplementedError)
|
70
|
+
|
71
|
+
|
72
|
+
# don't allow dupes
|
73
|
+
expect(subject.rejectable_errors(RuntimeError, NotImplementedError).size).to be 2
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe '.subscribe' do
|
79
|
+
let (:connection) { instance_double Philotic::Connection }
|
80
|
+
let (:consumer_instance) { instance_double subject }
|
81
|
+
it 'proxies to, and returns, a new instance' do
|
82
|
+
expect(Philotic).to receive(:connection).and_return(connection)
|
83
|
+
expect(subject).to receive(:new).and_return(consumer_instance)
|
84
|
+
expect(consumer_instance).to receive(:subscribe)
|
85
|
+
|
86
|
+
expect(subject.subscribe).to be consumer_instance
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#subscription_options' do
|
91
|
+
it 'returns a hash with the exclusive and manual_ack options' do
|
92
|
+
expect(subject.subscription_options).to match({manual_ack: false, exclusive: false})
|
93
|
+
|
94
|
+
subject.ack_messages
|
95
|
+
expect(subject.subscription_options).to match({manual_ack: true, exclusive: false})
|
96
|
+
|
97
|
+
subject.exclusive
|
98
|
+
expect(subject.subscription_options).to match({manual_ack: true, exclusive: true})
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#subscribe' do
|
103
|
+
it 'proxies to Philotic::Subscriber#subscribe' do
|
104
|
+
subject.subscribe_to named_queue
|
105
|
+
subject.ack_messages
|
106
|
+
subject.exclusive
|
107
|
+
|
108
|
+
expect_any_instance_of(Philotic::Subscriber).to receive(:subscribe).with(named_queue, manual_ack: true, exclusive: true)
|
109
|
+
|
110
|
+
subject.subscribe
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '#consume' do
|
115
|
+
subject { (Class.new(Philotic::Consumer)).new(nil) }
|
116
|
+
|
117
|
+
it 'raises an error unless the inheriting class redefines it' do
|
118
|
+
expect { subject.consume(nil) }.to raise_error(NotImplementedError)
|
119
|
+
|
120
|
+
subject.define_singleton_method :consume do |message|
|
121
|
+
# no op
|
122
|
+
end
|
123
|
+
|
124
|
+
expect { subject.consume(nil) }.to_not raise_error
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#_consume' do
|
129
|
+
subject { (Class.new(Philotic::Consumer)).new(nil) }
|
130
|
+
let(:message) { instance_double Philotic::Message }
|
131
|
+
|
132
|
+
it 'proxies to #consume' do
|
133
|
+
expect(subject).to receive(:consume).with(message)
|
134
|
+
|
135
|
+
subject.send(:_consume, message)
|
136
|
+
end
|
137
|
+
|
138
|
+
it 'acknowledges messages when @ack_messages is set' do
|
139
|
+
subject.class.ack_messages
|
140
|
+
|
141
|
+
subject.define_singleton_method :consume do |message|
|
142
|
+
# no op
|
143
|
+
end
|
144
|
+
|
145
|
+
expect(subject).to receive(:acknowledge).with(message)
|
146
|
+
|
147
|
+
subject.send(:_consume, message)
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'requeues messages when @ack_messages is set and a requeueable error is thrown' do
|
151
|
+
subject.class.ack_messages
|
152
|
+
subject.class.requeueable_errors(RuntimeError)
|
153
|
+
|
154
|
+
subject.define_singleton_method :consume do |message|
|
155
|
+
raise RuntimeError.new 'oops'
|
156
|
+
end
|
157
|
+
|
158
|
+
expect(subject).to receive(:reject).with(message, true)
|
159
|
+
|
160
|
+
subject.send(:_consume, message)
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'rejects messages when @ack_messages is set and a rejectable error is thrown' do
|
164
|
+
subject.class.ack_messages
|
165
|
+
subject.class.rejectable_errors(RuntimeError)
|
166
|
+
|
167
|
+
subject.define_singleton_method :consume do |message|
|
168
|
+
raise RuntimeError.new 'oops'
|
169
|
+
end
|
170
|
+
|
171
|
+
expect(subject).to receive(:reject).with(message, false)
|
172
|
+
|
173
|
+
subject.send(:_consume, message)
|
174
|
+
end
|
175
|
+
|
176
|
+
it 'raises all non-requeueable and non-rejectable errors' do
|
177
|
+
subject.class.ack_messages
|
178
|
+
|
179
|
+
subject.define_singleton_method :consume do |message|
|
180
|
+
raise RuntimeError.new 'oops'
|
181
|
+
end
|
182
|
+
|
183
|
+
expect {subject.send(:_consume, message)}.to raise_error RuntimeError
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|