eventq_aws 1.16.2 → 1.17.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
  SHA1:
3
- metadata.gz: e15c0b3ea491947a4e5b4def3a7f51bc4d67931e
4
- data.tar.gz: a7de217ebfaa2ff6fb60c9f3ed24502157a48342
3
+ metadata.gz: 060f06ea588d381244367abedaaefa6fa57c6878
4
+ data.tar.gz: 963b83f40dc3d8a00a4e05804912cf8210e23990
5
5
  SHA512:
6
- metadata.gz: 05c258c6081057650aacc7731d464f676bf6f0871938cb2316644948455289470b49ff57e3ed0210dbb59e41b701841919548bf2e778c98a2b7817061b06528a
7
- data.tar.gz: f1f95c3991299bcc67177e3c5158a67fd616a275568e9ae295752047e1b75fc9d7becdc1a17af3d27220949cb80157abc202d597f5bae386868a6c9004df3e9c
6
+ metadata.gz: 62ef5a2468dddb4685ac4e8f486603619a4d86d56ab2cc6babe7255fb6224e439e2202e7358169233f00df0aab867f5525c940f128802d75758c32c71a1b03d9
7
+ data.tar.gz: 958c3cad03b6408dabd2421e224f8b2236a8a0e26e6ede2281e09fb3d6de6b92f8668ec2982a1d060af49ad1f199cb19e231b4c098bbeae8500b5fb1b7269c30
@@ -13,6 +13,9 @@ module EventQ
13
13
 
14
14
  @aws_account = options[:aws_account_number]
15
15
 
16
+ @sns_keep_alive_timeout = options[:sns_keep_alive_timeout] || 30
17
+ @sns_continue_timeout = options[:sns_continue_timeout] || 15
18
+
16
19
  if options.has_key?(:aws_region)
17
20
  @aws_region = options[:aws_region]
18
21
  Aws.config[:region] = @aws_region
@@ -28,7 +31,10 @@ module EventQ
28
31
 
29
32
  # Returns the AWS SNS Client
30
33
  def sns
31
- @sns ||= Aws::SNS::Client.new
34
+ @sns ||= Aws::SNS::Client.new(
35
+ http_idle_timeout: @sns_keep_alive_timeout,
36
+ http_continue_timeout: @sns_continue_timeout
37
+ )
32
38
  end
33
39
 
34
40
  def get_topic_arn(event_type)
@@ -62,7 +68,6 @@ module EventQ
62
68
  def aws_safe_name(name)
63
69
  return name[0..79].gsub(/[^a-zA-Z\d_\-]/,'')
64
70
  end
65
-
66
71
  end
67
72
  end
68
73
  end
@@ -244,10 +244,14 @@ module EventQ
244
244
  payload = JSON.load(msg.body)
245
245
  message = deserialize_message(payload[MESSAGE])
246
246
 
247
- message_args = EventQ::MessageArgs.new(type: message.type,
248
- retry_attempts: retry_attempts,
249
- context: message.context,
250
- content_type: message.content_type)
247
+ message_args = EventQ::MessageArgs.new(
248
+ type: message.type,
249
+ retry_attempts: retry_attempts,
250
+ context: message.context,
251
+ content_type: message.content_type,
252
+ id: message.id,
253
+ sent: message.created
254
+ )
251
255
 
252
256
  EventQ.logger.info("[#{self.class}] - Message received. Retry Attempts: #{retry_attempts}")
253
257
 
@@ -0,0 +1,298 @@
1
+ require 'aws-sdk'
2
+
3
+ module EventQ
4
+ module Amazon
5
+ class QueueWorkerV2
6
+ include EventQ::WorkerId
7
+
8
+ APPROXIMATE_RECEIVE_COUNT = 'ApproximateReceiveCount'.freeze
9
+ MESSAGE = 'Message'.freeze
10
+
11
+ attr_accessor :is_running
12
+
13
+ def initialize
14
+ @forks = []
15
+ @is_running = false
16
+
17
+ @on_retry_exceeded_block = nil
18
+ @on_retry_block = nil
19
+ @on_error_block = nil
20
+
21
+ @hash_helper = HashKit::Helper.new
22
+ @serialization_provider_manager = EventQ::SerializationProviders::Manager.new
23
+ @signature_provider_manager = EventQ::SignatureProviders::Manager.new
24
+
25
+ @queue_poll_wait = 10
26
+ end
27
+
28
+ def start(queue, options = {}, &block)
29
+
30
+ EventQ.logger.info("[#{self.class}] - Preparing to start listening for messages.")
31
+
32
+ configure(queue, options)
33
+
34
+ if options[:client] == nil
35
+ raise "[#{self.class}] - :client (QueueClient) must be specified."
36
+ end
37
+
38
+ raise "[#{self.class}] - Worker is already running." if running?
39
+
40
+ client = options[:client]
41
+ EventQ.logger.debug do
42
+ "[#{self.class} #start] - Listening for messages on queue: #{queue.name}, Queue Url: #{client.get_queue_url(queue)}, Queue arn: #{client.get_queue_arn(queue)}"
43
+ end
44
+
45
+ EventQ.logger.info("[#{self.class}] - Listening for messages.")
46
+
47
+ @forks = []
48
+
49
+ if @fork_count > 1
50
+ Thread.new do
51
+ @fork_count.times do
52
+ pid = fork do
53
+ start_process(options, queue, block)
54
+ end
55
+ @forks.push(pid)
56
+ end
57
+ @forks.each { |pid| Process.wait(pid) }
58
+ end
59
+ else
60
+ start_process(options, queue, block)
61
+ end
62
+
63
+ return true
64
+ end
65
+
66
+ def start_process(options, queue, block)
67
+
68
+ %w'INT TERM'.each do |sig|
69
+ Signal.trap(sig) {
70
+ stop
71
+ exit
72
+ }
73
+ end
74
+
75
+ @is_running = true
76
+
77
+ Thread.new do
78
+ client = options[:client]
79
+ manager = EventQ::Amazon::QueueManager.new({ client: client })
80
+
81
+ queue_url = manager.get_queue(queue)
82
+ poller = Aws::SQS::QueuePoller.new(queue_url, attribute_names: [APPROXIMATE_RECEIVE_COUNT])
83
+
84
+ poller.poll(skip_delete: true) do |msg, stats|
85
+ begin
86
+ tag_processing_thread
87
+ process_message(msg, poller, queue, block)
88
+ rescue => e
89
+ EventQ.logger.error do
90
+ "[#{self.class}] - An unhandled error occurred. Error: #{e} | Backtrace: #{e.backtrace}"
91
+ end
92
+ call_on_error_block(error: e)
93
+ ensure
94
+ untag_processing_thread
95
+ end
96
+ end
97
+ end
98
+
99
+ if (options.key?(:wait) && options[:wait] == true) || (options.key?(:fork_count) && options[:fork_count] > 1)
100
+ while running? do
101
+ sleep 5
102
+ end
103
+ end
104
+ end
105
+
106
+ def call_on_error_block(error:, message: nil)
107
+ if @on_error_block
108
+ EventQ.logger.debug { "[#{self.class}] - Executing on_error block." }
109
+ begin
110
+ @on_error_block.call(error, message)
111
+ rescue => e
112
+ EventQ.logger.error("[#{self.class}] - An error occurred executing the on_error block. Error: #{e}")
113
+ end
114
+ else
115
+ EventQ.logger.debug { "[#{self.class}] - No on_error block specified to execute." }
116
+ end
117
+ end
118
+
119
+ def call_on_retry_exceeded_block(message)
120
+ if @on_retry_exceeded_block != nil
121
+ EventQ.logger.debug { "[#{self.class}] - Executing on_retry_exceeded block." }
122
+ begin
123
+ @on_retry_exceeded_block.call(message)
124
+ rescue => e
125
+ EventQ.logger.error("[#{self.class}] - An error occurred executing the on_retry_exceeded block. Error: #{e}")
126
+ end
127
+ else
128
+ EventQ.logger.debug { "[#{self.class}] - No on_retry_exceeded block specified." }
129
+ end
130
+ end
131
+
132
+ def call_on_retry_block(message)
133
+ if @on_retry_block
134
+ EventQ.logger.debug { "[#{self.class}] - Executing on_retry block." }
135
+ begin
136
+ @on_retry_block.call(message, abort)
137
+ rescue => e
138
+ EventQ.logger.error("[#{self.class}] - An error occurred executing the on_retry block. Error: #{e}")
139
+ end
140
+ else
141
+ EventQ.logger.debug { "[#{self.class}] - No on_retry block specified." }
142
+ end
143
+ end
144
+
145
+ def stop
146
+ EventQ.logger.info("[#{self.class}] - Stopping.")
147
+ @is_running = false
148
+ return true
149
+ end
150
+
151
+ def on_retry_exceeded(&block)
152
+ @retry_exceeded_block = block
153
+ end
154
+
155
+ def on_retry(&block)
156
+ @on_retry_block = block
157
+ return nil
158
+ end
159
+
160
+ def on_error(&block)
161
+ @on_error_block = block
162
+ return nil
163
+ end
164
+
165
+ def running?
166
+ return @is_running
167
+ end
168
+
169
+ def deserialize_message(payload)
170
+ provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
171
+ return provider.deserialize(payload)
172
+ end
173
+
174
+ def serialize_message(msg)
175
+ provider = @serialization_provider_manager.get_provider(EventQ::Configuration.serialization_provider)
176
+ return provider.serialize(msg)
177
+ end
178
+
179
+ private
180
+
181
+ def process_message(msg, poller, queue, block)
182
+ retry_attempts = msg.attributes[APPROXIMATE_RECEIVE_COUNT].to_i - 1
183
+
184
+ # deserialize the message payload
185
+ payload = JSON.load(msg.body)
186
+ message = deserialize_message(payload[MESSAGE])
187
+
188
+ message_args = EventQ::MessageArgs.new(
189
+ type: message.type,
190
+ retry_attempts: retry_attempts,
191
+ context: message.context,
192
+ content_type: message.content_type,
193
+ id: message.id,
194
+ sent: message.created
195
+ )
196
+
197
+ EventQ.logger.info("[#{self.class}] - Message received. Retry Attempts: #{retry_attempts}")
198
+
199
+ @signature_provider_manager.validate_signature(message: message, queue: queue)
200
+
201
+ if(!EventQ::NonceManager.is_allowed?(message.id))
202
+ EventQ.logger.info("[#{self.class}] - Duplicate Message received. Ignoring message.")
203
+ return false
204
+ end
205
+
206
+ # begin worker block for queue message
207
+ begin
208
+
209
+ block.call(message.content, message_args)
210
+
211
+ if message_args.abort == true
212
+ EventQ.logger.info("[#{self.class}] - Message aborted.")
213
+ else
214
+ # accept the message as processed
215
+ poller.delete_message(msg)
216
+ EventQ.logger.info("[#{self.class}] - Message acknowledged.")
217
+ end
218
+
219
+ rescue => e
220
+ EventQ.logger.error("[#{self.class}] - An unhandled error happened while attempting to process a queue message. Error: #{e} | Backtrace: #{e.backtrace}")
221
+ error = true
222
+ call_on_error_block(error: e, message: message)
223
+ end
224
+
225
+ if message_args.abort || error
226
+ EventQ::NonceManager.failed(message.id)
227
+ reject_message(queue, poller, msg, retry_attempts, message, message_args.abort)
228
+ else
229
+ EventQ::NonceManager.complete(message.id)
230
+ end
231
+
232
+ return true
233
+ end
234
+
235
+ def reject_message(queue, poller, msg, retry_attempts, message, abort)
236
+ if !queue.allow_retry || retry_attempts >= queue.max_retry_attempts
237
+ EventQ.logger.info("[#{self.class}] - Message rejected removing from queue. Message: #{serialize_message(message)}")
238
+
239
+ # remove the message from the queue so that it does not get retried again
240
+ poller.delete_message(msg)
241
+
242
+ if retry_attempts >= queue.max_retry_attempts
243
+ EventQ.logger.info("[#{self.class}] - Message retry attempt limit exceeded.")
244
+ call_on_retry_exceeded_block(message)
245
+ end
246
+ elsif queue.allow_retry
247
+ retry_attempts += 1
248
+
249
+ EventQ.logger.info("[#{self.class}] - Message rejected requesting retry. Attempts: #{retry_attempts}")
250
+
251
+ if queue.allow_retry_back_off == true
252
+ EventQ.logger.debug { "[#{self.class}] - Calculating message back off retry delay. Attempts: #{retry_attempts} * Delay: #{queue.retry_delay}" }
253
+ visibility_timeout = (queue.retry_delay * retry_attempts) / 1000
254
+ if visibility_timeout > (queue.max_retry_delay / 1000)
255
+ EventQ.logger.debug { "[#{self.class}] - Max message back off retry delay reached." }
256
+ visibility_timeout = queue.max_retry_delay / 1000
257
+ end
258
+ else
259
+ EventQ.logger.debug { "[#{self.class}] - Setting fixed retry delay for message." }
260
+ visibility_timeout = queue.retry_delay / 1000
261
+ end
262
+
263
+ if visibility_timeout > 43200
264
+ EventQ.logger.debug { "[#{self.class}] - AWS max visibility timeout of 12 hours has been exceeded. Setting message retry delay to 12 hours." }
265
+ visibility_timeout = 43200
266
+ end
267
+
268
+ EventQ.logger.debug { "[#{self.class}] - Sending message for retry. Message TTL: #{visibility_timeout}" }
269
+ poller.change_message_visibility_timeout(msg, visibility_timeout)
270
+
271
+ call_on_retry_block(message)
272
+ end
273
+
274
+ end
275
+
276
+ def configure(queue, options = {})
277
+ @queue = queue
278
+
279
+ if options.key?(:thread_count)
280
+ EventQ.logger.warn("[#{self.class}] - :thread_count is deprecated.")
281
+ end
282
+
283
+ if options.key?(:sleep)
284
+ EventQ.logger.warn("[#{self.class}] - :sleep is deprecated.")
285
+ end
286
+
287
+ @fork_count = 1
288
+ if options.key?(:fork_count)
289
+ @fork_count = options[:fork_count]
290
+ end
291
+
292
+ EventQ.logger.info("[#{self.class}] - Configuring. Process Count: #{@fork_count}.")
293
+
294
+ return true
295
+ end
296
+ end
297
+ end
298
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module EventQ
4
4
  module Amazon
5
- VERSION = "1.16.2"
5
+ VERSION = "1.17.0"
6
6
  end
7
7
  end
data/lib/eventq_aws.rb CHANGED
@@ -12,6 +12,7 @@ if RUBY_PLATFORM =~ /java/
12
12
  require 'eventq_aws/jruby/aws_queue_worker'
13
13
  else
14
14
  require 'eventq_aws/aws_queue_worker'
15
+ require 'eventq_aws/aws_queue_worker_v2'
15
16
  end
16
17
 
17
18
  module EventQ
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: eventq_aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.16.2
4
+ version: 1.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - vaughanbrittonsage
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-30 00:00:00.000000000 Z
11
+ date: 2018-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,20 +66,34 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: eventq_base
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
87
  - - "~>"
74
88
  - !ruby/object:Gem::Version
75
- version: '1.15'
89
+ version: '1.17'
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
94
  - - "~>"
81
95
  - !ruby/object:Gem::Version
82
- version: '1.15'
96
+ version: '1.17'
83
97
  description: This is the aws implementation for EventQ
84
98
  email:
85
99
  - vaughan.britton@sage.com
@@ -94,6 +108,7 @@ files:
94
108
  - lib/eventq_aws/aws_queue_client.rb
95
109
  - lib/eventq_aws/aws_queue_manager.rb
96
110
  - lib/eventq_aws/aws_queue_worker.rb
111
+ - lib/eventq_aws/aws_queue_worker_v2.rb
97
112
  - lib/eventq_aws/aws_status_checker.rb
98
113
  - lib/eventq_aws/aws_subscription_manager.rb
99
114
  - lib/eventq_aws/jruby/aws_queue_worker.rb