mimi-messaging-sqs_sns 0.8.0 → 0.8.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf7944b9a3e10f154f738d66544cfa63611b17a742b156460969f70821ad86bb
4
- data.tar.gz: f26e3e3623208170de192174c9c0fdb2ef5e26fa8cca831e73065eb86e21b0b5
3
+ metadata.gz: 9ebbd0b876cc696936356711703245e45106ff85ad152bde59fd2826b6cbc21f
4
+ data.tar.gz: ac2167ece90f7de977fee85c66137e5cb9f232e139fcb8ab797c27467cffa540
5
5
  SHA512:
6
- metadata.gz: 37bbb87ba16df4886a5e525ca13732b3712021c5269418d8d8c90e1af125cbaa7e32aa5757a96293569a1717cc4c00542aaf20d12f3fc7514477cd3d708cd615
7
- data.tar.gz: 9d53cc0479c47af711f0e89203f9ef1ced767115743fb2fa685ea559ebb0b891226a248219ff2103ec95207b678814c1c0b983f82a22eda8e741feac01a2d4dc
6
+ metadata.gz: 0cdc8a69e02de3533b0871fb9727fbe63e47081fe6a0ac66bf093cacf2f99d16f697034987adc507078bcf14d4864dd7ff78a2025e49305b4ae48c32313b1992
7
+ data.tar.gz: 56665e8adb58d3d17c1fcb7e3b5ef5eea8231d24a130de1bfd589acb90169473bd6088a5a227d3eb6d3141ce19af7939d2a874132607b45579b4a02d4b4c3103
data/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## UNRELEASED
4
4
 
5
+ ## v0.8.2
6
+
7
+ * [#7](https://github.com/kukushkin/mimi-messaging-sqs_sns/pull/7)
8
+ * Fixed an issue in the error processing, which could potentially crash the consumer threads
9
+
10
+ ## v0.8.1
11
+
12
+ * [#5](https://github.com/kukushkin/mimi-messaging-sqs_sns/pull/5)
13
+ * Refactored worker pool based message processing and error handling
14
+
5
15
  ## v0.8.0
6
16
 
7
17
  * [#3](https://github.com/kukushkin/mimi-messaging-sqs_sns/pull/3)
data/TODO.md CHANGED
@@ -3,7 +3,7 @@
3
3
  List of missing features planned for future releases.
4
4
 
5
5
  * [X] Log error and recover if the reply cannot be sent
6
- * [ ] Threadsafe TimeoutQueue
7
- * [ ] Multithreaded consumers
6
+ * [X] Threadsafe TimeoutQueue
7
+ * [X] Multithreaded consumers
8
8
  * [ ] Subscribe to topic without a queue (Temporary queues)
9
9
 
data/examples/event.rb CHANGED
@@ -4,8 +4,8 @@ require "mimi/messaging/sqs_sns"
4
4
 
5
5
  COUNT = 10
6
6
  AWS_REGION = "eu-west-1"
7
- AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
8
- AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
7
+ AWS_SQS_ENDPOINT_URL = "http://sqs-sns:4566"
8
+ AWS_SNS_ENDPOINT_URL = "http://sqs-sns:4566"
9
9
  AWS_ACCESS_KEY_ID = "foo"
10
10
  AWS_SECRET_ACCESS_KEY = "bar"
11
11
 
@@ -6,8 +6,8 @@ COUNT = 10
6
6
  THREADS = 10
7
7
  QUERY_TIMEOUT = 60
8
8
  AWS_REGION = "eu-west-1"
9
- AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
10
- AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
9
+ AWS_SQS_ENDPOINT_URL = "http://sqs-sns:4566"
10
+ AWS_SNS_ENDPOINT_URL = "http://sqs-sns:4566"
11
11
  AWS_ACCESS_KEY_ID = "foo"
12
12
  AWS_SECRET_ACCESS_KEY = "bar"
13
13
  AWS_SQS_SNS_KMS_MASTER_KEY_ID = "blah"
data/examples/query.rb CHANGED
@@ -4,8 +4,8 @@ require "mimi/messaging/sqs_sns"
4
4
 
5
5
  COUNT = 10
6
6
  AWS_REGION = "eu-west-1"
7
- AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
8
- AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
7
+ AWS_SQS_ENDPOINT_URL = "http://sqs-sns:4566"
8
+ AWS_SNS_ENDPOINT_URL = "http://sqs-sns:4566"
9
9
  AWS_ACCESS_KEY_ID = "foo"
10
10
  AWS_SECRET_ACCESS_KEY = "bar"
11
11
  AWS_SQS_SNS_KMS_MASTER_KEY_ID = "blah"
@@ -3,8 +3,8 @@
3
3
  require "mimi/messaging/sqs_sns"
4
4
 
5
5
  AWS_REGION = "eu-west-1"
6
- AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
7
- AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
6
+ AWS_SQS_ENDPOINT_URL = "http://sqs-sns:4566"
7
+ AWS_SNS_ENDPOINT_URL = "http://sqs-sns:4566"
8
8
  AWS_ACCESS_KEY_ID = "foo"
9
9
  AWS_SECRET_ACCESS_KEY = "bar"
10
10
  AWS_SQS_SNS_KMS_MASTER_KEY_ID = "blah"
@@ -3,8 +3,8 @@
3
3
  require "mimi/messaging/sqs_sns"
4
4
 
5
5
  AWS_REGION = "eu-west-1"
6
- AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
7
- AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
6
+ AWS_SQS_ENDPOINT_URL = "http://sqs-sns:4566"
7
+ AWS_SNS_ENDPOINT_URL = "http://sqs-sns:4566"
8
8
  AWS_ACCESS_KEY_ID = "foo"
9
9
  AWS_SECRET_ACCESS_KEY = "bar"
10
10
 
@@ -185,15 +185,8 @@ module Mimi
185
185
  @consumers ||= []
186
186
  opts = opts.dup
187
187
  queue_url = find_or_create_queue(queue_name)
188
- @consumers << Consumer.new(self, queue_url) do |m|
189
- worker_pool.post do
190
- process_request_message(processor, m)
191
- end
192
- rescue Concurrent::RejectedExecutionError
193
- # the backlog is overflown, put the message back
194
- Mimi::Messaging.log "Worker pool backlog is full, nack-ing the message " \
195
- "(workers:#{worker_pool.length}, backlog:#{worker_pool.queue_length})"
196
- raise Mimi::Messaging::NACK # exception raised in Consumer thread
188
+ @consumers << Consumer.new(self, queue_url, worker_pool) do |m|
189
+ process_request_message(processor, m)
197
190
  end
198
191
  end
199
192
 
@@ -209,15 +202,8 @@ module Mimi
209
202
  topic_arn = find_or_create_topic(topic_name) # TODO: or find_topic!(...) ?
210
203
  queue_url = find_or_create_queue(queue_name)
211
204
  subscribe_topic_queue(topic_arn, queue_url)
212
- @consumers << Consumer.new(self, queue_url) do |m|
213
- worker_pool.post do
214
- process_event_message(processor, m)
215
- end
216
- rescue Concurrent::RejectedExecutionError
217
- # the backlog is overflown, put the message back
218
- Mimi::Messaging.log "Worker pool backlog is full, nack-ing the message " \
219
- "(workers:#{worker_pool.length}, backlog:#{worker_pool.queue_length})"
220
- raise Mimi::Messaging::NACK # exception raised in Consumer thread
205
+ @consumers << Consumer.new(self, queue_url, worker_pool) do |m|
206
+ process_event_message(processor, m)
221
207
  end
222
208
  end
223
209
 
@@ -10,12 +10,20 @@ module Mimi
10
10
  # (seconds) determines how soon the NACK-ed message becomes visible to other consumers
11
11
  NACK_VISIBILITY_TIMEOUT = 1
12
12
 
13
- def initialize(adapter, queue_url, &block)
13
+ # Creates a new Consumer to read and process messages from the given queue.
14
+ #
15
+ # @param adapter [Mimi::Messaging::SQS_SNS::Adapter]
16
+ # @param queue_url [String]
17
+ # @param worker_pool [Concurrent::ThreadPoolExecutor, nil] an optional worker pool to be used
18
+ #
19
+ def initialize(adapter, queue_url, worker_pool = nil, &block)
14
20
  @stop_requested = false
15
- Mimi::Messaging.log "Starting consumer for: #{queue_url}"
21
+ @worker_pool = worker_pool
22
+ Mimi::Messaging.log "Starting consumer for: #{queue_url}, " \
23
+ " worker_pool: #{worker_pool ? "yes" : "no"}"
16
24
  @consumer_thread = Thread.new do
17
25
  while not @stop_requested
18
- read_and_process_message(adapter, queue_url, block)
26
+ read_and_process_message(adapter, queue_url, worker_pool, block)
19
27
  end
20
28
  Mimi::Messaging.log "Stopping consumer for: #{queue_url}"
21
29
  end
@@ -41,25 +49,33 @@ module Mimi
41
49
  #
42
50
  # @param adapter [Mimi::Messaging::SQS_SNS::Adapter]
43
51
  # @param queue_url [String]
52
+ # @param worker_pool [Concurrent::ThreadPoolExecutor,nil]
44
53
  # @param block [Proc] a block to be invoked when a message is received
45
54
  #
46
- def read_and_process_message(adapter, queue_url, block)
55
+ def read_and_process_message(adapter, queue_url, worker_pool, block)
47
56
  message = read_message(adapter, queue_url)
48
57
  return unless message
49
58
 
50
59
  Mimi::Messaging.log "Read message from: #{queue_url}"
51
- block.call(message)
52
- ack_message(adapter, queue_url, message)
53
- rescue Mimi::Messaging::NACK
54
- Mimi::Messaging.log "NACK-ing message from: #{queue_url}"
55
- nack_message(adapter, queue_url, message)
60
+ if worker_pool
61
+ process_message_worker_pool(adapter, queue_url, worker_pool, message, block)
62
+ else
63
+ process_message(adapter, queue_url, message, block)
64
+ end
56
65
  rescue StandardError => e
57
66
  Mimi::Messaging.logger&.error(
58
- "#{self.class}: failed to read and process message from: #{queue_url}," \
67
+ "#{self.class}: failed to read or process message from: #{queue_url}," \
68
+ " worker_pool: #{worker_pool ? "yes" : "no"}" \
59
69
  " error: (#{e.class}) #{e}"
60
70
  )
61
71
  end
62
72
 
73
+ # Returns a message read from SQS queue
74
+ #
75
+ # @param adapter [Mimi::Messaging::SQS_SNS::Adapter]
76
+ # @param queue_url [String]
77
+ # @return [Hash] with stringified keys
78
+ #
63
79
  def read_message(adapter, queue_url)
64
80
  result = adapter.sqs_client.receive_message(
65
81
  queue_url: queue_url,
@@ -73,6 +89,40 @@ module Mimi
73
89
  raise Mimi::Messaging::ConnectionError, "Unexpected number of messages read"
74
90
  end
75
91
 
92
+ # Processes a received message using the worker pool
93
+ #
94
+ # @param adapter [Mimi::Messaging::SQS_SNS::Adapter]
95
+ # @param queue_url [String]
96
+ # @param worker_pool [Concurrent::ThreadPoolExecutor,nil]
97
+ # @param block [Proc] a block to be invoked when a message is received
98
+ #
99
+ def process_message_worker_pool(adapter, queue_url, worker_pool, message, block)
100
+ begin
101
+ worker_pool.post do
102
+ process_message(adapter, queue_url, message, block)
103
+ end
104
+ rescue Concurrent::RejectedExecutionError
105
+ # the backlog is overflown, put the message back
106
+ Mimi::Messaging.log "Worker pool backlog is full, nack-ing the message " \
107
+ "(workers:#{worker_pool.length}, backlog:#{worker_pool.queue_length})"
108
+ nack_message(adapter, queue_url, message)
109
+ end
110
+ end
111
+
112
+ def process_message(adapter, queue_url, message, block)
113
+ block.call(message)
114
+ ack_message(adapter, queue_url, message)
115
+ rescue Mimi::Messaging::NACK
116
+ Mimi::Messaging.log "NACK-ing message from: #{queue_url}"
117
+ nack_message(adapter, queue_url, message)
118
+ rescue StandardError => e
119
+ Mimi::Messaging.logger&.error(
120
+ "#{self.class}: failed to process message from: #{queue_url}," \
121
+ " error: (#{e.class}) #{e}"
122
+ )
123
+ # NOTE: error is recovered and the message is neither ACKed or NACKed
124
+ end
125
+
76
126
  # ACK-ing the message indicates successfull processing of it
77
127
  # and removes the message from the queue
78
128
  #
@@ -91,6 +141,12 @@ module Mimi
91
141
  receipt_handle: msg.receipt_handle,
92
142
  visibility_timeout: NACK_VISIBILITY_TIMEOUT
93
143
  )
144
+ rescue StandardError => e
145
+ Mimi::Messaging.logger&.error(
146
+ "#{self.class}: failed to NACK message from: #{queue_url}," \
147
+ " error: (#{e.class}) #{e}"
148
+ )
149
+ # NOTE: error is recovered and the message is neither ACKed or NACKed
94
150
  end
95
151
  end # class Consumer
96
152
  end # module SQS_SNS
@@ -3,7 +3,7 @@
3
3
  module Mimi
4
4
  module Messaging
5
5
  module SQS_SNS
6
- VERSION = "0.8.0"
6
+ VERSION = "0.8.3"
7
7
  end
8
8
  end
9
9
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mimi-messaging-sqs_sns
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Kukushkin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-16 00:00:00.000000000 Z
11
+ date: 2022-03-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimi-messaging