eventq 2.0.0.rc1
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 -0
- data/README.md +336 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/eventq/aws.rb +38 -0
- data/lib/eventq/eventq_aws/README.md +53 -0
- data/lib/eventq/eventq_aws/aws_eventq_client.rb +120 -0
- data/lib/eventq/eventq_aws/aws_queue_client.rb +64 -0
- data/lib/eventq/eventq_aws/aws_queue_manager.rb +68 -0
- data/lib/eventq/eventq_aws/aws_queue_worker.rb +168 -0
- data/lib/eventq/eventq_aws/aws_status_checker.rb +25 -0
- data/lib/eventq/eventq_aws/aws_subscription_manager.rb +65 -0
- data/lib/eventq/eventq_aws/jruby/aws_queue_worker.rb +370 -0
- data/lib/eventq/eventq_aws/sns.rb +64 -0
- data/lib/eventq/eventq_aws/sqs.rb +112 -0
- data/lib/eventq/eventq_base/configuration.rb +33 -0
- data/lib/eventq/eventq_base/event_raised_exchange.rb +7 -0
- data/lib/eventq/eventq_base/event_raised_queue.rb +7 -0
- data/lib/eventq/eventq_base/eventq_client_contract.rb +9 -0
- data/lib/eventq/eventq_base/eventq_logger.rb +28 -0
- data/lib/eventq/eventq_base/exceptions/invalid_signature_exception.rb +9 -0
- data/lib/eventq/eventq_base/exceptions/worker_thread_error.rb +10 -0
- data/lib/eventq/eventq_base/exceptions.rb +2 -0
- data/lib/eventq/eventq_base/exchange.rb +5 -0
- data/lib/eventq/eventq_base/message_args.rb +23 -0
- data/lib/eventq/eventq_base/nonce_manager.rb +57 -0
- data/lib/eventq/eventq_base/queue.rb +27 -0
- data/lib/eventq/eventq_base/queue_message.rb +31 -0
- data/lib/eventq/eventq_base/queue_worker_contract.rb +23 -0
- data/lib/eventq/eventq_base/serialization_providers/binary_serialization_provider.rb +15 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/array_writer.rb +20 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/attribute_writer.rb +24 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/class_writer.rb +20 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/date_time_writer.rb +33 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/date_writer.rb +22 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/hash_writer.rb +18 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/rational_writer.rb +20 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/serializer.rb +17 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/time_writer.rb +18 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj/value_writer.rb +16 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj.rb +10 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby/oj_serialization_provider.rb +25 -0
- data/lib/eventq/eventq_base/serialization_providers/jruby.rb +2 -0
- data/lib/eventq/eventq_base/serialization_providers/json_serialization_provider.rb +28 -0
- data/lib/eventq/eventq_base/serialization_providers/oj_serialization_provider.rb +24 -0
- data/lib/eventq/eventq_base/serialization_providers.rb +36 -0
- data/lib/eventq/eventq_base/signature_providers/sha256_signature_provider.rb +31 -0
- data/lib/eventq/eventq_base/signature_providers.rb +44 -0
- data/lib/eventq/eventq_base/subscription_manager_contract.rb +13 -0
- data/lib/eventq/eventq_base/version.rb +3 -0
- data/lib/eventq/eventq_base/worker_id.rb +20 -0
- data/lib/eventq/eventq_rabbitmq/README.md +36 -0
- data/lib/eventq/eventq_rabbitmq/default_queue.rb +12 -0
- data/lib/eventq/eventq_rabbitmq/jruby/rabbitmq_queue_worker.rb +367 -0
- data/lib/eventq/eventq_rabbitmq/rabbitmq_eventq_client.rb +140 -0
- data/lib/eventq/eventq_rabbitmq/rabbitmq_queue_client.rb +54 -0
- data/lib/eventq/eventq_rabbitmq/rabbitmq_queue_manager.rb +104 -0
- data/lib/eventq/eventq_rabbitmq/rabbitmq_queue_worker.rb +168 -0
- data/lib/eventq/eventq_rabbitmq/rabbitmq_status_checker.rb +62 -0
- data/lib/eventq/eventq_rabbitmq/rabbitmq_subscription_manager.rb +54 -0
- data/lib/eventq/queue_worker.rb +241 -0
- data/lib/eventq/rabbitmq.rb +49 -0
- data/lib/eventq/worker_status.rb +64 -0
- data/lib/eventq.rb +25 -0
- metadata +289 -0
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'thread'
|
2
|
+
module EventQ
|
3
|
+
module RabbitMq
|
4
|
+
# Implements a general interface to raise an event
|
5
|
+
# EventQ::Amazon::EventQClient is the sister-class which does the same for AWS
|
6
|
+
class EventQClient
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
|
10
|
+
if options[:client] == nil
|
11
|
+
raise ':client (QueueClient) must be specified.'.freeze
|
12
|
+
end
|
13
|
+
|
14
|
+
@client = options[:client]
|
15
|
+
@queue_manager = QueueManager.new
|
16
|
+
@event_raised_exchange = EventRaisedExchange.new
|
17
|
+
@serialization_manager = EventQ::SerializationProviders::Manager.new
|
18
|
+
@signature_manager = EventQ::SignatureProviders::Manager.new
|
19
|
+
|
20
|
+
# this array is used to record known event types
|
21
|
+
@known_event_types = []
|
22
|
+
|
23
|
+
@connection_pool = ::Queue.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def check_out_connection
|
27
|
+
@connection_pool.pop(true)
|
28
|
+
rescue
|
29
|
+
@client.get_connection
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_in_connection(connection)
|
33
|
+
@connection_pool.push(connection)
|
34
|
+
end
|
35
|
+
|
36
|
+
def registered?(event_type)
|
37
|
+
@known_event_types.include?(event_type)
|
38
|
+
end
|
39
|
+
|
40
|
+
def register_event(event_type)
|
41
|
+
if registered?(event_type)
|
42
|
+
return true
|
43
|
+
end
|
44
|
+
|
45
|
+
@known_event_types << event_type
|
46
|
+
true
|
47
|
+
end
|
48
|
+
|
49
|
+
def publish(topic:, event:, context: {})
|
50
|
+
raise_event(topic, event, context)
|
51
|
+
end
|
52
|
+
|
53
|
+
def raise_event(event_type, event, context = {})
|
54
|
+
register_event(event_type)
|
55
|
+
|
56
|
+
_event_type = EventQ.create_event_type(event_type)
|
57
|
+
|
58
|
+
with_connection do |channel|
|
59
|
+
exchange = @queue_manager.get_exchange(channel, @event_raised_exchange)
|
60
|
+
|
61
|
+
message = serialized_message(event_type, event, context)
|
62
|
+
|
63
|
+
exchange.publish(message, routing_key: _event_type)
|
64
|
+
|
65
|
+
EventQ.logger.debug do
|
66
|
+
"[#{self.class}] - Raised event to Exchange. Routing Key: #{_event_type} | Message: #{message}."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def raise_event_in_queue(event_type, event, queue, delay, context = {})
|
72
|
+
register_event(event_type)
|
73
|
+
|
74
|
+
_event_type = EventQ.create_event_type(event_type)
|
75
|
+
|
76
|
+
with_connection do |channel|
|
77
|
+
exchange = @queue_manager.get_queue_exchange(channel, queue)
|
78
|
+
|
79
|
+
delay_exchange = @queue_manager.get_delay_exchange(channel, queue, delay)
|
80
|
+
|
81
|
+
delay_queue = @queue_manager.create_delay_queue(channel, queue, exchange.name, delay)
|
82
|
+
delay_queue.bind(delay_exchange, routing_key: _event_type)
|
83
|
+
|
84
|
+
_queue_name = EventQ.create_queue_name(queue.name)
|
85
|
+
|
86
|
+
q = channel.queue(_queue_name, durable: @queue_manager.durable)
|
87
|
+
q.bind(exchange, routing_key: _event_type)
|
88
|
+
|
89
|
+
message = serialized_message(event_type, event, context)
|
90
|
+
|
91
|
+
delay_exchange.publish(message, routing_key: _event_type)
|
92
|
+
|
93
|
+
EventQ.logger.debug do
|
94
|
+
"[#{self.class}] - Raised event to Queue: #{_queue_name} | Message: #{message} | Delay: #{delay}."
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def new_message
|
100
|
+
EventQ::QueueMessage.new
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
def with_connection
|
106
|
+
connection = check_out_connection
|
107
|
+
|
108
|
+
begin
|
109
|
+
channel = connection.create_channel
|
110
|
+
|
111
|
+
yield(channel)
|
112
|
+
|
113
|
+
ensure
|
114
|
+
channel&.close if channel.open?
|
115
|
+
check_in_connection(connection)
|
116
|
+
end
|
117
|
+
|
118
|
+
true
|
119
|
+
end
|
120
|
+
|
121
|
+
def serialized_message(event_type, event, context)
|
122
|
+
qm = new_message
|
123
|
+
qm.content = event
|
124
|
+
qm.type = event_type
|
125
|
+
qm.context = context
|
126
|
+
qm.content_type = event.class.to_s
|
127
|
+
|
128
|
+
if EventQ::Configuration.signature_secret != nil
|
129
|
+
provider = @signature_manager.get_provider(EventQ::Configuration.signature_provider)
|
130
|
+
qm.signature = provider.write(message: qm, secret: EventQ::Configuration.signature_secret)
|
131
|
+
end
|
132
|
+
|
133
|
+
serialization_provider = @serialization_manager.get_provider(EventQ::Configuration.serialization_provider)
|
134
|
+
|
135
|
+
serialization_provider.serialize(qm)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module EventQ
|
2
|
+
module RabbitMq
|
3
|
+
class QueueClient
|
4
|
+
|
5
|
+
GUEST = 'guest'.freeze
|
6
|
+
|
7
|
+
def initialize(options = {})
|
8
|
+
|
9
|
+
if options[:endpoint] == nil
|
10
|
+
raise ':endpoint must be specified.'.freeze
|
11
|
+
end
|
12
|
+
|
13
|
+
@endpoint = options[:endpoint]
|
14
|
+
|
15
|
+
@port = Integer(options[:port] || 5672)
|
16
|
+
|
17
|
+
@user = options[:user] || GUEST
|
18
|
+
|
19
|
+
@password = options[:password] || GUEST
|
20
|
+
|
21
|
+
@ssl = options[:ssl] == true || false
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def connection_options
|
26
|
+
{
|
27
|
+
:host => @endpoint,
|
28
|
+
:port => @port,
|
29
|
+
:user => @user,
|
30
|
+
:pass => @password,
|
31
|
+
:ssl => @ssl,
|
32
|
+
:read_timeout => 4,
|
33
|
+
:heartbeat => 8,
|
34
|
+
:continuation_timeout => 5000,
|
35
|
+
:automatically_recover => true,
|
36
|
+
:network_recovery_interval => 1,
|
37
|
+
:recover_from_connection_close => true
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_connection
|
42
|
+
if RUBY_PLATFORM =~ /java/
|
43
|
+
conn = MarchHare.connect(connection_options)
|
44
|
+
else
|
45
|
+
conn = Bunny.new(connection_options)
|
46
|
+
end
|
47
|
+
|
48
|
+
conn.start
|
49
|
+
return conn
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module EventQ
|
2
|
+
module RabbitMq
|
3
|
+
class QueueManager
|
4
|
+
|
5
|
+
X_DEAD_LETTER_EXCHANGE = 'x-dead-letter-exchange'.freeze
|
6
|
+
X_MESSAGE_TTL = 'x-message-ttl'.freeze
|
7
|
+
|
8
|
+
attr_accessor :durable
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@event_raised_exchange = EventQ::EventRaisedExchange.new
|
12
|
+
@durable = true
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_queue(channel, queue)
|
16
|
+
|
17
|
+
_queue_name = EventQ.create_queue_name(queue.name)
|
18
|
+
|
19
|
+
# get/create the queue
|
20
|
+
q = channel.queue(_queue_name, :durable => @durable)
|
21
|
+
|
22
|
+
subscriber_exchange = get_subscriber_exchange(channel, queue)
|
23
|
+
|
24
|
+
if queue.allow_retry
|
25
|
+
retry_exchange = get_retry_exchange(channel, queue)
|
26
|
+
retry_queue = get_retry_queue(channel, queue)
|
27
|
+
retry_queue.bind(retry_exchange)
|
28
|
+
end
|
29
|
+
|
30
|
+
q.bind(subscriber_exchange)
|
31
|
+
|
32
|
+
return q
|
33
|
+
end
|
34
|
+
|
35
|
+
def pop_message(queue:)
|
36
|
+
if RUBY_PLATFORM =~ /java/
|
37
|
+
headers, payload = queue.pop({ :ack => true, :block => true })
|
38
|
+
if headers == nil
|
39
|
+
return [nil,nil]
|
40
|
+
end
|
41
|
+
[headers.delivery_tag, payload]
|
42
|
+
else
|
43
|
+
headers, properties, payload = queue.pop({ :manual_ack => true, :block => true })
|
44
|
+
if headers == nil
|
45
|
+
return [nil,nil]
|
46
|
+
end
|
47
|
+
[headers.delivery_tag, payload]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def get_queue_exchange(channel, queue)
|
52
|
+
_exchange_name = EventQ.create_exchange_name(queue.name)
|
53
|
+
channel.fanout("#{_exchange_name}.ex")
|
54
|
+
end
|
55
|
+
|
56
|
+
def get_retry_exchange(channel, queue)
|
57
|
+
_queue_name = EventQ.create_queue_name(queue.name)
|
58
|
+
return channel.fanout("#{_queue_name}.r.ex")
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_subscriber_exchange(channel, queue)
|
62
|
+
_queue_name = EventQ.create_queue_name(queue.name)
|
63
|
+
return channel.fanout("#{_queue_name}.ex")
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_delay_exchange(channel, queue, delay)
|
67
|
+
_queue_name = EventQ.create_queue_name(queue.name)
|
68
|
+
channel.direct("#{_queue_name}.#{delay}.d.ex")
|
69
|
+
end
|
70
|
+
|
71
|
+
def get_retry_queue(channel, queue)
|
72
|
+
subscriber_exchange = get_subscriber_exchange(channel, queue)
|
73
|
+
|
74
|
+
_queue_name = EventQ.create_queue_name(queue.name)
|
75
|
+
|
76
|
+
if queue.allow_retry_back_off == true
|
77
|
+
|
78
|
+
EventQ.logger.debug { "[#{self.class}] - Requesting retry queue. x-dead-letter-exchange: #{subscriber_exchange.name} | x-message-ttl: #{queue.max_retry_delay}" }
|
79
|
+
|
80
|
+
return channel.queue("#{_queue_name}.r", :durable => @durable, :arguments => { X_DEAD_LETTER_EXCHANGE => subscriber_exchange.name, X_MESSAGE_TTL => queue.max_retry_delay })
|
81
|
+
|
82
|
+
else
|
83
|
+
|
84
|
+
EventQ.logger.debug { "[#{self.class}] - Requesting retry queue. x-dead-letter-exchange: #{subscriber_exchange.name} | x-message-ttl: #{queue.retry_delay}" }
|
85
|
+
|
86
|
+
return channel.queue("#{_queue_name}.r", :durable => @durable, :arguments => { X_DEAD_LETTER_EXCHANGE => subscriber_exchange.name, X_MESSAGE_TTL => queue.retry_delay })
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
def create_delay_queue(channel, queue, dlx_name, delay=0)
|
93
|
+
queue_name = EventQ.create_queue_name(queue.name)
|
94
|
+
channel.queue("#{queue_name}.#{delay}.delay", durable: @durable,
|
95
|
+
arguments: { X_DEAD_LETTER_EXCHANGE => dlx_name, X_MESSAGE_TTL => delay * 1000 })
|
96
|
+
end
|
97
|
+
|
98
|
+
def get_exchange(channel, exchange)
|
99
|
+
_exchange_name = EventQ.create_exchange_name(exchange.name)
|
100
|
+
return channel.direct(_exchange_name, :durable => @durable)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
module EventQ
|
2
|
+
module RabbitMq
|
3
|
+
class QueueWorker
|
4
|
+
include EventQ::WorkerId
|
5
|
+
|
6
|
+
attr_accessor :is_running, :context
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@serialization_provider_manager = EventQ::SerializationProviders::Manager.new
|
10
|
+
@signature_provider_manager = EventQ::SignatureProviders::Manager.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def pre_process(context, options)
|
14
|
+
manager = EventQ::RabbitMq::QueueManager.new
|
15
|
+
manager.durable = options[:durable]
|
16
|
+
options[:manager] = manager
|
17
|
+
|
18
|
+
connection = options[:client].dup.get_connection
|
19
|
+
options[:connection] = connection
|
20
|
+
end
|
21
|
+
|
22
|
+
# This method should not be called iteratively and will sit in a loop
|
23
|
+
# The reason is because this uses a push notification from the subscribe mechanism to trigger the
|
24
|
+
# block and will exit if you do not block.
|
25
|
+
def thread_process_iteration(queue, options, block)
|
26
|
+
manager = options[:manager]
|
27
|
+
channel = options[:connection].create_channel
|
28
|
+
channel.prefetch(1)
|
29
|
+
|
30
|
+
q = manager.get_queue(channel, queue)
|
31
|
+
retry_exchange = manager.get_retry_exchange(channel, queue)
|
32
|
+
|
33
|
+
q.subscribe(:manual_ack => true, :block => false, :exclusive => false) do |delivery_info, properties, payload|
|
34
|
+
begin
|
35
|
+
tag_processing_thread
|
36
|
+
process_message(payload, queue, channel, retry_exchange, delivery_info.delivery_tag, block)
|
37
|
+
rescue => e
|
38
|
+
EventQ.logger.error(
|
39
|
+
"[#{self.class}] - An error occurred attempting to process a message. Error: #{e} | "\
|
40
|
+
"Backtrace: #{e.backtrace}"
|
41
|
+
)
|
42
|
+
context.call_on_error_block(error: e)
|
43
|
+
ensure
|
44
|
+
untag_processing_thread
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# we don't want to stop the subscribe process as it will not block.
|
49
|
+
sleep 5 while context.running?
|
50
|
+
|
51
|
+
if channel != nil && channel.open?
|
52
|
+
channel.close
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def deserialize_message(payload)
|
57
|
+
provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
|
58
|
+
return provider.deserialize(payload)
|
59
|
+
end
|
60
|
+
|
61
|
+
def serialize_message(msg)
|
62
|
+
provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
|
63
|
+
return provider.serialize(msg)
|
64
|
+
end
|
65
|
+
|
66
|
+
def reject_message(channel, message, delivery_tag, retry_exchange, queue, abort)
|
67
|
+
|
68
|
+
EventQ.logger.info("[#{self.class}] - Message rejected removing from queue.")
|
69
|
+
#reject the message to remove from queue
|
70
|
+
channel.reject(delivery_tag, false)
|
71
|
+
|
72
|
+
#check if the message retry limit has been exceeded
|
73
|
+
if message.retry_attempts >= queue.max_retry_attempts
|
74
|
+
|
75
|
+
EventQ.logger.info("[#{self.class}] - Message retry attempt limit exceeded. Msg: #{serialize_message(message)}")
|
76
|
+
|
77
|
+
context.call_on_retry_exceeded_block(message)
|
78
|
+
|
79
|
+
#check if the message is allowed to be retried
|
80
|
+
elsif queue.allow_retry
|
81
|
+
|
82
|
+
EventQ.logger.debug { "[#{self.class}] - Incrementing retry attempts count." }
|
83
|
+
message.retry_attempts += 1
|
84
|
+
|
85
|
+
if queue.allow_retry_back_off == true
|
86
|
+
EventQ.logger.debug { "[#{self.class}] - Calculating message back off retry delay. Attempts: #{message.retry_attempts} * Retry Delay: #{queue.retry_delay}" }
|
87
|
+
message_ttl = message.retry_attempts * queue.retry_delay
|
88
|
+
if (message.retry_attempts * queue.retry_delay) > queue.max_retry_delay
|
89
|
+
EventQ.logger.debug { "[#{self.class}] - Max message back off retry delay reached." }
|
90
|
+
message_ttl = queue.max_retry_delay
|
91
|
+
end
|
92
|
+
else
|
93
|
+
EventQ.logger.debug { "[#{self.class}] - Setting fixed retry delay for message." }
|
94
|
+
message_ttl = queue.retry_delay
|
95
|
+
end
|
96
|
+
|
97
|
+
EventQ.logger.debug { "[#{self.class}] - Sending message for retry. Message TTL: #{message_ttl}" }
|
98
|
+
retry_exchange.publish(serialize_message(message), :expiration => message_ttl)
|
99
|
+
EventQ.logger.debug { "[#{self.class}] - Published message to retry exchange." }
|
100
|
+
|
101
|
+
context.call_on_retry_block(message)
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
return true
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
def configure(options = {})
|
110
|
+
options[:durable] ||= true
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def process_message(payload, queue, channel, retry_exchange, delivery_tag, block)
|
116
|
+
abort = false
|
117
|
+
error = false
|
118
|
+
message = deserialize_message(payload)
|
119
|
+
|
120
|
+
EventQ.logger.info("[#{self.class}] - Message received. Retry Attempts: #{message.retry_attempts}")
|
121
|
+
|
122
|
+
@signature_provider_manager.validate_signature(message: message, queue: queue)
|
123
|
+
|
124
|
+
message_args = EventQ::MessageArgs.new(
|
125
|
+
type: message.type,
|
126
|
+
retry_attempts: message.retry_attempts,
|
127
|
+
context: message.context,
|
128
|
+
content_type: message.content_type,
|
129
|
+
id: message.id,
|
130
|
+
sent: message.created
|
131
|
+
)
|
132
|
+
|
133
|
+
if(!EventQ::NonceManager.is_allowed?(message.id))
|
134
|
+
EventQ.logger.info("[#{self.class}] - Duplicate Message received. Dropping message.")
|
135
|
+
channel.acknowledge(delivery_tag, false)
|
136
|
+
return false
|
137
|
+
end
|
138
|
+
|
139
|
+
# begin worker block for queue message
|
140
|
+
begin
|
141
|
+
block.call(message.content, message_args)
|
142
|
+
|
143
|
+
if message_args.abort == true
|
144
|
+
abort = true
|
145
|
+
EventQ.logger.info("[#{self.class}] - Message aborted.")
|
146
|
+
else
|
147
|
+
# accept the message as processed
|
148
|
+
channel.acknowledge(delivery_tag, false)
|
149
|
+
EventQ.logger.info("[#{self.class}] - Message acknowledged.")
|
150
|
+
end
|
151
|
+
|
152
|
+
rescue => e
|
153
|
+
EventQ.logger.error("[#{self.class}] - An unhandled error happened attempting to process a queue message. Error: #{e} | Backtrace: #{e.backtrace}")
|
154
|
+
error = true
|
155
|
+
context.call_on_error_block(error: e, message: message)
|
156
|
+
end
|
157
|
+
|
158
|
+
if error || abort
|
159
|
+
EventQ::NonceManager.failed(message.id)
|
160
|
+
reject_message(channel, message, delivery_tag, retry_exchange, queue, abort)
|
161
|
+
else
|
162
|
+
EventQ::NonceManager.complete(message.id)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module EventQ
|
2
|
+
module RabbitMq
|
3
|
+
class StatusChecker
|
4
|
+
|
5
|
+
def initialize(client:, queue_manager:)
|
6
|
+
|
7
|
+
if client == nil
|
8
|
+
raise 'client must be specified.'.freeze
|
9
|
+
end
|
10
|
+
|
11
|
+
@client = client
|
12
|
+
|
13
|
+
if queue_manager == nil
|
14
|
+
raise 'queue_manager must be specified.'.freeze
|
15
|
+
end
|
16
|
+
|
17
|
+
@queue_manager = queue_manager
|
18
|
+
|
19
|
+
@event_raised_exchange = EventRaisedExchange.new
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def queue?(queue)
|
24
|
+
|
25
|
+
outcome = true
|
26
|
+
|
27
|
+
begin
|
28
|
+
connection = @client.get_connection
|
29
|
+
channel = connection.create_channel
|
30
|
+
_queue_name = EventQ.create_queue_name(queue.name)
|
31
|
+
channel.queue(_queue_name, :durable => true)
|
32
|
+
rescue
|
33
|
+
outcome = false
|
34
|
+
ensure
|
35
|
+
channel.close if channel
|
36
|
+
connection.close if connection
|
37
|
+
end
|
38
|
+
|
39
|
+
outcome
|
40
|
+
end
|
41
|
+
|
42
|
+
def event_type?(event_type)
|
43
|
+
|
44
|
+
outcome = true
|
45
|
+
|
46
|
+
begin
|
47
|
+
connection = @client.get_connection
|
48
|
+
channel = connection.create_channel
|
49
|
+
@queue_manager.get_exchange(channel, @event_raised_exchange)
|
50
|
+
rescue
|
51
|
+
outcome = false
|
52
|
+
ensure
|
53
|
+
channel.close if channel
|
54
|
+
connection.close if connection
|
55
|
+
end
|
56
|
+
|
57
|
+
outcome
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module EventQ
|
2
|
+
module RabbitMq
|
3
|
+
class SubscriptionManager
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
if options[:client] == nil
|
7
|
+
raise ':client (QueueClient) must be specified.'.freeze
|
8
|
+
end
|
9
|
+
@client = options[:client]
|
10
|
+
@queue_manager = QueueManager.new
|
11
|
+
@event_raised_exchange = EventQ::EventRaisedExchange.new
|
12
|
+
end
|
13
|
+
|
14
|
+
def subscribe(event_type, queue)
|
15
|
+
|
16
|
+
_event_type = EventQ.create_event_type(event_type)
|
17
|
+
|
18
|
+
connection = @client.get_connection
|
19
|
+
channel = connection.create_channel
|
20
|
+
|
21
|
+
queue = @queue_manager.get_queue(channel, queue)
|
22
|
+
exchange = @queue_manager.get_exchange(channel, @event_raised_exchange)
|
23
|
+
|
24
|
+
queue.bind(exchange, :routing_key => _event_type)
|
25
|
+
|
26
|
+
channel.close
|
27
|
+
connection.close
|
28
|
+
|
29
|
+
EventQ.logger.debug do
|
30
|
+
"[#{self.class} #subscribe] - Subscribing queue: #{queue.name} to Exchange: #{_event_type}"
|
31
|
+
end
|
32
|
+
|
33
|
+
return true
|
34
|
+
end
|
35
|
+
|
36
|
+
def unsubscribe(queue)
|
37
|
+
|
38
|
+
connection = @client.get_connection
|
39
|
+
channel = connection.create_channel
|
40
|
+
|
41
|
+
queue = @queue_manager.get_queue(channel, queue)
|
42
|
+
exchange = @queue_manager.get_exchange(channel, @event_raised_exchange)
|
43
|
+
|
44
|
+
queue.unbind(exchange)
|
45
|
+
|
46
|
+
channel.close
|
47
|
+
connection.close
|
48
|
+
|
49
|
+
return true
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|