active_elastic_job 1.4.0 → 1.4.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
  SHA1:
3
- metadata.gz: 2c8395a6c3ac158c58cf57615c9df6bbe847ea76
4
- data.tar.gz: 33b4188334606d4df92dd4fff85e2fc6a5558629
3
+ metadata.gz: f7f80373d7f57286083c91bfb62632d463df9b7a
4
+ data.tar.gz: 30ad4c79acf1d9a8393092bdf430f7416b606239
5
5
  SHA512:
6
- metadata.gz: e53f0f7464e92f180bbd19af890a8069dbecafab7032865c4eb8f83052c7f01a3497c83383e023c996097875c4208fb70b1274e83e868fb80d50257eaeb53390
7
- data.tar.gz: 44fab25e6c687772f19b01816ee56f94ccefc06e517a541b5aad1363f9a72f289d6a65713f5e663d89a7dda86844d070ca5ad8e4c3f0670b93102b5760958e17
6
+ metadata.gz: 72d3f884abb6f6b16d0c43fe2c537ba64d80acba7e65ff2a97faaea99d16b4e6b45666aeb33f232b95cf227b8d16af172385bc9dfcc5d978720fe97f3ea6742a
7
+ data.tar.gz: b5f4204e84cc39de88f67f321fbc758021b1fbcbb698cc7c991e1a1e0e14b0b9d6d177f92f92191840a01e9e72e29e4b5796886dfa4d2482e310889b89eafda1
@@ -1,4 +1,4 @@
1
- require 'digest'
1
+ require 'openssl'
2
2
  module ActiveElasticJob
3
3
  # This module provides methods that calculate the MD5 digest for Amazon
4
4
  # SQS message bodies and message attributes.
@@ -29,35 +29,30 @@ module ActiveElasticJob
29
29
  'Number' => 1
30
30
  }
31
31
 
32
- CHARSET_ENCODING = Encoding::UTF_8
32
+ NORMALIZED_ENCODING = Encoding::UTF_8
33
33
 
34
- # Returns MD5 digest of +message_body+.
35
34
  def md5_of_message_body(message_body)
36
35
  OpenSSL::Digest::MD5.hexdigest(message_body)
37
36
  end
38
37
 
39
- # Returns MD5 digest of +message_attributes+.
40
- #
41
- # The calculation follows the official algorithm which
42
- # is specified by Amazon.
43
38
  def md5_of_message_attributes(message_attributes)
44
- encoded = message_attributes.each.with_object({ }) do |(name, v), hash|
45
- hash[name.to_s] = ""
46
- data_type = v['data_type'] || v[:data_type]
39
+ encoded = { }
40
+ message_attributes.each do |name, attribute|
41
+ name = name.to_s
42
+ encoded[name] = String.new
43
+ encoded[name] << encode_length_and_bytes(name) <<
44
+ encode_length_and_bytes(attribute[:data_type]) <<
45
+ [TRANSPORT_TYPE_ENCODINGS[attribute[:data_type]]].pack('C'.freeze)
47
46
 
48
- hash[name.to_s] << encode_length_and_bytes(name.to_s) <<
49
- encode_length_and_bytes(data_type) <<
50
- [ TRANSPORT_TYPE_ENCODINGS[data_type] ].pack('C')
51
-
52
- if string_value = v['string_value'] || v[:string_value]
53
- hash[name.to_s] << encode_length_and_string(string_value)
54
- elsif binary_value = v['binary_value'] || v[:binary_value]
55
- hash[name.to_s] << encode_length_and_bytes(binary_value)
47
+ if string_value = attribute[:string_value]
48
+ encoded[name] << encode_length_and_string(string_value)
49
+ elsif binary_value = attribute[:binary_value]
50
+ encoded[name] << encode_length_and_bytes(binary_value)
56
51
  end
57
52
  end
58
53
 
59
- buffer = encoded.keys.sort.reduce("") do |b, name|
60
- b << encoded[name]
54
+ buffer = encoded.keys.sort.reduce(String.new) do |string, name|
55
+ string << encoded[name]
61
56
  end
62
57
  OpenSSL::Digest::MD5.hexdigest(buffer)
63
58
  end
@@ -65,15 +60,13 @@ module ActiveElasticJob
65
60
  private
66
61
 
67
62
  def encode_length_and_string(string)
68
- return '' if string.nil?
69
63
  string = String.new(string)
70
- string.encode!(CHARSET_ENCODING)
64
+ string.encode!(NORMALIZED_ENCODING)
71
65
  encode_length_and_bytes(string)
72
66
  end
73
67
 
74
68
  def encode_length_and_bytes(bytes)
75
- return '' if bytes.nil?
76
- [ bytes.bytesize, bytes ].pack("L>a#{bytes.bytesize}")
69
+ [bytes.bytesize, bytes].pack('L>a*'.freeze)
77
70
  end
78
71
  end
79
72
  end
@@ -13,20 +13,22 @@ module ActiveElasticJob
13
13
  @secret = secret
14
14
  end
15
15
 
16
- def verify!(message, digest)
16
+ def verify(message, digest)
17
17
  if message.nil? || message.blank? || digest.nil? || digest.blank?
18
- raise InvalidDigest
18
+ return false
19
19
  end
20
20
 
21
- unless ActiveSupport::SecurityUtils.secure_compare(digest, generate_digest(message))
22
- raise InvalidDigest
23
- end
24
- true
21
+ return ActiveSupport::SecurityUtils.secure_compare(
22
+ digest, generate_digest(message))
23
+ end
24
+
25
+ def verify!(message, digest)
26
+ raise InvalidDigest unless verify(message, digest)
25
27
  end
26
28
 
27
29
  def generate_digest(message)
28
30
  require 'openssl' unless defined?(OpenSSL)
29
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest.const_get('SHA1').new, @secret, message)
31
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, @secret, message)
30
32
  end
31
33
  end
32
34
  end
@@ -5,8 +5,8 @@ module ActiveElasticJob
5
5
  # This middleware intercepts requests which are sent by the SQS daemon
6
6
  # running in {Amazon Elastic Beanstalk worker environments}[http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features-managing-env-tiers.html].
7
7
  # It does this by looking at the +User-Agent+ header.
8
- # Furthermore, it verifies the digest which is sent along with a legit SQS message,
9
- # and passed as an HTTP header in the resulting request.
8
+ # Furthermore, it verifies the digest which is sent along with a legit SQS
9
+ # message, and passed as an HTTP header in the resulting request.
10
10
  # The digest is based on Rails' +secrets.secret_key_base+.
11
11
  # Therefore, the application running in the web environment, which generates
12
12
  # the digest, and the application running in the worker
@@ -36,11 +36,20 @@ module ActiveElasticJob
36
36
  job = JSON.load(request.body)
37
37
  ActiveJob::Base.execute(job)
38
38
  rescue ActiveElasticJob::MessageVerifier::InvalidDigest => e
39
- return ['403', {CONTENT_TYPE_HEADER_NAME => 'text/plain' }, ["incorrect digest"]]
39
+ return [
40
+ '403',
41
+ {CONTENT_TYPE_HEADER_NAME => 'text/plain' },
42
+ ["incorrect digest"]]
40
43
  rescue StandardError => e
41
- return ['500', {CONTENT_TYPE_HEADER_NAME => 'text/plain' }, [e.message]]
44
+ return [
45
+ '500',
46
+ {CONTENT_TYPE_HEADER_NAME => 'text/plain' },
47
+ [e.message]]
42
48
  end
43
- return [OK_RESPONSE_CODE , {CONTENT_TYPE_HEADER_NAME => CONTENT_TYPE }, [ '' ]]
49
+ return [
50
+ OK_RESPONSE_CODE ,
51
+ {CONTENT_TYPE_HEADER_NAME => CONTENT_TYPE },
52
+ [ '' ]]
44
53
  end
45
54
  @app.call(env)
46
55
  end
@@ -2,7 +2,7 @@ module ActiveElasticJob
2
2
  module VERSION
3
3
  MAJOR = 1
4
4
  MINOR = 4
5
- TINY = 0
5
+ TINY = 1
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
@@ -8,9 +8,11 @@ module ActiveJob
8
8
  # environments}[http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/using-features-managing-env-tiers.html].
9
9
  #
10
10
  # This adapter serializes job objects and sends them as a message to an
11
- # Amazon SQS queue specified by the job's queue name, see <tt>ActiveJob::Base.queue_as</tt>
11
+ # Amazon SQS queue specified by the job's queue name,
12
+ # see <tt>ActiveJob::Base.queue_as</tt>
12
13
  #
13
- # To use Active Elastic Job, set the queue_adapter config to +:active_elastic_job+.
14
+ # To use Active Elastic Job, set the queue_adapter config
15
+ # to +:active_elastic_job+.
14
16
  #
15
17
  # Rails.application.config.active_job.queue_adapter = :active_elastic_job
16
18
  class ActiveElasticJobAdapter
@@ -34,9 +36,9 @@ which exceeds the allowed maximum of #{MAX_MESSAGE_SIZE} bytes imposed by Amazon
34
36
  end
35
37
 
36
38
  # Raised when job queue does not exist. The job queue is determined by
37
- # <tt>ActiveJob::Base.queue_as</tt>. You can either: (1) create a new Amazon
38
- # SQS queue and attach a worker environment to it, or (2) select a different
39
- # queue for your jobs.
39
+ # <tt>ActiveJob::Base.queue_as</tt>. You can either: (1) create a new
40
+ # Amazon SQS queue and attach a worker environment to it, or (2) select a
41
+ # different queue for your jobs.
40
42
  #
41
43
  # Example:
42
44
  # * Open your AWS console and create an SQS queue named +high_priority+ in
@@ -49,12 +51,12 @@ which exceeds the allowed maximum of #{MAX_MESSAGE_SIZE} bytes imposed by Amazon
49
51
  # end
50
52
  class NonExistentQueue < Error
51
53
  def initialize(queue_name)
52
- msg = <<-MSG
53
- The job is bound to queue at #{queue_name}. Unfortunately a queue
54
- with this name does not exist in this region. Either create an Amazon SQS queue
55
- named #{queue_name} - you can do this in AWS console, make sure to select
56
- region '#{ENV['AWS_REGION']}' - or you select another queue for your jobs.
57
- MSG
54
+ msg = "The job is bound to queue at #{queue_name}. " <<
55
+ "Unfortunately a queue with this name does not exist in this " <<
56
+ "region. Either create an Amazon SQS queue named #{queue_name} - " <<
57
+ "you can do this in AWS console, make sure to select region " <<
58
+ "'#{ENV['AWS_REGION']}' - or you select another queue for your jobs."
59
+
58
60
  super msg
59
61
  end
60
62
  end
@@ -62,11 +64,12 @@ region '#{ENV['AWS_REGION']}' - or you select another queue for your jobs.
62
64
  # Raised when calculated MD5 digest does not match the MD5 Digest
63
65
  # of the response from Amazon SQS.
64
66
  class MD5MismatchError < Error
65
- def initialize( message_id)
66
- msg = <<-MSG
67
- MD5 returned by Amazon SQS does not match the calculation on the original request.
68
- The message with Message ID #{message_id} sent to SQS might be corrupted.
69
- MSG
67
+ def initialize(message_id)
68
+ msg = "MD5 returned by Amazon SQS does not match the calculation " <<
69
+ "on the original request. The message with Message ID " <<
70
+ "#{message_id} sent to SQS might be corrupted."
71
+
72
+ super msg
70
73
  end
71
74
  end
72
75
 
@@ -128,13 +131,14 @@ The message with Message ID #{message_id} sent to SQS might be corrupted.
128
131
  def calculate_delay(timestamp)
129
132
  delay = (timestamp - Time.current.to_f).to_i + 1
130
133
  if delay > MAX_DELAY_IN_MINUTES.minutes
131
- msg =<<-MSG
132
- Jobs cannot be scheduled more than #{MAX_DELAY_IN_MINUTES} minutes into the future.
133
- See http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html
134
- for further details!
135
- MSG
136
- raise RangeError
134
+ msg = "Jobs cannot be scheduled more than " <<
135
+ "#{MAX_DELAY_IN_MINUTES} minutes into the future. " <<
136
+ "See http://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SendMessage.html" <<
137
+ " for further details!"
138
+
139
+ raise RangeError, msg
137
140
  end
141
+ delay = 0 if delay < 0
138
142
  delay
139
143
  end
140
144
 
@@ -158,7 +162,7 @@ for further details!
158
162
  @verifier.generate_digest(messsage_body)
159
163
  end
160
164
 
161
- def verify_md5_digests!(response, messsage_body, message_attributes = nil)
165
+ def verify_md5_digests!(response, messsage_body, message_attributes)
162
166
  if md5_of_message_body(messsage_body) != response.md5_of_message_body
163
167
  raise MD5MismatchError, response.message_id
164
168
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_elastic_job
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tawan Sierek
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-09 00:00:00.000000000 Z
11
+ date: 2016-02-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk