sqewer 6.5.0 → 6.5.1

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: a69e4c565c8d9532e871d74b077188f617fe513519fdc4f72f03ad25ba8c67d2
4
- data.tar.gz: 92b73c32b4f9535fc53868f9ba61a3e579bfbba1244c191fc6c34c5a64bd7e2c
3
+ metadata.gz: cf1c2d6717fda50ce8a72721d00ffcfd2fae867f40f40a07a0cf48cbe94fe17b
4
+ data.tar.gz: fb1622a03a4f540aaa96d24dc3d5d39c5d400b658f371c88dc682844ac784ea5
5
5
  SHA512:
6
- metadata.gz: 339e77231c3b905a5b3477c2bb933d5fadcbb3f6291f30f12b5e4682bc0d858ee9bb1b8da44e1ba59b46b4647cb3bb877b200f180fd78b91e2c775f0c7103755
7
- data.tar.gz: 16eb06ee13263bd2af1ce18af5c8c4c5da20bf95bca329644a7ccce9fbbe77c54ea18769b3d2819e13f7f7c0374be293ec7beaa6f324ded588a1f2313591154b
6
+ metadata.gz: fd4e73838959531d646d0ed69fd8316e85075d3abe96b5362c58ff5de9af27b26cec142273bce674aaadf571275f1f91cf055c305be4b9797edd75eb89b74222
7
+ data.tar.gz: 9f4b9006f504bd4a0a85abea9d3c82bf2c70ccdfecf59095df58a1e6b1b8b3ed0b6ba819778f828c48e5dd1865c1f312c5feda78485e9ceab95565e9559cc870
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ### 6.5.1
2
+ - Also retry on `Aws::SQS::Errors::InternalError` exception when receiving/sending messages. This will make
3
+ the receiving thread more resilient to sudden SQS failures. By the time SQS recovers the receiving thread
4
+ should stay alive.
5
+
1
6
  ### 6.5.0
2
7
  - Adds `$stdout.sync = true` to CLI to flush the logs to STDOUT
3
8
 
data/README.md CHANGED
@@ -20,14 +20,14 @@ and to start processing, in your commandline handler:
20
20
 
21
21
  #!/usr/bin/env ruby
22
22
  require 'my_applicaion'
23
- Sqewer::CLI.run
23
+ Sqewer::CLI.start
24
24
 
25
25
  To add arguments to the job
26
26
 
27
27
  class JobWithArgs
28
28
  include Sqewer::SimpleJob
29
29
  attr_accessor :times
30
-
30
+
31
31
  def run
32
32
  ...
33
33
  end
@@ -88,6 +88,10 @@ Note that at this point only arguments that are raw JSON types are supported:
88
88
 
89
89
  If you need marshalable Ruby types there instead, you might need to implement a custom `Serializer.`
90
90
 
91
+ ### Sqewer::SimpleJob
92
+
93
+ The module `Sqewer::SimpleJob` can be included to a job class to add some features, specially dealing with attributes, see more details [here](https://github.com/WeTransfer/sqewer/blob/master/lib/sqewer/simple_job.rb).
94
+
91
95
  ## Jobs spawning dependent jobs
92
96
 
93
97
  If your `run` method on the job object accepts arguments (has non-zero `arity` ) the `ExecutionContext` will
@@ -119,11 +123,11 @@ include all the keyword arguments needed to instantiate the job when executing.
119
123
  def initialize(to:, body:)
120
124
  ...
121
125
  end
122
-
126
+
123
127
  def run()
124
128
  ...
125
129
  end
126
-
130
+
127
131
  def to_h
128
132
  {to: @to, body: @body}
129
133
  end
@@ -151,7 +155,7 @@ conform to the job serialization format used internally. For example, you can ha
151
155
  message = JSON.load(message_blob)
152
156
  return if message['Service'] # AWS test
153
157
  return HandleS3Notification.new(message) if message['Records']
154
-
158
+
155
159
  super # as default
156
160
  end
157
161
  end
@@ -176,7 +180,7 @@ The very minimal executable for running jobs would be this:
176
180
 
177
181
  #!/usr/bin/env ruby
178
182
  require 'my_applicaion'
179
- Sqewer::CLI.run
183
+ Sqewer::CLI.start
180
184
 
181
185
  This will connect to the queue at the URL set in the `SQS_QUEUE_URL` environment variable, and
182
186
  use all the default parameters. The `CLI` module will also set up a signal handler to terminate
@@ -233,9 +237,9 @@ you generate. For example, you could use a pipe. But in a more general case some
233
237
  ActiveRAMGobbler.fetch_stupendously_many_things.each do |...|
234
238
  end
235
239
  end
236
-
240
+
237
241
  _, status = Process.wait2(pid)
238
-
242
+
239
243
  # Raise an error in the parent process to signal Sqewer that the job failed
240
244
  # if the child exited with a non-0 status
241
245
  raise "Child process crashed" unless status.exitstatus && status.exitstatus.zero?
@@ -252,7 +256,7 @@ You can wrap job processing in middleware. A full-featured middleware class look
252
256
  # msg_id is the receipt handle, msg_payload is the message body string, msg_attributes are the message's attributes
253
257
  yield
254
258
  end
255
-
259
+
256
260
  # Surrounds the actual job execution
257
261
  def around_execution(job, context)
258
262
  # job is the actual job you will be running, context is the ExecutionContext.
@@ -378,7 +382,7 @@ products using this library, was a very bad idea (more workload for deployment).
378
382
 
379
383
  ## Why so many configurable components?
380
384
 
381
- Because sometimes your requirements differ just-a-little-bit from what is provided, and you have to swap your
385
+ Because sometimes your requirements differ just-a-little-bit from what is provided, and you have to swap your
382
386
  implementation in instead. One product needs foreign-submitted SQS jobs (S3 notifications). Another product
383
387
  needs a custom Logger subclass. Yet another product needs process-based concurrency on top of threads.
384
388
  Yet another process needs to manage database connections when running the jobs. Have 3-4 of those, and a
@@ -398,7 +402,7 @@ Because I found that a producer-consumer model with a thread pool works quite we
398
402
  the Ruby standard library alone.
399
403
 
400
404
  ## Contributing to the library
401
-
405
+
402
406
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
403
407
  * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
404
408
  * Fork the project.
@@ -52,9 +52,9 @@ class Sqewer::Connection
52
52
  # even after 15 minutes it is either down or the server is misconfigured. Either way it makes no sense to
53
53
  # continue.
54
54
  #
55
- # @return [Array<Message>] an array of Message objects
55
+ # @return [Array<Message>] an array of Message objects
56
56
  def receive_messages
57
- Retriable.retriable on: Seahorse::Client::NetworkingError, tries: MAX_RANDOM_RECEIVE_FAILURES do
57
+ Retriable.retriable on: network_and_aws_sdk_errors, tries: MAX_RANDOM_RECEIVE_FAILURES do
58
58
  response = client.receive_message(
59
59
  queue_url: @queue_url,
60
60
  attribute_names: ['All'],
@@ -69,7 +69,7 @@ class Sqewer::Connection
69
69
  #
70
70
  # @param message_body[String] the message to send
71
71
  # @param kwargs_for_send[Hash] additional arguments for the submit (such as `delay_seconds`).
72
- # Passes the arguments to the AWS SDK.
72
+ # Passes the arguments to the AWS SDK.
73
73
  # @return [void]
74
74
  def send_message(message_body, **kwargs_for_send)
75
75
  send_multiple_messages {|via| via.send_message(message_body, **kwargs_for_send) }
@@ -191,8 +191,12 @@ class Sqewer::Connection
191
191
 
192
192
  private
193
193
 
194
+ def network_and_aws_sdk_errors
195
+ [NotOurFaultAwsError, Seahorse::Client::NetworkingError, Aws::SQS::Errors::InternalError]
196
+ end
197
+
194
198
  def handle_batch_with_retries(method, batch)
195
- Retriable.retriable on: [NotOurFaultAwsError, Seahorse::Client::NetworkingError], tries: MAX_RANDOM_FAILURES_PER_CALL do
199
+ Retriable.retriable on: network_and_aws_sdk_errors, tries: MAX_RANDOM_FAILURES_PER_CALL do
196
200
  resp = client.send(method, queue_url: @queue_url, entries: batch)
197
201
  wrong_messages, aws_failures = resp.failed.partition {|m| m.sender_fault }
198
202
  if wrong_messages.any?
@@ -4,6 +4,13 @@
4
4
  # * initialize() will have keyword access to all accessors, and will ensure you have called each one of them
5
5
  # * to_h() will produce a symbolized Hash with all the properties defined using attr_accessor, and the job_class_name
6
6
  # * inspect() will provide a sensible default string representation for logging
7
+ #
8
+ # This module validates if the attributes defined in the job class are the same as
9
+ # those persisted in the queue. More details on `Sqewer::SimpleJob#initialize`.
10
+ # Because of this, it's required to create a new job class when adding or removing
11
+ # an attribute.
12
+ # This mechanism guarantees strong consistency. Without it, a new deployed job class
13
+ # could process old incompatible payloads.
7
14
  module Sqewer::SimpleJob
8
15
  UnknownJobAttribute = Class.new(Sqewer::Error)
9
16
  MissingAttribute = Class.new(Sqewer::Error)
@@ -53,7 +60,7 @@ module Sqewer::SimpleJob
53
60
  accessor = "#{k}="
54
61
  touched_attributes << k
55
62
  unless respond_to?(accessor)
56
- raise UnknownJobAttribute, "Unknown attribute #{k.inspect} for #{self.class}"
63
+ raise UnknownJobAttribute, "Unknown attribute #{k.inspect} for #{self.class}"
57
64
  end
58
65
 
59
66
  send("#{k}=", v)
@@ -1,3 +1,3 @@
1
1
  module Sqewer
2
- VERSION = '6.5.0'
2
+ VERSION = '6.5.1'
3
3
  end
data/lib/sqewer/worker.rb CHANGED
@@ -91,7 +91,7 @@ class Sqewer::Worker
91
91
 
92
92
  consumers = (1..@num_threads).map do
93
93
  Thread.new do
94
- catch(:goodbye) { loop {take_and_execute} }
94
+ loop { take_and_execute }
95
95
  end
96
96
  end
97
97
 
@@ -233,8 +233,11 @@ class Sqewer::Worker
233
233
  message = @execution_queue.pop(nonblock=true)
234
234
  handle_message(message)
235
235
  rescue ThreadError # Queue is empty
236
- throw :goodbye if stopping?
237
- sleep SLEEP_SECONDS_ON_EMPTY_QUEUE
236
+ if stopping?
237
+ Thread.current.exit
238
+ else
239
+ sleep SLEEP_SECONDS_ON_EMPTY_QUEUE
240
+ end
238
241
  rescue => e # anything else, at or below StandardError that does not need us to quit
239
242
  @logger.error { '[worker] Failed "%s..." with %s: %s' % [message.inspect[0..64], e.class, e.message] }
240
243
  e.backtrace.each { |s| @logger.debug{"\t#{s}"} }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqewer
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.5.0
4
+ version: 6.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julik Tarkhanov
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2020-09-25 00:00:00.000000000 Z
12
+ date: 2021-02-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk-sqs
@@ -285,7 +285,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
285
285
  - !ruby/object:Gem::Version
286
286
  version: '0'
287
287
  requirements: []
288
- rubygems_version: 3.1.2
288
+ rubygems_version: 3.0.6
289
289
  signing_key:
290
290
  specification_version: 4
291
291
  summary: Process jobs from SQS