mimi-messaging-sqs_sns 0.4.1 → 0.7.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
- SHA1:
3
- metadata.gz: f0919e38a4926e465f4b2017b98ce6b621a41f5b
4
- data.tar.gz: f356e4552744757c4e6c77eb3eca359839d7d834
2
+ SHA256:
3
+ metadata.gz: b02992abcb101248ebc54069aba5b3887417930b7613a84ed4b6723ad7ce3060
4
+ data.tar.gz: 3b830249dfb56e42a7d380571402c2abef55d74f3e90bf0b9f537e105078cd27
5
5
  SHA512:
6
- metadata.gz: b45642dc502c2bf8e5debf230460594abef63fde87f4f029d5583fdb942965465581be65e0eb050781d2780453f1843644a9c0539849ef1e562062b3370cd47b
7
- data.tar.gz: b5251902e1ac67cad8731f05fdd5a0fe1a7e32db70f4aa62a9f7a29bdb0a2de0c6ff56e82c0fa5b01fabb9d7438fb0411aa62390daf1afe0ceed1ce72c223562
6
+ metadata.gz: 4d6ecfe3d2202124b10ff03129166249f518fca0f15c2e513ba5ab6b2835a713671618eab623fb39e3cbebe3c8351e0688884743e4f69baa3832b1db94a6a858
7
+ data.tar.gz: 5bb7ae92080d112f16a4127b010f7f102ebd71cb53b4701b756e9bbab8c43fae42618969c148fd71f67678dbf34ed4d6c734307a1c84f7201229d5bd95c3907a
data/CHANGELOG.md ADDED
@@ -0,0 +1,12 @@
1
+ # Changelog
2
+
3
+ ## v0.7.0
4
+
5
+ * [#1](https://github.com/kukushkin/mimi-messaging-sqs_sns/pull/1)
6
+ * Added KMS support for creating queues/topics with sever-side encryption enabled
7
+ * Optimized stopping of the adapter: stopping all consumers in parallel
8
+
9
+
10
+ ## v0.6.x
11
+
12
+ * Basic functionality implemented, see missing features in [TODO](TODO.md)
data/README.md CHANGED
@@ -2,6 +2,9 @@
2
2
 
3
3
  AWS SQS/SNS adapter for [mimi-messaging](https://github.com/kukushkin/mimi-messaging).
4
4
 
5
+ * [Changes](CHANGELOG.md)
6
+
7
+
5
8
  ## Installation
6
9
 
7
10
  Add this line to your application's Gemfile:
@@ -43,7 +46,6 @@ Mimi::Messaging.configure(
43
46
  Mimi::Messaging.start
44
47
  ```
45
48
 
46
-
47
49
  ## Contributing
48
50
 
49
51
  Bug reports and pull requests are welcome on GitHub at https://github.com/kukushkin/mimi-messaging-sqs_sns. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
data/TODO.md ADDED
@@ -0,0 +1,9 @@
1
+ # TODO
2
+
3
+ List of missing features planned for future releases.
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)
9
+
data/examples/query.rb CHANGED
@@ -4,10 +4,11 @@ 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
+ AWS_SQS_SNS_KMS_MASTER_KEY_ID = "blah"
11
12
 
12
13
  logger = Logger.new(STDOUT)
13
14
  logger.level = Logger::INFO
@@ -18,7 +19,8 @@ Mimi::Messaging.configure(
18
19
  mq_aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
19
20
  mq_aws_region: AWS_REGION,
20
21
  mq_aws_sqs_endpoint: AWS_SQS_ENDPOINT_URL,
21
- mq_aws_sns_endpoint: AWS_SNS_ENDPOINT_URL
22
+ mq_aws_sns_endpoint: AWS_SNS_ENDPOINT_URL,
23
+ mq_aws_sqs_sns_kms_master_key_id: AWS_SQS_SNS_KMS_MASTER_KEY_ID
22
24
  )
23
25
  adapter = Mimi::Messaging.adapter
24
26
 
@@ -2,11 +2,12 @@
2
2
 
3
3
  require "mimi/messaging/sqs_sns"
4
4
 
5
- AWS_REGION = "eu-west-1"
6
- AWS_SQS_ENDPOINT_URL = "http://localstack:4576"
7
- AWS_SNS_ENDPOINT_URL = "http://localstack:4575"
8
- AWS_ACCESS_KEY_ID = "foo"
5
+ AWS_REGION = "eu-west-1"
6
+ AWS_SQS_ENDPOINT_URL = "http://localstack:4566"
7
+ AWS_SNS_ENDPOINT_URL = "http://localstack:4566"
8
+ AWS_ACCESS_KEY_ID = "foo"
9
9
  AWS_SECRET_ACCESS_KEY = "bar"
10
+ AWS_SQS_SNS_KMS_MASTER_KEY_ID = "blah"
10
11
 
11
12
  class Processor
12
13
  def self.call_command(method_name, message, opts)
@@ -22,7 +23,7 @@ end # class Processor
22
23
 
23
24
 
24
25
  logger = Logger.new(STDOUT)
25
- logger.level = Logger::INFO
26
+ logger.level = Logger::DEBUG
26
27
  Mimi::Messaging.use(logger: logger, serializer: Mimi::Messaging::JsonSerializer)
27
28
  Mimi::Messaging.configure(
28
29
  mq_adapter: "sqs_sns",
@@ -30,7 +31,8 @@ Mimi::Messaging.configure(
30
31
  mq_aws_secret_access_key: AWS_SECRET_ACCESS_KEY,
31
32
  mq_aws_region: AWS_REGION,
32
33
  mq_aws_sqs_endpoint: AWS_SQS_ENDPOINT_URL,
33
- mq_aws_sns_endpoint: AWS_SNS_ENDPOINT_URL
34
+ mq_aws_sns_endpoint: AWS_SNS_ENDPOINT_URL,
35
+ mq_aws_sqs_sns_kms_master_key_id: AWS_SQS_SNS_KMS_MASTER_KEY_ID
34
36
  )
35
37
  adapter = Mimi::Messaging.adapter
36
38
  queue_name = "test"
@@ -47,4 +49,3 @@ ensure
47
49
  puts "Stopping adapter"
48
50
  adapter.stop
49
51
  end
50
-
@@ -12,4 +12,5 @@ end # module Mimi
12
12
 
13
13
  require_relative "sqs_sns/adapter"
14
14
  require_relative "sqs_sns/consumer"
15
+ require_relative "sqs_sns/temporary_queue_consumer"
15
16
  require_relative "sqs_sns/reply_consumer"
@@ -56,7 +56,8 @@ module Mimi
56
56
  mq_aws_sqs_endpoint: nil,
57
57
  mq_aws_sns_endpoint: nil,
58
58
 
59
- mq_aws_sqs_read_timeout: 10, # seconds
59
+ mq_aws_sqs_sns_kms_master_key_id: nil,
60
+ mq_aws_sqs_read_timeout: 20, # seconds
60
61
  }.freeze
61
62
 
62
63
  # Initializes SQS/SNS adapter
@@ -93,6 +94,7 @@ module Mimi
93
94
  # for processors.
94
95
  #
95
96
  def stop_all_processors
97
+ @consumers&.each(&:signal_stop)
96
98
  @consumers&.each(&:stop)
97
99
  @consumers = nil
98
100
  @reply_consumer&.stop
@@ -190,7 +192,7 @@ module Mimi
190
192
  response,
191
193
  __request_id: message.headers[:__request_id]
192
194
  )
193
- deliver_message_queue(reply_to, response_message)
195
+ deliver_query_respone(reply_to, response_message)
194
196
  else
195
197
  processor.call_command(method_name, message, {})
196
198
  end
@@ -219,6 +221,48 @@ module Mimi
219
221
  end
220
222
  end
221
223
 
224
+ # Creates a new queue
225
+ #
226
+ # @param queue_name [String] name of the topic to be created
227
+ # @return [String] a new queue URL
228
+ #
229
+ def create_queue(queue_name)
230
+ fqn = sqs_sns_converted_full_name(queue_name)
231
+ Mimi::Messaging.log "Creating a queue: #{fqn}"
232
+ attrs = {}
233
+ if options[:mq_aws_sqs_sns_kms_master_key_id]
234
+ attrs["KmsMasterKeyId"] = options[:mq_aws_sqs_sns_kms_master_key_id]
235
+ end
236
+ result = sqs_client.create_queue(queue_name: fqn, attributes: attrs)
237
+ result.queue_url
238
+ rescue StandardError => e
239
+ raise Mimi::Messaging::ConnectionError, "Failed to create queue '#{queue_name}': #{e}"
240
+ end
241
+
242
+ # Finds a queue URL for a queue with given name.
243
+ #
244
+ # If an existing queue with this name is not found,
245
+ # the method will try to create a new one.
246
+ #
247
+ # @param queue_name [String]
248
+ # @return [String] a queue URL
249
+ #
250
+ def find_or_create_queue(queue_name)
251
+ queue_registry(queue_name) || create_queue(queue_name)
252
+ end
253
+
254
+ # Deletes a queue identified by the queue URL
255
+ #
256
+ # @param queue_url [String]
257
+ #
258
+ def delete_queue(queue_url)
259
+ Mimi::Messaging.log "Deleting a queue: #{queue_url}"
260
+ sqs_client.delete_queue(queue_url: queue_url)
261
+ rescue StandardError => e
262
+ raise Mimi::Messaging::ConnectionError,
263
+ "Failed to delete queue with url '#{queue_url}': #{e}"
264
+ end
265
+
222
266
  private
223
267
 
224
268
  # Returns configuration parameters for AWS SQS client
@@ -266,20 +310,6 @@ module Mimi
266
310
  end
267
311
  end
268
312
 
269
- # Creates a new queue
270
- #
271
- # @param queue_name [String] name of the topic to be created
272
- # @return [String] a new queue URL
273
- #
274
- def create_queue(queue_name)
275
- fqn = sqs_sns_converted_full_name(queue_name)
276
- Mimi::Messaging.log "Creating a queue: #{fqn}"
277
- result = sqs_client.create_queue(queue_name: fqn)
278
- result.queue_url
279
- rescue StandardError => e
280
- raise Mimi::Messaging::ConnectionError, "Failed to create queue '#{queue_name}': #{e}"
281
- end
282
-
283
313
  # Delivers a message to a queue with given URL.
284
314
  #
285
315
  # @param queue_url [String]
@@ -290,7 +320,8 @@ module Mimi
290
320
  unless message.is_a?(Mimi::Messaging::Message)
291
321
  raise ArgumentError, "Message is expected as argument"
292
322
  end
293
- Mimi::Messaging.log "Delivering message to: #{queue_url}"
323
+
324
+ Mimi::Messaging.log "Delivering message to: #{queue_url}, headers: #{message.headers}"
294
325
  sqs_client.send_message(
295
326
  queue_url: queue_url,
296
327
  message_body: serialize(message),
@@ -302,6 +333,23 @@ module Mimi
302
333
  raise Mimi::Messaging::ConnectionError, "Failed to deliver message to '#{queue_url}': #{e}"
303
334
  end
304
335
 
336
+ # Delivers a message as a response to a QUERY
337
+ #
338
+ # Responses are allowed to fail. There can be a number of reasons
339
+ # why responses fail: reply queue does not exist (anymore?),
340
+ # response message is too big. In any case the error is reported,
341
+ # but the QUERY message is acknowledged as a successfully processed.
342
+ #
343
+ # @param queue_url [String]
344
+ # @param message [Mimi::Messaging::Message]
345
+ #
346
+ def deliver_query_respone(queue_url, message)
347
+ deliver_message_queue(queue_url, message)
348
+ rescue Mimi::Messaging::ConnectionError => e
349
+ Mimi::Messaging.logger&.warn("Failed to deliver QRY response: #{e}")
350
+ # NOTE: error is recovered
351
+ end
352
+
305
353
  # Returns URL of a queue with a given name.
306
354
  #
307
355
  # If the queue with given name does not exist, returns nil
@@ -349,18 +397,6 @@ module Mimi
349
397
  )
350
398
  end
351
399
 
352
- # Finds a queue URL for a queue with given name.
353
- #
354
- # If an existing queue with this name is not found,
355
- # the method will try to create a new one.
356
- #
357
- # @param queue_name [String]
358
- # @return [String] a queue URL
359
- #
360
- def find_or_create_queue(queue_name)
361
- queue_registry(queue_name) || create_queue(queue_name)
362
- end
363
-
364
400
  # Returns the configured reply listener for this process
365
401
  #
366
402
  # @return [ReplyConsumer]
@@ -368,8 +404,7 @@ module Mimi
368
404
  def reply_consumer
369
405
  @reply_consumer ||= begin
370
406
  reply_queue_name = options[:mq_reply_queue_prefix] + SecureRandom.hex(8)
371
- reply_queue_url = create_queue(reply_queue_name)
372
- Mimi::Messaging::SQS_SNS::ReplyConsumer.new(self, reply_queue_url)
407
+ Mimi::Messaging::SQS_SNS::ReplyConsumer.new(self, reply_queue_name)
373
408
  end
374
409
  end
375
410
 
@@ -450,7 +485,11 @@ module Mimi
450
485
  def create_topic(topic_name)
451
486
  fqn = sqs_sns_converted_full_name(topic_name)
452
487
  Mimi::Messaging.log "Creating a topic: #{fqn}"
453
- result = sns_client.create_topic(name: fqn)
488
+ attrs = {}
489
+ if options[:mq_aws_sqs_sns_kms_master_key_id]
490
+ attrs["KmsMasterKeyId"] = options[:mq_aws_sqs_sns_kms_master_key_id]
491
+ end
492
+ result = sns_client.create_topic(name: fqn, attributes: attrs)
454
493
  result.topic_arn
455
494
  rescue StandardError => e
456
495
  raise Mimi::Messaging::ConnectionError, "Failed to create topic '#{topic_name}': #{e}"
@@ -467,7 +506,7 @@ module Mimi
467
506
  )
468
507
  queue_arn = result.attributes["QueueArn"]
469
508
  Mimi::Messaging.log "Subscribing queue to a topic: '#{topic_arn}'->'#{queue_url}'"
470
- result = sns_client.subscribe(
509
+ _result = sns_client.subscribe(
471
510
  topic_arn: topic_arn,
472
511
  protocol: "sqs",
473
512
  endpoint: queue_arn,
@@ -489,6 +528,7 @@ module Mimi
489
528
  unless message.is_a?(Mimi::Messaging::Message)
490
529
  raise ArgumentError, "Message is expected as argument"
491
530
  end
531
+
492
532
  Mimi::Messaging.log "Delivering message to: #{topic_arn}"
493
533
  sns_client.publish(
494
534
  topic_arn: topic_arn,
@@ -4,25 +4,28 @@ module Mimi
4
4
  module Messaging
5
5
  module SQS_SNS
6
6
  #
7
- # Message processor for SQS queues
7
+ # Message consumer for SQS queues
8
8
  #
9
9
  class Consumer
10
10
  def initialize(adapter, queue_url, &block)
11
- @block = block
12
11
  @stop_requested = false
13
12
  Mimi::Messaging.log "Starting consumer for: #{queue_url}"
14
13
  @consumer_thread = Thread.new do
15
- while not @stop_requested do
16
- message = read_message(adapter, queue_url)
17
- next unless message
18
- Mimi::Messaging.log "Read message from: #{queue_url}"
19
- block.call(message)
20
- ack_message(adapter, queue_url, message)
14
+ while not @stop_requested
15
+ read_and_process_message(adapter, queue_url, block)
21
16
  end
22
17
  Mimi::Messaging.log "Stopping consumer for: #{queue_url}"
23
18
  end
24
19
  end
25
20
 
21
+ # Requests the Consumer to stop, without actually waiting for it
22
+ #
23
+ def signal_stop
24
+ @stop_requested = true
25
+ end
26
+
27
+ # Requests the Consumer to stop AND waits until it does
28
+ #
26
29
  def stop
27
30
  @stop_requested = true
28
31
  @consumer_thread.join
@@ -30,6 +33,27 @@ module Mimi
30
33
 
31
34
  private
32
35
 
36
+ # A method invoked in a loop to read/wait for a message
37
+ # from the associated queue and process it
38
+ #
39
+ # @param adapter [Mimi::Messaging::SQS_SNS::Adapter]
40
+ # @param queue_url [String]
41
+ # @param block [Proc] a block to be invoked when a message is received
42
+ #
43
+ def read_and_process_message(adapter, queue_url, block)
44
+ message = read_message(adapter, queue_url)
45
+ return unless message
46
+
47
+ Mimi::Messaging.log "Read message from: #{queue_url}"
48
+ block.call(message)
49
+ ack_message(adapter, queue_url, message)
50
+ rescue StandardError => e
51
+ Mimi::Messaging.logger&.error(
52
+ "#{self.class}: failed to read and process message from: #{queue_url}," \
53
+ " error: (#{e.class}) #{e}"
54
+ )
55
+ end
56
+
33
57
  def read_message(adapter, queue_url)
34
58
  result = adapter.sqs_client.receive_message(
35
59
  queue_url: queue_url,
@@ -39,6 +63,7 @@ module Mimi
39
63
  )
40
64
  return nil if result.messages.count == 0
41
65
  return result.messages.first if result.messages.count == 1
66
+
42
67
  raise Mimi::Messaging::ConnectionError, "Unexpected number of messages read"
43
68
  end
44
69
 
@@ -8,25 +8,23 @@ module Mimi
8
8
  # and passes them to registered Queues (see Ruby ::Queue class).
9
9
  #
10
10
  class ReplyConsumer
11
- attr_reader :reply_queue_url
11
+ attr_reader :reply_queue_name, :reply_queue_url
12
12
 
13
- def initialize(adapter, reply_queue_url)
13
+ def initialize(adapter, reply_queue_name)
14
14
  @mutex = Mutex.new
15
15
  @queues = {}
16
16
  @adapter = adapter
17
- @reply_queue_url = reply_queue_url
18
- @consumer = Consumer.new(adapter, reply_queue_url) do |message|
17
+ @reply_queue_name = reply_queue_name
18
+ @consumer = TemporaryQueueConsumer.new(adapter, reply_queue_name) do |message|
19
19
  dispatch_message(message)
20
20
  end
21
+ @reply_queue_url = @consumer.queue_url
21
22
  end
22
23
 
23
24
  def stop
24
- begin
25
- @consumer.stop
26
- rescue StandardError => e
27
- raise Mimi::Messaging::Error, "Failed to stop consumer: #{e}"
28
- end
29
- # TODO: adapter.sqs_client.delete_queue(reply_queue_url)
25
+ @consumer.stop
26
+ rescue StandardError => e
27
+ raise Mimi::Messaging::Error, "Failed to stop reply consumer: #{e}"
30
28
  end
31
29
 
32
30
  # Register a new request_id to listen for.
@@ -65,6 +63,7 @@ module Mimi
65
63
  @mutex.synchronize do
66
64
  headers = deserialize_headers(message)
67
65
  request_id = headers[:__request_id]
66
+ Mimi::Messaging.log "dispatching response, headers:#{headers}"
68
67
  queue = @queues.delete(request_id)
69
68
  end
70
69
  queue&.push(message)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mimi
4
+ module Messaging
5
+ module SQS_SNS
6
+ #
7
+ # Temporary queue consumer creates a temporary queue
8
+ # and attaches to it. The queue will be deleted
9
+ # on consumer shutdown.
10
+ #
11
+ class TemporaryQueueConsumer
12
+ attr_reader :queue_url
13
+
14
+ def initialize(adapter, queue_name, &block)
15
+ @adapter = adapter
16
+ @queue_url = adapter.find_or_create_queue(queue_name)
17
+ @consumer = Consumer.new(adapter, @queue_url, &block)
18
+ end
19
+
20
+ def stop
21
+ @consumer.stop
22
+ @adapter.delete_queue(queue_url)
23
+ rescue StandardError => e
24
+ raise Mimi::Messaging::Error, "Failed to stop temporary queue consumer: #{e}"
25
+ end
26
+ end # class TemporaryQueueConsumer
27
+ end # module SQS_SNS
28
+ end # module Messaging
29
+ end # module Mimi
@@ -3,7 +3,7 @@
3
3
  module Mimi
4
4
  module Messaging
5
5
  module SQS_SNS
6
- VERSION = "0.4.1"
6
+ VERSION = "0.7.0"
7
7
  end
8
8
  end
9
9
  end
@@ -39,6 +39,6 @@ Gem::Specification.new do |spec|
39
39
 
40
40
  spec.add_development_dependency "bundler", "~> 2.0"
41
41
  spec.add_development_dependency "pry", "~> 0.12"
42
- spec.add_development_dependency "rake", "~> 10.0"
42
+ spec.add_development_dependency "rake", "~> 12.0", ">= 12.3.3"
43
43
  spec.add_development_dependency "rspec", "~> 3.0"
44
44
  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.4.1
4
+ version: 0.7.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: 2019-10-14 00:00:00.000000000 Z
11
+ date: 2021-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mimi-messaging
@@ -86,14 +86,20 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '10.0'
89
+ version: '12.0'
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ version: 12.3.3
90
93
  type: :development
91
94
  prerelease: false
92
95
  version_requirements: !ruby/object:Gem::Requirement
93
96
  requirements:
94
97
  - - "~>"
95
98
  - !ruby/object:Gem::Version
96
- version: '10.0'
99
+ version: '12.0'
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 12.3.3
97
103
  - !ruby/object:Gem::Dependency
98
104
  name: rspec
99
105
  requirement: !ruby/object:Gem::Requirement
@@ -118,11 +124,13 @@ files:
118
124
  - ".gitignore"
119
125
  - ".rspec"
120
126
  - ".travis.yml"
127
+ - CHANGELOG.md
121
128
  - CODE_OF_CONDUCT.md
122
129
  - Gemfile
123
130
  - LICENSE.txt
124
131
  - README.md
125
132
  - Rakefile
133
+ - TODO.md
126
134
  - bin/console
127
135
  - bin/setup
128
136
  - examples/event.rb
@@ -133,6 +141,7 @@ files:
133
141
  - lib/mimi/messaging/sqs_sns/adapter.rb
134
142
  - lib/mimi/messaging/sqs_sns/consumer.rb
135
143
  - lib/mimi/messaging/sqs_sns/reply_consumer.rb
144
+ - lib/mimi/messaging/sqs_sns/temporary_queue_consumer.rb
136
145
  - lib/mimi/messaging/sqs_sns/version.rb
137
146
  - mimi-messaging-sqs_sns.gemspec
138
147
  homepage: https://github.com/kukushkin/mimi-messaging-sqs_sns
@@ -157,8 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
157
166
  - !ruby/object:Gem::Version
158
167
  version: '0'
159
168
  requirements: []
160
- rubyforge_project:
161
- rubygems_version: 2.6.14.4
169
+ rubygems_version: 3.1.2
162
170
  signing_key:
163
171
  specification_version: 4
164
172
  summary: AWS SQS/SNS adapter for mimi-messaging