sqewer 5.0.8 → 5.0.9

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
  SHA1:
3
- metadata.gz: 303e0674eeb56dc7ff4a8056482a828988eb53c5
4
- data.tar.gz: 47762bf5591cac2d28a6a6b7078a97c82a697b45
3
+ metadata.gz: 84caf342300d2128e0e128efe4d235413bf011bc
4
+ data.tar.gz: f695a18f5e6b94a5c1854e4a5eb973ab7066def1
5
5
  SHA512:
6
- metadata.gz: fa6a9832e1833e9ed3ec3b2a316001b4637bc9eeec997474a265aa9242c5b3e490752fa8c12f4d238a5bd6c2ef8a8012ca2e37651d853d4f53b879fc7e253a9e
7
- data.tar.gz: 10327bbbe1e13113f7ed4910c6feb90f29b1148ee0af9f98762eab127287bfa3038be7609709cd76079efea10038b5d06c25ae9c851c796bfc479947dea33892
6
+ metadata.gz: 408c64f831f9441ed93609b07f037dff99de6af2d5ece6daebc95bf604c43a6518e2a9dc18a5c8ec37cdfe5d138f0d1a1b3a82b9b1a6554f4b34832992d275b0
7
+ data.tar.gz: 9b1c80ccadffe1b7f006a3310272d9fbdc715d3c45e22c1fcf8ace0d9bc8e2d300ac27096a745af0e80d031b41b454f60c46c6830263542c512cb7382312cd4d
@@ -1,3 +1,8 @@
1
+ ### 2017-06-16
2
+ - Released v5.0.9 to Rubygems.org.
3
+ - Testing with fake_sqs when the daemon was not running or with a misconfigured SQS_QUEUE_URL could lead to Sqewer seemingly hanging. The actual cause was a _very_ large amount of retries were being performed. The amount of retries has been adjusted to a more reasonable number.
4
+ - An exception in the message fetching thread could lead to the receiving thread silently dying, while leaving the worker threads running without any work to do. Uncaught exceptions in the receiving thread now lead to a graceful shutdown of the worker.
5
+
1
6
  ### 2017-06-12
2
7
  - Released v5.0.8 to Rubygems.org.
3
8
  - Retry sending and deleting messages when `sender_fault=false`.
@@ -9,6 +9,7 @@ class Sqewer::Connection
9
9
  DEFAULT_TIMEOUT_SECONDS = 5
10
10
  BATCH_RECEIVE_SIZE = 10
11
11
  MAX_RANDOM_FAILURES_PER_CALL = 10
12
+ MAX_RANDOM_RECEIVE_FAILURES = 100 # sure to hit the max_elapsed_time of 900 seconds
12
13
 
13
14
  NotOurFaultAwsError = Class.new(StandardError)
14
15
 
@@ -39,14 +40,17 @@ class Sqewer::Connection
39
40
  @queue_url = queue_url
40
41
  end
41
42
 
42
- # Receive at most 10 messages from the queue, and return the array of Message objects.
43
+ # Receive at most 10 messages from the queue, and return the array of Message objects. Retries for at
44
+ # most 900 seconds (15 minutes) and then gives up, thereby crashing the read loop. If SQS is not available
45
+ # even after 15 minutes it is either down or the server is misconfigured. Either way it makes no sense to
46
+ # continue.
43
47
  #
44
48
  # @return [Array<Message>] an array of Message objects
45
49
  def receive_messages
46
- response = client.receive_message(queue_url: @queue_url,
47
- wait_time_seconds: DEFAULT_TIMEOUT_SECONDS, max_number_of_messages: 10)
48
- response.messages.map do | message |
49
- Message.new(message.receipt_handle, message.body)
50
+ Retriable.retriable on: Seahorse::Client::NetworkingError, tries: MAX_RANDOM_RECEIVE_FAILURES do
51
+ response = client.receive_message(queue_url: @queue_url,
52
+ wait_time_seconds: DEFAULT_TIMEOUT_SECONDS, max_number_of_messages: BATCH_RECEIVE_SIZE)
53
+ response.messages.map {|message| Message.new(message.receipt_handle, message.body) }
50
54
  end
51
55
  end
52
56
 
@@ -125,7 +129,7 @@ class Sqewer::Connection
125
129
  private
126
130
 
127
131
  def handle_batch_with_retries(method, batch)
128
- Retriable.retriable on: NotOurFaultAwsError, tries: MAX_RANDOM_FAILURES_PER_CALL do
132
+ Retriable.retriable on: [NotOurFaultAwsError, Seahorse::Client::NetworkingError], tries: MAX_RANDOM_FAILURES_PER_CALL do
129
133
  resp = client.send(method, queue_url: @queue_url, entries: batch)
130
134
  wrong_messages, aws_failures = resp.failed.partition {|m| m.sender_fault }
131
135
  if wrong_messages.any?
@@ -139,27 +143,7 @@ class Sqewer::Connection
139
143
  end
140
144
  end
141
145
 
142
- class RetryWrapper < Struct.new(:sqs_client)
143
- MAX_RETRIES = 1000
144
- # Provide retrying wrappers for all the methods of Aws::SQS::Client that we actually use
145
- [:delete_message_batch, :send_message_batch, :receive_message].each do |retriable_method_name|
146
- define_method(retriable_method_name) do |*args, **kwargs|
147
- tries = 1
148
- begin
149
- sqs_client.public_send(retriable_method_name, *args, **kwargs)
150
- rescue Seahorse::Client::NetworkingError => e
151
- if (tries += 1) >= MAX_RETRIES
152
- raise(e)
153
- else
154
- sleep 0.5
155
- retry
156
- end
157
- end
158
- end
159
- end
160
- end
161
-
162
146
  def client
163
- @client ||= RetryWrapper.new(Aws::SQS::Client.new)
147
+ @client ||= Aws::SQS::Client.new
164
148
  end
165
149
  end
@@ -1,3 +1,3 @@
1
1
  module Sqewer
2
- VERSION = '5.0.8'
2
+ VERSION = '5.0.9'
3
3
  end
@@ -33,6 +33,9 @@ class Sqewer::Worker
33
33
  # @return [Fixnum] the number of worker threads set up for this Worker
34
34
  attr_reader :num_threads
35
35
 
36
+ # @return [Symbol] the current state of this Worker
37
+ attr_reader :state
38
+
36
39
  # Returns a Worker instance, configured based on the default components
37
40
  #
38
41
  # @return [Sqewer::Worker]
@@ -94,22 +97,28 @@ class Sqewer::Worker
94
97
 
95
98
  # Create the provider thread. When the execution queue is exhausted,
96
99
  # grab new messages and place them on the local queue.
100
+ owning_worker = self # self won't be self anymore in the thread
97
101
  provider = Thread.new do
98
102
  loop do
99
- break if stopping?
100
-
101
- if queue_has_capacity?
102
- messages = @connection.receive_messages
103
- if messages.any?
104
- messages.each {|m| @execution_queue << m }
105
- @logger.debug { "[worker] Received and buffered %d messages" % messages.length } if messages.any?
103
+ begin
104
+ break if stopping?
105
+
106
+ if queue_has_capacity?
107
+ messages = @connection.receive_messages
108
+ if messages.any?
109
+ messages.each {|m| @execution_queue << m }
110
+ @logger.debug { "[worker] Received and buffered %d messages" % messages.length } if messages.any?
111
+ else
112
+ @logger.debug { "[worker] No messages received" }
113
+ Thread.pass
114
+ end
106
115
  else
107
- @logger.debug { "[worker] No messages received" }
108
- Thread.pass
116
+ @logger.debug { "[worker] Cache is full (%d items), postponing receive" % @execution_queue.length }
117
+ sleep SLEEP_SECONDS_ON_EMPTY_QUEUE
109
118
  end
110
- else
111
- @logger.debug { "[worker] Cache is full (%d items), postponing receive" % @execution_queue.length }
112
- sleep SLEEP_SECONDS_ON_EMPTY_QUEUE
119
+ rescue StandardError => e
120
+ @logger.fatal "Exiting because message receiving thread died. Exception causing this: #{e.inspect}"
121
+ owning_worker.stop # allow any queues and/or running jobs to complete
113
122
  end
114
123
  end
115
124
  end
@@ -158,7 +167,7 @@ class Sqewer::Worker
158
167
  true
159
168
  end
160
169
 
161
- # Peforms a hard shutdown by killing all the threads
170
+ # Performs a hard shutdown by killing all the threads
162
171
  def kill
163
172
  @state.transition! :stopping
164
173
  @logger.info { '[worker] Killing (unclean shutdown), will kill all threads'}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqewer
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.8
4
+ version: 5.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-12 00:00:00.000000000 Z
11
+ date: 2017-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk