mimi-messaging-sqs_sns 0.7.0 → 0.8.0

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: b02992abcb101248ebc54069aba5b3887417930b7613a84ed4b6723ad7ce3060
4
- data.tar.gz: 3b830249dfb56e42a7d380571402c2abef55d74f3e90bf0b9f537e105078cd27
3
+ metadata.gz: cf7944b9a3e10f154f738d66544cfa63611b17a742b156460969f70821ad86bb
4
+ data.tar.gz: f26e3e3623208170de192174c9c0fdb2ef5e26fa8cca831e73065eb86e21b0b5
5
5
  SHA512:
6
- metadata.gz: 4d6ecfe3d2202124b10ff03129166249f518fca0f15c2e513ba5ab6b2835a713671618eab623fb39e3cbebe3c8351e0688884743e4f69baa3832b1db94a6a858
7
- data.tar.gz: 5bb7ae92080d112f16a4127b010f7f102ebd71cb53b4701b756e9bbab8c43fae42618969c148fd71f67678dbf34ed4d6c734307a1c84f7201229d5bd95c3907a
6
+ metadata.gz: 37bbb87ba16df4886a5e525ca13732b3712021c5269418d8d8c90e1af125cbaa7e32aa5757a96293569a1717cc4c00542aaf20d12f3fc7514477cd3d708cd615
7
+ data.tar.gz: 9d53cc0479c47af711f0e89203f9ef1ced767115743fb2fa685ea559ebb0b891226a248219ff2103ec95207b678814c1c0b983f82a22eda8e741feac01a2d4dc
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## UNRELEASED
4
+
5
+ ## v0.8.0
6
+
7
+ * [#3](https://github.com/kukushkin/mimi-messaging-sqs_sns/pull/3)
8
+ * Added a worker pool:
9
+ * now processing of messages from a single queue can be done in multiple parallel threads (workers)
10
+ * the worker threads are shared across all message consumers which read messages from different queues
11
+ * the size of the worker pool is limited, to have at most `mq_worker_pool_max_threads` processing messages in parallel
12
+ * `mq_worker_pool_min_threads` determines the target minimal number of threads in the pool, waiting for new messages
13
+ * `mq_worker_pool_max_backlog` controls how many messages which are read from SQS queues can be put in the worker pool backlog; if a new message is read from SQS queue and the backlog is full, this message is NACK-ed (put back into SQS queue for the other consumers to process)
14
+ * Improved thread-safety of the adapter: reply consumer, TimeoutQueue#pop
15
+
3
16
  ## v0.7.0
4
17
 
5
18
  * [#1](https://github.com/kukushkin/mimi-messaging-sqs_sns/pull/1)
data/TODO.md CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  List of missing features planned for future releases.
4
4
 
5
- [X] Log error and recover if the reply cannot be sent
6
- [ ] Threadsafe TimeoutQueue
7
- [ ] Multithreaded consumers
8
- [ ] Subscribe to topic without a queue (Temporary queues)
5
+ * [X] Log error and recover if the reply cannot be sent
6
+ * [ ] Threadsafe TimeoutQueue
7
+ * [ ] Multithreaded consumers
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:4576"
8
- AWS_SNS_ENDPOINT_URL = "http://localstack:4575"
7
+ AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
8
+ AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
9
9
  AWS_ACCESS_KEY_ID = "foo"
10
10
  AWS_SECRET_ACCESS_KEY = "bar"
11
11
 
@@ -30,5 +30,5 @@ COUNT.times do |i|
30
30
  t = Time.now
31
31
  puts "Publishing event: #{i}"
32
32
  adapter.event("hello#tested", i: i) # rand(100))
33
- sleep 1
33
+ sleep 0.1
34
34
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mimi/messaging/sqs_sns"
4
+
5
+ COUNT = 10
6
+ THREADS = 10
7
+ QUERY_TIMEOUT = 60
8
+ AWS_REGION = "eu-west-1"
9
+ AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
10
+ AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
11
+ AWS_ACCESS_KEY_ID = "foo"
12
+ AWS_SECRET_ACCESS_KEY = "bar"
13
+ AWS_SQS_SNS_KMS_MASTER_KEY_ID = "blah"
14
+
15
+ logger = Logger.new(STDOUT)
16
+ logger.level = Logger::INFO
17
+ Mimi::Messaging.use(logger: logger, serializer: Mimi::Messaging::JsonSerializer)
18
+ Mimi::Messaging.configure(
19
+ mq_adapter: "sqs_sns",
20
+ mq_aws_access_key_id: AWS_ACCESS_KEY_ID,
21
+ mq_aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
22
+ mq_aws_region: AWS_REGION,
23
+ mq_aws_sqs_endpoint: AWS_SQS_ENDPOINT_URL,
24
+ mq_aws_sns_endpoint: AWS_SNS_ENDPOINT_URL,
25
+ mq_aws_sqs_sns_kms_master_key_id: AWS_SQS_SNS_KMS_MASTER_KEY_ID,
26
+ mq_default_query_timeout: QUERY_TIMEOUT
27
+ )
28
+ adapter = Mimi::Messaging.adapter
29
+
30
+ adapter.start
31
+
32
+ t_start = Time.now
33
+ t_queries = []
34
+ threads = []
35
+ THREADS.times do |ti|
36
+ threads << Thread.new do
37
+ COUNT.times do |i|
38
+ t = Time.now
39
+ result = adapter.query("test/hello", i: i) # rand(100))
40
+ t = Time.now - t
41
+ t_queries << t
42
+ puts "result: #{result.to_h}, t: %.3fs" % t
43
+ sleep 0.1
44
+ end
45
+ end
46
+ end
47
+
48
+ threads.each(&:join)
49
+
50
+ t_elapsed = Time.now - t_start
51
+ puts "t_elapsed: %.3fs" % t_elapsed
52
+ adapter.stop
53
+ puts "t.avg: %.3fs" % (t_queries.sum / t_queries.count)
@@ -17,6 +17,7 @@ class Processor
17
17
  def self.call_query(method_name, message, opts)
18
18
  # puts "QUERY: #{method_name}, #{message}, headers: #{opts[:headers]}"
19
19
  puts "QUERY: #{method_name}, headers: #{opts[:headers]}"
20
+ sleep 1 # imitate work
20
21
  {}
21
22
  end
22
23
  end # class Processor
@@ -32,7 +33,11 @@ Mimi::Messaging.configure(
32
33
  mq_aws_region: AWS_REGION,
33
34
  mq_aws_sqs_endpoint: AWS_SQS_ENDPOINT_URL,
34
35
  mq_aws_sns_endpoint: AWS_SNS_ENDPOINT_URL,
35
- mq_aws_sqs_sns_kms_master_key_id: AWS_SQS_SNS_KMS_MASTER_KEY_ID
36
+ mq_aws_sqs_sns_kms_master_key_id: AWS_SQS_SNS_KMS_MASTER_KEY_ID,
37
+ mq_worker_pool_min_threads: 1,
38
+ mq_worker_pool_max_threads: 2,
39
+ mq_worker_pool_max_backlog: 4,
40
+ mq_log_at_level: :info
36
41
  )
37
42
  adapter = Mimi::Messaging.adapter
38
43
  queue_name = "test"
@@ -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:4576"
7
- AWS_SNS_ENDPOINT_URL = "http://localstack:4575"
6
+ AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
7
+ AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
8
8
  AWS_ACCESS_KEY_ID = "foo"
9
9
  AWS_SECRET_ACCESS_KEY = "bar"
10
10
 
@@ -20,6 +20,7 @@ class Processor
20
20
 
21
21
  def self.call_event(event_type, message, opts)
22
22
  puts "EVENT: #{event_type}, #{message}, headers: #{message.headers}"
23
+ sleep 1 # imitate work
23
24
  end
24
25
  end # class Processor
25
26
 
@@ -34,6 +35,9 @@ Mimi::Messaging.configure(
34
35
  mq_aws_region: AWS_REGION,
35
36
  mq_aws_sqs_endpoint: AWS_SQS_ENDPOINT_URL,
36
37
  mq_aws_sns_endpoint: AWS_SNS_ENDPOINT_URL,
38
+ mq_worker_pool_min_threads: 1,
39
+ mq_worker_pool_max_threads: 2,
40
+ mq_worker_pool_max_backlog: 4,
37
41
  mq_log_at_level: :info
38
42
  )
39
43
  adapter = Mimi::Messaging.adapter
@@ -52,4 +56,3 @@ ensure
52
56
  puts "Stopping adapter"
53
57
  adapter.stop
54
58
  end
55
-
@@ -3,8 +3,9 @@
3
3
  require "mimi/messaging"
4
4
  require "aws-sdk-sqs"
5
5
  require "aws-sdk-sns"
6
- require "timeout"
7
6
  require "securerandom"
7
+ require "concurrent"
8
+ require_relative "timeout_queue"
8
9
 
9
10
  module Mimi
10
11
  module Messaging
@@ -40,7 +41,7 @@ module Mimi
40
41
  "." => "-"
41
42
  }.freeze
42
43
 
43
- attr_reader :options, :sqs_client, :sns_client
44
+ attr_reader :options, :sqs_client, :sns_client, :worker_pool
44
45
 
45
46
  register_adapter_name "sqs_sns"
46
47
 
@@ -49,6 +50,11 @@ module Mimi
49
50
  mq_default_query_timeout: 15, # seconds,
50
51
  mq_reply_queue_prefix: "reply-",
51
52
 
53
+ # worker pool parameters
54
+ mq_worker_pool_min_threads: 1,
55
+ mq_worker_pool_max_threads: 16,
56
+ mq_worker_pool_max_backlog: 16,
57
+
52
58
  # if nil, AWS SDK will guess values from environment
53
59
  mq_aws_region: nil,
54
60
  mq_aws_access_key_id: nil,
@@ -74,16 +80,19 @@ module Mimi
74
80
  #
75
81
  def initialize(options)
76
82
  @options = DEFAULT_OPTIONS.merge(options).dup
83
+ @reply_consumer_mutex = Mutex.new
77
84
  end
78
85
 
79
86
  def start
80
87
  @sqs_client = Aws::SQS::Client.new(sqs_client_config)
81
88
  @sns_client = Aws::SNS::Client.new(sns_client_config)
89
+ start_worker_pool!
82
90
  check_availability!
83
91
  end
84
92
 
85
93
  def stop
86
94
  stop_all_processors
95
+ stop_worker_pool!
87
96
  @sqs_client = nil
88
97
  @sns_client = nil
89
98
  end
@@ -126,7 +135,7 @@ module Mimi
126
135
  # @param opts [Hash] additional options, e.g. :timeout
127
136
  #
128
137
  # @return [Hash]
129
- # @raise [SomeError,TimeoutError]
138
+ # @raise [SomeError,Timeout::Error]
130
139
  #
131
140
  def query(target, message, opts = {})
132
141
  queue_name, method_name = target.split("/")
@@ -142,10 +151,7 @@ module Mimi
142
151
  )
143
152
  deliver_message_queue(queue_url, message)
144
153
  timeout = opts[:timeout] || options[:mq_default_query_timeout]
145
- response = nil
146
- Timeout::timeout(timeout) do
147
- response = reply_queue.pop
148
- end
154
+ response = reply_queue.pop(true, timeout)
149
155
  deserialize(response.body)
150
156
  end
151
157
 
@@ -180,22 +186,14 @@ module Mimi
180
186
  opts = opts.dup
181
187
  queue_url = find_or_create_queue(queue_name)
182
188
  @consumers << Consumer.new(self, queue_url) do |m|
183
- message = Mimi::Messaging::Message.new(
184
- deserialize(m.body),
185
- deserialize_headers(m)
186
- )
187
- method_name = message.headers[:__method]
188
- reply_to = message.headers[:__reply_queue_url]
189
- if reply_to
190
- response = processor.call_query(method_name, message, {})
191
- response_message = Mimi::Messaging::Message.new(
192
- response,
193
- __request_id: message.headers[:__request_id]
194
- )
195
- deliver_query_respone(reply_to, response_message)
196
- else
197
- processor.call_command(method_name, message, {})
189
+ worker_pool.post do
190
+ process_request_message(processor, m)
198
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
199
197
  end
200
198
  end
201
199
 
@@ -212,12 +210,14 @@ module Mimi
212
210
  queue_url = find_or_create_queue(queue_name)
213
211
  subscribe_topic_queue(topic_arn, queue_url)
214
212
  @consumers << Consumer.new(self, queue_url) do |m|
215
- message = Mimi::Messaging::Message.new(
216
- deserialize(m.body),
217
- deserialize_headers(m)
218
- )
219
- event_type = message.headers[:__event_type]
220
- processor.call_event(event_type, message, {})
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
221
221
  end
222
222
  end
223
223
 
@@ -333,6 +333,30 @@ module Mimi
333
333
  raise Mimi::Messaging::ConnectionError, "Failed to deliver message to '#{queue_url}': #{e}"
334
334
  end
335
335
 
336
+ # Processes an incoming COMMAND or QUERY message
337
+ #
338
+ # @param processor [#call_query(),#call_command()] request processor object
339
+ # @param sqs_message
340
+ #
341
+ def process_request_message(processor, sqs_message)
342
+ message = Mimi::Messaging::Message.new(
343
+ deserialize(sqs_message.body),
344
+ deserialize_headers(sqs_message)
345
+ )
346
+ method_name = message.headers[:__method]
347
+ reply_to = message.headers[:__reply_queue_url]
348
+ if reply_to
349
+ response = processor.call_query(method_name, message, {})
350
+ response_message = Mimi::Messaging::Message.new(
351
+ response,
352
+ __request_id: message.headers[:__request_id]
353
+ )
354
+ deliver_query_response(reply_to, response_message)
355
+ else
356
+ processor.call_command(method_name, message, {})
357
+ end
358
+ end
359
+
336
360
  # Delivers a message as a response to a QUERY
337
361
  #
338
362
  # Responses are allowed to fail. There can be a number of reasons
@@ -343,7 +367,7 @@ module Mimi
343
367
  # @param queue_url [String]
344
368
  # @param message [Mimi::Messaging::Message]
345
369
  #
346
- def deliver_query_respone(queue_url, message)
370
+ def deliver_query_response(queue_url, message)
347
371
  deliver_message_queue(queue_url, message)
348
372
  rescue Mimi::Messaging::ConnectionError => e
349
373
  Mimi::Messaging.logger&.warn("Failed to deliver QRY response: #{e}")
@@ -402,9 +426,11 @@ module Mimi
402
426
  # @return [ReplyConsumer]
403
427
  #
404
428
  def reply_consumer
405
- @reply_consumer ||= begin
406
- reply_queue_name = options[:mq_reply_queue_prefix] + SecureRandom.hex(8)
407
- Mimi::Messaging::SQS_SNS::ReplyConsumer.new(self, reply_queue_name)
429
+ @reply_consumer_mutex.synchronize do
430
+ @reply_consumer ||= begin
431
+ reply_queue_name = options[:mq_reply_queue_prefix] + SecureRandom.hex(8)
432
+ Mimi::Messaging::SQS_SNS::ReplyConsumer.new(self, reply_queue_name)
433
+ end
408
434
  end
409
435
  end
410
436
 
@@ -540,6 +566,46 @@ module Mimi
540
566
  rescue StandardError => e
541
567
  raise Mimi::Messaging::ConnectionError, "Failed to deliver message to '#{topic_arn}': #{e}"
542
568
  end
569
+
570
+ # Processes an incoming EVENT message
571
+ #
572
+ # @param processor [#call_event()] event processor object
573
+ # @param sqs_message []
574
+ #
575
+ def process_event_message(processor, sqs_message)
576
+ message = Mimi::Messaging::Message.new(
577
+ deserialize(sqs_message.body),
578
+ deserialize_headers(sqs_message)
579
+ )
580
+ event_type = message.headers[:__event_type]
581
+ processor.call_event(event_type, message, {})
582
+ end
583
+
584
+ # Starts the worker pool using current configuration
585
+ #
586
+ # @return [Concurrent::ThreadPoolExecutor]
587
+ #
588
+ def start_worker_pool!
589
+ Mimi::Messaging.log "Starting worker pool, " \
590
+ "min_threads:#{options[:mq_worker_pool_min_threads]}, " \
591
+ "max_threads:#{options[:mq_worker_pool_max_threads]}, " \
592
+ "max_backlog:#{options[:mq_worker_pool_max_backlog]}"
593
+
594
+ @worker_pool = Concurrent::ThreadPoolExecutor.new(
595
+ min_threads: options[:mq_worker_pool_min_threads],
596
+ max_threads: options[:mq_worker_pool_max_threads],
597
+ max_queue: options[:mq_worker_pool_max_backlog],
598
+ fallback_policy: :abort
599
+ )
600
+ end
601
+
602
+ # Gracefully stops the worker pool, allowing all threads to finish their jobs
603
+ #
604
+ def stop_worker_pool!
605
+ Mimi::Messaging.log "Stopping worker pool"
606
+ @worker_pool.shutdown
607
+ @worker_pool.wait_for_termination
608
+ end
543
609
  end # class Adapter
544
610
  end # module SQS_SNS
545
611
  end # module Messaging
@@ -7,6 +7,9 @@ module Mimi
7
7
  # Message consumer for SQS queues
8
8
  #
9
9
  class Consumer
10
+ # (seconds) determines how soon the NACK-ed message becomes visible to other consumers
11
+ NACK_VISIBILITY_TIMEOUT = 1
12
+
10
13
  def initialize(adapter, queue_url, &block)
11
14
  @stop_requested = false
12
15
  Mimi::Messaging.log "Starting consumer for: #{queue_url}"
@@ -47,6 +50,9 @@ module Mimi
47
50
  Mimi::Messaging.log "Read message from: #{queue_url}"
48
51
  block.call(message)
49
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)
50
56
  rescue StandardError => e
51
57
  Mimi::Messaging.logger&.error(
52
58
  "#{self.class}: failed to read and process message from: #{queue_url}," \
@@ -67,11 +73,25 @@ module Mimi
67
73
  raise Mimi::Messaging::ConnectionError, "Unexpected number of messages read"
68
74
  end
69
75
 
76
+ # ACK-ing the message indicates successfull processing of it
77
+ # and removes the message from the queue
78
+ #
70
79
  def ack_message(adapter, queue_url, msg)
71
80
  adapter.sqs_client.delete_message(
72
81
  queue_url: queue_url, receipt_handle: msg.receipt_handle
73
82
  )
74
83
  end
84
+
85
+ # NACK-ing the message indicates a failure to process the message.
86
+ # The message becomes immediately available to other consumers.
87
+ #
88
+ def nack_message(adapter, queue_url, msg)
89
+ adapter.sqs_client.change_message_visibility(
90
+ queue_url: queue_url,
91
+ receipt_handle: msg.receipt_handle,
92
+ visibility_timeout: NACK_VISIBILITY_TIMEOUT
93
+ )
94
+ end
75
95
  end # class Consumer
76
96
  end # module SQS_SNS
77
97
  end # module Messaging
@@ -36,7 +36,7 @@ module Mimi
36
36
  # @return [Queue] a new Queue object registered for this request_id
37
37
  #
38
38
  def register_request_id(request_id)
39
- queue = Queue.new
39
+ queue = TimeoutQueue.new
40
40
  @mutex.synchronize do
41
41
  queue = @queues[request_id] ||= queue
42
42
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "timeout"
4
+
5
+ module Mimi
6
+ module Messaging
7
+ module SQS_SNS
8
+ # TimeoutQueue solves the problem the native Ruby Queue class has with waiting for elements.
9
+ #
10
+ # See the excellent blog post discussing the issue:
11
+ # https://medium.com/workday-engineering/ruby-concurrency-building-a-timeout-queue-5d7c588ca80d
12
+ #
13
+ # TLDR -- using Ruby standard Timeout.timeout() around Queue#pop() is unsafe
14
+ #
15
+ #
16
+ class TimeoutQueue
17
+ def initialize
18
+ @elems = []
19
+ @mutex = Mutex.new
20
+ @cond_var = ConditionVariable.new
21
+ end
22
+
23
+ # Pushes an element into the queue
24
+ #
25
+ # @param elem [Object]
26
+ #
27
+ def <<(elem)
28
+ @mutex.synchronize do
29
+ @elems << elem
30
+ @cond_var.signal
31
+ end
32
+ end
33
+ alias push <<
34
+
35
+ # Pops an element from the queue in either non-blocking
36
+ # or a blocking (with an optional timeout) way.
37
+ #
38
+ # @param blocking [true,false] wait for a new element (true) or return immediately
39
+ # @param timeout [nil,Integer] if in blocking mode,
40
+ # wait at most given number of seconds or forever (nil)
41
+ # @raise [Timeout::Error] if a timeout in blocking mode was reached
42
+ #
43
+ def pop(blocking = true, timeout = nil)
44
+ @mutex.synchronize do
45
+ if blocking
46
+ if timeout.nil?
47
+ while @elems.empty?
48
+ @cond_var.wait(@mutex)
49
+ end
50
+ else
51
+ timeout_time = Time.now.to_f + timeout
52
+ while @elems.empty? && (remaining_time = timeout_time - Time.now.to_f) > 0
53
+ @cond_var.wait(@mutex, remaining_time)
54
+ end
55
+ end
56
+ end
57
+ raise Timeout::Error, "queue timeout expired" if @elems.empty?
58
+
59
+ @elems.shift
60
+ end
61
+ end
62
+ end # class TimeoutQueue
63
+ end # module SQS_SNS
64
+ end # module Messaging
65
+ end # module Mimi
@@ -3,7 +3,7 @@
3
3
  module Mimi
4
4
  module Messaging
5
5
  module SQS_SNS
6
- VERSION = "0.7.0"
6
+ VERSION = "0.8.0"
7
7
  end
8
8
  end
9
9
  end
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
36
36
  spec.add_dependency "mimi-messaging", "~> 1.2"
37
37
  spec.add_dependency "aws-sdk-sqs", "~> 1.22"
38
38
  spec.add_dependency "aws-sdk-sns", "~> 1.19"
39
+ spec.add_dependency "concurrent-ruby"
39
40
 
40
41
  spec.add_development_dependency "bundler", "~> 2.0"
41
42
  spec.add_development_dependency "pry", "~> 0.12"
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.7.0
4
+ version: 0.8.0
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-14 00:00:00.000000000 Z
11
+ date: 2021-02-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimi-messaging
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.19'
55
+ - !ruby/object:Gem::Dependency
56
+ name: concurrent-ruby
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: bundler
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -134,6 +148,7 @@ files:
134
148
  - bin/console
135
149
  - bin/setup
136
150
  - examples/event.rb
151
+ - examples/mass-query.rb
137
152
  - examples/query.rb
138
153
  - examples/responder.rb
139
154
  - examples/subscriber.rb
@@ -142,6 +157,7 @@ files:
142
157
  - lib/mimi/messaging/sqs_sns/consumer.rb
143
158
  - lib/mimi/messaging/sqs_sns/reply_consumer.rb
144
159
  - lib/mimi/messaging/sqs_sns/temporary_queue_consumer.rb
160
+ - lib/mimi/messaging/sqs_sns/timeout_queue.rb
145
161
  - lib/mimi/messaging/sqs_sns/version.rb
146
162
  - mimi-messaging-sqs_sns.gemspec
147
163
  homepage: https://github.com/kukushkin/mimi-messaging-sqs_sns