mimi-messaging-sqs_sns 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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