better_sqs 0.1.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 +7 -0
- data/.gitignore +89 -0
- data/.rubocop.yml +75 -0
- data/.rubocop_todo.yml +20 -0
- data/LICENSE +21 -0
- data/README.md +44 -0
- data/better_sqs.gemspec +21 -0
- data/circle.yml +15 -0
- data/lib/better_sqs/client.rb +64 -0
- data/lib/better_sqs/configuration.rb +24 -0
- data/lib/better_sqs/message.rb +43 -0
- data/lib/better_sqs.rb +36 -0
- data/spec/better_sqs/client_spec.rb +94 -0
- data/spec/better_sqs/message_spec.rb +54 -0
- data/spec/better_sqs_spec.rb +76 -0
- data/spec/simplecov_custom_profile.rb +4 -0
- data/spec/spec_helper.rb +5 -0
- data/spec/support/mocks.rb +41 -0
- metadata +166 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c6ab639c3edfc471887f487626ebcebf9b0dbf71
|
4
|
+
data.tar.gz: 43f95965ec9edc194a6f16d3ceec1f406dd36350
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3ef5b247cf8e2974a09c188bc7cb89386487bb53eb7c7665268721b6232da4a4e1b32d2897aeb178d8e983794f3e257b136e6a62f05864094cfa47491a37898f
|
7
|
+
data.tar.gz: e58dbb3e89731bf35022750af27b2cee539ec67552f5209d1ac9985f19b05f3aff27354bc94950adfd4e36161192d6ce70796250f9ec5a046054a256accdc526
|
data/.gitignore
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Created by .ignore support plugin (hsz.mobi)
|
2
|
+
### Ruby template
|
3
|
+
*.gem
|
4
|
+
*.rbc
|
5
|
+
/.config
|
6
|
+
/coverage/
|
7
|
+
/InstalledFiles
|
8
|
+
/pkg/
|
9
|
+
/spec/reports/
|
10
|
+
/test/tmp/
|
11
|
+
/test/version_tmp/
|
12
|
+
/tmp/
|
13
|
+
|
14
|
+
## Specific to RubyMotion:
|
15
|
+
.dat*
|
16
|
+
.repl_history
|
17
|
+
build/
|
18
|
+
|
19
|
+
## Documentation cache and generated files:
|
20
|
+
/.yardoc/
|
21
|
+
/_yardoc/
|
22
|
+
/doc/
|
23
|
+
/rdoc/
|
24
|
+
|
25
|
+
## Environment normalisation:
|
26
|
+
/.bundle/
|
27
|
+
/vendor/bundle
|
28
|
+
/lib/bundler/man/
|
29
|
+
|
30
|
+
# for a library or gem, you might want to ignore these files since the code is
|
31
|
+
# intended to run in multiple environments; otherwise, check them in:
|
32
|
+
# Gemfile.lock
|
33
|
+
# .ruby-version
|
34
|
+
# .ruby-gemset
|
35
|
+
|
36
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
37
|
+
.rvmrc
|
38
|
+
|
39
|
+
|
40
|
+
### JetBrains template
|
41
|
+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion
|
42
|
+
|
43
|
+
*.iml
|
44
|
+
|
45
|
+
## Directory-based project format:
|
46
|
+
.idea/
|
47
|
+
# if you remove the above rule, at least ignore the following:
|
48
|
+
|
49
|
+
# User-specific stuff:
|
50
|
+
# .idea/workspace.xml
|
51
|
+
# .idea/tasks.xml
|
52
|
+
# .idea/dictionaries
|
53
|
+
|
54
|
+
# Sensitive or high-churn files:
|
55
|
+
# .idea/dataSources.ids
|
56
|
+
# .idea/dataSources.xml
|
57
|
+
# .idea/sqlDataSources.xml
|
58
|
+
# .idea/dynamic.xml
|
59
|
+
# .idea/uiDesigner.xml
|
60
|
+
|
61
|
+
# Gradle:
|
62
|
+
# .idea/gradle.xml
|
63
|
+
# .idea/libraries
|
64
|
+
|
65
|
+
# Mongo Explorer plugin:
|
66
|
+
# .idea/mongoSettings.xml
|
67
|
+
|
68
|
+
## File-based project format:
|
69
|
+
*.ipr
|
70
|
+
*.iws
|
71
|
+
|
72
|
+
## Plugin-specific files:
|
73
|
+
|
74
|
+
# IntelliJ
|
75
|
+
/out/
|
76
|
+
|
77
|
+
# mpeltonen/sbt-idea plugin
|
78
|
+
.idea_modules/
|
79
|
+
|
80
|
+
# JIRA plugin
|
81
|
+
atlassian-ide-plugin.xml
|
82
|
+
|
83
|
+
# Crashlytics plugin (for Android Studio and IntelliJ)
|
84
|
+
com_crashlytics_export_strings.xml
|
85
|
+
crashlytics.properties
|
86
|
+
crashlytics-build.properties
|
87
|
+
|
88
|
+
|
89
|
+
projectFilesBackup
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
inherit_from: .rubocop_todo.yml
|
2
|
+
|
3
|
+
Lint/UselessAssignment:
|
4
|
+
Enabled: true
|
5
|
+
|
6
|
+
Lint/UnusedMethodArgument:
|
7
|
+
Enabled: true
|
8
|
+
|
9
|
+
Lint/UnusedBlockArgument:
|
10
|
+
Enabled: true
|
11
|
+
|
12
|
+
Metrics/AbcSize:
|
13
|
+
Exclude:
|
14
|
+
- spec/**/*
|
15
|
+
|
16
|
+
Style/DotPosition:
|
17
|
+
Enabled: true
|
18
|
+
EnforcedStyle: trailing
|
19
|
+
|
20
|
+
Style/PercentLiteralDelimiters:
|
21
|
+
PreferredDelimiters:
|
22
|
+
'%': () # interpolated String
|
23
|
+
'%i': '[]' # Array of symbols
|
24
|
+
'%q': () # Single quoted string
|
25
|
+
'%Q': () # Double quoted string
|
26
|
+
'%r': '{}' # Regex
|
27
|
+
'%s': () # Symbol
|
28
|
+
'%w': '[]' # Array of strings
|
29
|
+
'%W': '[]' # Array of strings, interpolated
|
30
|
+
'%x': () # shell command
|
31
|
+
|
32
|
+
Style/StringLiterals:
|
33
|
+
EnforcedStyle: double_quotes
|
34
|
+
|
35
|
+
Style/CollectionMethods:
|
36
|
+
Enabled: true
|
37
|
+
# Mapping from undesired method to desired_method
|
38
|
+
# e.g. use `detect` over `find`:
|
39
|
+
PreferredMethods:
|
40
|
+
find: 'detect'
|
41
|
+
find_all: 'select'
|
42
|
+
|
43
|
+
Style/AlignHash:
|
44
|
+
EnforcedHashRocketStyle: table
|
45
|
+
EnforcedColonStyle: table
|
46
|
+
|
47
|
+
Style/AndOr:
|
48
|
+
# Whether `and` and `or` are banned only in conditionals (conditionals)
|
49
|
+
# or completely (always).
|
50
|
+
EnforcedStyle: conditionals # and/or are sometimes used for flow control.
|
51
|
+
|
52
|
+
Style/BlockDelimiters:
|
53
|
+
EnforcedStyle: semantic
|
54
|
+
|
55
|
+
Style/HashSyntax:
|
56
|
+
EnforcedStyle: ruby19_no_mixed_keys
|
57
|
+
|
58
|
+
Style/NumericLiterals:
|
59
|
+
MinDigits: 5
|
60
|
+
|
61
|
+
Style/SingleSpaceBeforeFirstArg:
|
62
|
+
Enabled: false
|
63
|
+
|
64
|
+
# Configuration parameters: EnforcedStyleForMultiline, SupportedStyles.
|
65
|
+
Style/TrailingComma:
|
66
|
+
EnforcedStyleForMultiline: comma
|
67
|
+
|
68
|
+
Style/SingleLineBlockParams:
|
69
|
+
Enabled: false
|
70
|
+
|
71
|
+
Style/EachWithObject:
|
72
|
+
Enabled: false
|
73
|
+
|
74
|
+
Style/Lambda:
|
75
|
+
Enabled: false
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2016-01-26 02:10:21 +0000 using RuboCop version 0.35.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 15
|
10
|
+
# Configuration parameters: AllowURI, URISchemes.
|
11
|
+
Metrics/LineLength:
|
12
|
+
Max: 173
|
13
|
+
|
14
|
+
# Offense count: 1
|
15
|
+
# Configuration parameters: Exclude.
|
16
|
+
Style/Documentation:
|
17
|
+
Exclude:
|
18
|
+
- 'spec/**/*'
|
19
|
+
- 'test/**/*'
|
20
|
+
- 'lib/better_sqs.rb'
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Referly
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# Better SQS
|
2
|
+
|
3
|
+
Making it _easier_ for you to quickly interact with SQS in an idiomatic fashion.
|
4
|
+
|
5
|
+
## Status
|
6
|
+
|
7
|
+
[](https://circleci.com/gh/Referly/better_sqs)
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require "better_sqs"
|
13
|
+
|
14
|
+
better = BetterSqs::Client.new
|
15
|
+
better.push "better_sqs_dev_queue", "You pushed the message successfully!"
|
16
|
+
# At this point you can confirm that the message was enqueued in the AWS console
|
17
|
+
message = better.reserve "better_sqs_dev_queue"
|
18
|
+
|
19
|
+
puts message.message_body
|
20
|
+
|
21
|
+
message.delete
|
22
|
+
```
|
23
|
+
|
24
|
+
## Configuration
|
25
|
+
|
26
|
+
To configure BetterSqs use the configuration block pattern
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
require "better_sqs"
|
30
|
+
BetterSqs.configure do |config|
|
31
|
+
# When a message is deferred, this number of seconds is added to the time period that the message
|
32
|
+
# will remain invisible to other consumers. SQS has a hard cap of 12 hours on visibility.
|
33
|
+
# It defaults to 60 seconds
|
34
|
+
config.sqs_message_deferral_seconds = 120
|
35
|
+
|
36
|
+
# If you want to hardcode which region of SQS should be used then you can set this option. It is recommended
|
37
|
+
# to use the environment variable ENV["AWS_REGION"] instead
|
38
|
+
config.region = "us-west-2"
|
39
|
+
|
40
|
+
# for aws_access_key_id and aws_secret_access_key you can set them in this fashion, but it is strongly
|
41
|
+
# recommended that you just use the environment variables instead: ENV["AWS_ACCESS_KEY_ID"],
|
42
|
+
# ENV["AWS_SECRET_ACCESS_KEY"]
|
43
|
+
end
|
44
|
+
```
|
data/better_sqs.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "better_sqs"
|
3
|
+
s.version = "0.1.0"
|
4
|
+
s.license = "MIT"
|
5
|
+
s.date = "2016-01-26"
|
6
|
+
s.summary = "A more idiomatic interface to SQS."
|
7
|
+
s.description = "A convenient API for developers to interact with SQS with a trivial amount of effort"
|
8
|
+
s.authors = ["Courtland Caldwell"]
|
9
|
+
s.email = "engineering@mattermark.com"
|
10
|
+
s.files = `git ls-files`.split("\n") - %w[Gemfile Gemfile.lock]
|
11
|
+
s.test_files = `git ls-files -- {spec,features}/*`.split("\n")
|
12
|
+
s.homepage =
|
13
|
+
"https://github.com/Referly/better_sqs"
|
14
|
+
s.add_runtime_dependency "lincoln_logger", "~> 1.0" # Mattermark gem
|
15
|
+
s.add_runtime_dependency "aws-sdk", "~> 2" # Apache2 https://github.com/aws/aws-sdk-ruby/blob/master/LICENSE.txt
|
16
|
+
s.add_development_dependency "rspec", "~> 3.2" # MIT - @link https://github.com/rspec/rspec/blob/master/License.txt
|
17
|
+
s.add_development_dependency "byebug", "~> 3.5" # BSD (content is BSD) https://github.com/deivid-rodriguez/byebug/blob/master/LICENSE
|
18
|
+
s.add_development_dependency "simplecov", "~> 0.10" # MIT - @link https://github.com/colszowka/simplecov/blob/master/MIT-LICENSE
|
19
|
+
s.add_development_dependency "rubocop", "~> 0.31" # Create Commons Attribution-NonCommerical https://github.com/bbatsov/rubocop/blob/master/LICENSE.txt
|
20
|
+
s.add_development_dependency "rspec_junit_formatter", "~> 0.2" # MIT https://github.com/sj26/rspec_junit_formatter/blob/master/LICENSE
|
21
|
+
end
|
data/circle.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
machine:
|
2
|
+
|
3
|
+
timezone:
|
4
|
+
America/Los_Angeles # Set the timezone
|
5
|
+
|
6
|
+
# Version of ruby to use
|
7
|
+
ruby:
|
8
|
+
version:
|
9
|
+
2.1.3
|
10
|
+
|
11
|
+
test:
|
12
|
+
override:
|
13
|
+
- bundle exec rubocop
|
14
|
+
- mkdir -p $CIRCLE_TEST_REPORTS/rspec
|
15
|
+
- bundle exec rspec --format RspecJunitFormatter --out $CIRCLE_TEST_REPORTS/rspec/rspec.xml spec --format progress
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require "aws-sdk"
|
2
|
+
module BetterSqs
|
3
|
+
# A class that wraps the aws sdk v2 SQS client to reduce interface complexity
|
4
|
+
class Client
|
5
|
+
attr_accessor :sqs
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
# if BetterSqs has not been configured then run the default configuration
|
9
|
+
BetterSqs.configure unless BetterSqs.configured?
|
10
|
+
end
|
11
|
+
|
12
|
+
# Push a message onto a queue
|
13
|
+
#
|
14
|
+
# @param queue_name [String, Symbol] the name of the queue that the message should pushed onto
|
15
|
+
# @param message_body [String] the message as it will be pushed onto the queue, no serialization occurs as
|
16
|
+
# part of this method. You need to encode or serialize your object to a string before sending it to this method
|
17
|
+
# @return [Types::SendMessageResult] the sent message object returned from s3
|
18
|
+
def push(queue_name, message_body)
|
19
|
+
sqs.send_message(queue_url: url_for_queue(queue_name), message_body: message_body)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Reserve a message from the specified queue
|
23
|
+
#
|
24
|
+
# @param queue_name [String, Symbol] the name of the SQS queue to reserve a message from
|
25
|
+
# @return [Messages::Sqs, NilClass] the message retrieved from the queue
|
26
|
+
def reserve(queue_name)
|
27
|
+
resp = sqs.receive_message(queue_url: url_for_queue(queue_name), max_number_of_messages: 1)
|
28
|
+
return nil unless resp.messages.any?
|
29
|
+
Message.new queue_client: self, queue: queue_name, sqs_message: resp.messages.first
|
30
|
+
end
|
31
|
+
|
32
|
+
# Delete a message from the queue
|
33
|
+
#
|
34
|
+
# @param message [Messages::Sqs] the message that should be deleted
|
35
|
+
def delete(message)
|
36
|
+
sqs.delete_message queue_url: url_for_queue(message.queue), receipt_handle: message.receipt_handle
|
37
|
+
end
|
38
|
+
|
39
|
+
# Updates the message visibility timeout to create some delay before an attempt will be made to reprocess the
|
40
|
+
# message
|
41
|
+
#
|
42
|
+
# @param message [Messages::Sqs] the message for which the next retry should be delayed
|
43
|
+
def defer_retry(message)
|
44
|
+
sqs.change_message_visibility queue_url: url_for_queue(message.queue),
|
45
|
+
receipt_handle: message.receipt_handle,
|
46
|
+
visibility_timeout: BetterSqs.configuration.sqs_message_deferral_seconds
|
47
|
+
end
|
48
|
+
|
49
|
+
# Get the existing or create a new instances of the SQS client
|
50
|
+
#
|
51
|
+
# @return [Aws::SQS::Client] an instance of the SQS client
|
52
|
+
def sqs
|
53
|
+
@sqs ||= Aws::SQS::Client.new
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get the specified queue instance if it already exists, otherwise create it and wait for it to be readied
|
57
|
+
#
|
58
|
+
# @param queue_name [String, Symbol] the name of the queue to be created
|
59
|
+
# @return [AWS::SQS::Queue] the requested queue instance
|
60
|
+
def url_for_queue(queue_name)
|
61
|
+
sqs.create_queue(queue_name: queue_name).queue_url
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module BetterSqs
|
2
|
+
# Provides configuration management for the BetterSqs gem
|
3
|
+
class Configuration
|
4
|
+
attr_accessor :queue_name,
|
5
|
+
:region,
|
6
|
+
:sqs_message_deferral_seconds,
|
7
|
+
:aws_access_key_id,
|
8
|
+
:aws_secret_access_key
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@sqs_message_deferral_seconds = 60
|
12
|
+
@aws_access_key_id = ENV["AWS_ACCESS_KEY_ID"]
|
13
|
+
@aws_secret_access_key = ENV["AWS_SECRET_ACCESS_KEY"]
|
14
|
+
@region = ENV["AWS_REGION"]
|
15
|
+
end
|
16
|
+
|
17
|
+
def configure_aws
|
18
|
+
Aws.config.update(
|
19
|
+
region: region,
|
20
|
+
credentials: Aws::Credentials.new(aws_access_key_id, aws_secret_access_key),
|
21
|
+
)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module BetterSqs
|
2
|
+
# A class that wraps Aws::Types::Message by reducing the size of the interface and adding imperative actions
|
3
|
+
# like deletion of self from a queue.
|
4
|
+
class Message
|
5
|
+
attr_accessor :sqs_message, :queue_client, :queue
|
6
|
+
|
7
|
+
# @param queue_client [Clients::Sqs] a SQS client instance
|
8
|
+
# @param queue [String, Symbol] the name of the queue the message came from
|
9
|
+
# @param sqs_message [Types::Message] the message result object
|
10
|
+
def initialize(queue_client: nil, queue: nil, sqs_message: nil)
|
11
|
+
@queue_client = queue_client
|
12
|
+
@queue = queue
|
13
|
+
@sqs_message = sqs_message
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [String] the receipt handle that is used to uniquely identify this particular receipt of the message
|
17
|
+
def receipt_handle
|
18
|
+
sqs_message.receipt_handle
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [String] the message's body contents
|
22
|
+
def message_body
|
23
|
+
sqs_message.body
|
24
|
+
end
|
25
|
+
alias_method :body, :message_body
|
26
|
+
|
27
|
+
# Delete self from the SQS queue
|
28
|
+
def delete
|
29
|
+
BetterSqs.logger.info "Deleting message from SQS queue."
|
30
|
+
queue_client.delete self
|
31
|
+
end
|
32
|
+
|
33
|
+
# Defer for sqs_message_deferral_seconds the message, before it will be made visible in sqs
|
34
|
+
def defer_retry
|
35
|
+
BetterSqs.logger.warn "Deferring retry processing of the message for #{BetterSqs.configuration.sqs_message_deferral_seconds} in SQS."
|
36
|
+
queue_client.defer_retry self
|
37
|
+
end
|
38
|
+
|
39
|
+
def ==(other)
|
40
|
+
sqs_message == other.sqs_message && queue_client == other.queue_client && queue == other.queue
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/better_sqs.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require "lincoln_logger"
|
2
|
+
require "better_sqs/configuration"
|
3
|
+
require "better_sqs/client"
|
4
|
+
require "better_sqs/message"
|
5
|
+
module BetterSqs
|
6
|
+
class << self
|
7
|
+
# Allows the user to set configuration options
|
8
|
+
# by yielding the configuration block
|
9
|
+
#
|
10
|
+
# @param opts [Hash] an optional hash of options, supported options are `reset: true`
|
11
|
+
# @param block [Block] an optional configuration block
|
12
|
+
# @return [Configuration] the current configuration object
|
13
|
+
def configure(opts = {}, &_block)
|
14
|
+
@configuration = nil if opts.key?(:reset) && opts[:reset]
|
15
|
+
yield(configuration) if block_given?
|
16
|
+
|
17
|
+
configuration.configure_aws
|
18
|
+
configuration
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns the singleton class's configuration object
|
22
|
+
#
|
23
|
+
# @return [Configuration] the current configuration object
|
24
|
+
def configuration
|
25
|
+
@configuration ||= Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def configured?
|
29
|
+
!@configuration.nil?
|
30
|
+
end
|
31
|
+
|
32
|
+
def logger
|
33
|
+
LincolnLogger.logger
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe BetterSqs::Client do
|
4
|
+
subject { described_class.new }
|
5
|
+
|
6
|
+
let(:queue_name) { "anotherqueue" }
|
7
|
+
let(:sqs) { mock_aws_sqs_client queue_url: "sqs://foo/bar" }
|
8
|
+
let(:sqs_message) { mock_sqs_message }
|
9
|
+
|
10
|
+
before do
|
11
|
+
subject.sqs = sqs
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#push" do
|
15
|
+
let(:message_body) { "I am an important message" }
|
16
|
+
|
17
|
+
it "enqueues the message into the SQS queue" do
|
18
|
+
expect(sqs).
|
19
|
+
to receive(:send_message).
|
20
|
+
with(queue_url: sqs.url_for_queue(queue_name), message_body: message_body).
|
21
|
+
and_return(double "SendMessageResult")
|
22
|
+
|
23
|
+
subject.push queue_name, message_body
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "#reserve" do
|
28
|
+
let(:receive_message_response) { mock_aws_sqs_receive_message_response messages: [sqs_message] }
|
29
|
+
before do
|
30
|
+
allow(sqs).to receive(:receive_message).and_return receive_message_response
|
31
|
+
end
|
32
|
+
|
33
|
+
it "retrieves a message from SQS" do
|
34
|
+
expect(sqs).
|
35
|
+
to receive(:receive_message).
|
36
|
+
with(queue_url: sqs.url_for_queue(queue_name), max_number_of_messages: 1).
|
37
|
+
and_return receive_message_response
|
38
|
+
|
39
|
+
subject.reserve queue_name
|
40
|
+
end
|
41
|
+
|
42
|
+
it "wraps the message in a BetterSqs::Message object" do
|
43
|
+
expected_message = BetterSqs::Message.new queue_client: subject,
|
44
|
+
queue: queue_name,
|
45
|
+
sqs_message: sqs_message
|
46
|
+
expect(subject.reserve queue_name).to eq expected_message
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#delete" do
|
51
|
+
it "deletes a message from SQS" do
|
52
|
+
message_to_delete = BetterSqs::Message.new queue_client: subject,
|
53
|
+
queue: queue_name,
|
54
|
+
sqs_message: sqs_message
|
55
|
+
expect(sqs).
|
56
|
+
to receive(:delete_message).
|
57
|
+
with(queue_url: sqs.url_for_queue(queue_name), receipt_handle: sqs_message.receipt_handle)
|
58
|
+
|
59
|
+
subject.delete message_to_delete
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "#url_for_queue" do
|
64
|
+
let(:mock_queue) {
|
65
|
+
mq = SqsMocks::MockQueue.new
|
66
|
+
mq.queue_name = queue_name
|
67
|
+
mq.queue_url = sqs.queue_url
|
68
|
+
mq
|
69
|
+
}
|
70
|
+
it "creates the queue" do
|
71
|
+
expect(sqs).to receive(:create_queue).with(queue_name: queue_name).and_return mock_queue
|
72
|
+
subject.url_for_queue queue_name
|
73
|
+
end
|
74
|
+
|
75
|
+
it "is the queue_url for the queue" do
|
76
|
+
expect(subject.url_for_queue queue_name).to eq sqs.queue_url
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "#defer_retry" do
|
81
|
+
it "increases the visibility timeout for the message" do
|
82
|
+
message_to_defer = BetterSqs::Message.new queue_client: subject,
|
83
|
+
queue: queue_name,
|
84
|
+
sqs_message: sqs_message
|
85
|
+
|
86
|
+
expect(sqs).
|
87
|
+
to receive(:change_message_visibility).
|
88
|
+
with(queue_url: sqs.url_for_queue(queue_name),
|
89
|
+
receipt_handle: message_to_defer.receipt_handle,
|
90
|
+
visibility_timeout: BetterSqs.configuration.sqs_message_deferral_seconds)
|
91
|
+
subject.defer_retry message_to_defer
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe BetterSqs::Message do
|
4
|
+
let(:queue_client) { mock_queue_client }
|
5
|
+
let(:queue) { "queue_name" }
|
6
|
+
let(:sqs_message) { mock_sqs_message }
|
7
|
+
|
8
|
+
subject { described_class.new }
|
9
|
+
|
10
|
+
describe "creating a new QueueMessage instance" do
|
11
|
+
{
|
12
|
+
queue_client: :imagine_i_am_a_queue_client,
|
13
|
+
queue: "queue_name",
|
14
|
+
sqs_message: "I like to eat peanut butter.",
|
15
|
+
}.each do |optional_param, value|
|
16
|
+
it "supports #{optional_param} as an optional parameter" do
|
17
|
+
instance = described_class.new optional_param => value
|
18
|
+
expect(instance.public_send optional_param).to eq value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#receipt_handle" do
|
24
|
+
it "is the s3_message's receipt handle" do
|
25
|
+
subject.sqs_message = sqs_message
|
26
|
+
expect(subject.receipt_handle).to eq sqs_message.receipt_handle
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#message_body" do
|
31
|
+
it "is the s3_message's body" do
|
32
|
+
subject.sqs_message = sqs_message
|
33
|
+
expect(subject.message_body).to eq sqs_message.body
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#delete" do
|
38
|
+
it "deletes itself from the SQS queue" do
|
39
|
+
expect(queue_client).to receive(:delete).with(subject).and_return Aws::EmptyStructure
|
40
|
+
subject.queue_client = queue_client
|
41
|
+
|
42
|
+
subject.delete
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#defer_retry" do
|
47
|
+
it "increases the visibility timeout for the message" do
|
48
|
+
expect(queue_client).to receive(:defer_retry).with(subject).and_return Aws::EmptyStructure
|
49
|
+
subject.queue_client = queue_client
|
50
|
+
|
51
|
+
subject.defer_retry
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe BetterSqs do
|
4
|
+
describe "configuring BetterSqs" do
|
5
|
+
describe ".configure" do
|
6
|
+
it "yields an instance of BetterSqs::Configuration to the provided configuration block" do
|
7
|
+
expect { |b| BetterSqs.configure(&b) }.to yield_with_args BetterSqs::Configuration
|
8
|
+
end
|
9
|
+
describe "configurable attributes" do
|
10
|
+
{
|
11
|
+
queue_name: "handsomequeue",
|
12
|
+
region: "us-east-1",
|
13
|
+
}.each do |k, v|
|
14
|
+
describe "#{k}" do
|
15
|
+
let(:key) { k }
|
16
|
+
let(:value) { v }
|
17
|
+
|
18
|
+
let(:configure_block) do
|
19
|
+
proc do |config|
|
20
|
+
config.send "#{key}=", value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is configurable" do
|
25
|
+
described_class.configure(&configure_block)
|
26
|
+
|
27
|
+
expect(described_class.configuration.public_send k).to eq v
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
it "allows the configuration to be reset" do
|
33
|
+
described_class.configure do |c|
|
34
|
+
c.queue_name = "original_queue_name"
|
35
|
+
end
|
36
|
+
first_configuration = described_class.configuration
|
37
|
+
|
38
|
+
described_class.configure(reset: true) do |c|
|
39
|
+
c.region = "ca-1"
|
40
|
+
end
|
41
|
+
|
42
|
+
expect(described_class.configuration).not_to eq first_configuration
|
43
|
+
expect(described_class.configuration.queue_name).not_to eq "original_queue_name"
|
44
|
+
expect(described_class.configuration.region).to eq "ca-1"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "accessing the current BetterSqs configuration" do
|
50
|
+
describe ".configuration" do
|
51
|
+
context "when the BetterSqs has been previously configured" do
|
52
|
+
before do
|
53
|
+
described_class.configure
|
54
|
+
end
|
55
|
+
|
56
|
+
it "is the current configuration of the BetterSqs" do
|
57
|
+
expected_configuration = described_class.instance_variable_get :@configuration
|
58
|
+
|
59
|
+
expect(described_class.configuration).to eq expected_configuration
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when the BetterSqs has not been previously configured" do
|
64
|
+
it "sets the current configuration to a new instance of Configuration" do
|
65
|
+
described_class.configuration
|
66
|
+
|
67
|
+
expect(described_class.instance_variable_get :@configuration).to be_a BetterSqs::Configuration
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns the new Configuration instance" do
|
71
|
+
expect(described_class.configuration).to eq described_class.instance_variable_get :@configuration
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
def mock_queue_client
|
2
|
+
double "QueueClient"
|
3
|
+
end
|
4
|
+
|
5
|
+
def mock_sqs_message
|
6
|
+
double "SqsMessage", receipt_handle: "0111532-2342124", body: "this is the body of the message"
|
7
|
+
end
|
8
|
+
|
9
|
+
def mock_aws_sqs_receive_message_response(messages: [])
|
10
|
+
double "ReceiveMessageResponse", messages: messages
|
11
|
+
end
|
12
|
+
|
13
|
+
module SqsMocks
|
14
|
+
class MockQueue
|
15
|
+
attr_accessor :queue_name, :queue_url
|
16
|
+
end
|
17
|
+
|
18
|
+
class MockClient
|
19
|
+
attr_accessor :queue_name, :queue_url
|
20
|
+
|
21
|
+
def initialize(queue_url)
|
22
|
+
@queue_url = queue_url
|
23
|
+
end
|
24
|
+
|
25
|
+
def create_queue(queue_name)
|
26
|
+
@queue_name = queue_name
|
27
|
+
q = MockQueue.new
|
28
|
+
q.queue_name = queue_name
|
29
|
+
q.queue_url = queue_url
|
30
|
+
q
|
31
|
+
end
|
32
|
+
|
33
|
+
def url_for_queue(_queue_name)
|
34
|
+
@queue_url
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def mock_aws_sqs_client(queue_url: nil)
|
40
|
+
SqsMocks::MockClient.new queue_url
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,166 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: better_sqs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Courtland Caldwell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-01-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: lincoln_logger
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: aws-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.2'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: byebug
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.5'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.5'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.10'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.10'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.31'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.31'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec_junit_formatter
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.2'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0.2'
|
111
|
+
description: A convenient API for developers to interact with SQS with a trivial amount
|
112
|
+
of effort
|
113
|
+
email: engineering@mattermark.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- ".rubocop.yml"
|
120
|
+
- ".rubocop_todo.yml"
|
121
|
+
- LICENSE
|
122
|
+
- README.md
|
123
|
+
- better_sqs.gemspec
|
124
|
+
- circle.yml
|
125
|
+
- lib/better_sqs.rb
|
126
|
+
- lib/better_sqs/client.rb
|
127
|
+
- lib/better_sqs/configuration.rb
|
128
|
+
- lib/better_sqs/message.rb
|
129
|
+
- spec/better_sqs/client_spec.rb
|
130
|
+
- spec/better_sqs/message_spec.rb
|
131
|
+
- spec/better_sqs_spec.rb
|
132
|
+
- spec/simplecov_custom_profile.rb
|
133
|
+
- spec/spec_helper.rb
|
134
|
+
- spec/support/mocks.rb
|
135
|
+
homepage: https://github.com/Referly/better_sqs
|
136
|
+
licenses:
|
137
|
+
- MIT
|
138
|
+
metadata: {}
|
139
|
+
post_install_message:
|
140
|
+
rdoc_options: []
|
141
|
+
require_paths:
|
142
|
+
- lib
|
143
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ">="
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0'
|
148
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
requirements: []
|
154
|
+
rubyforge_project:
|
155
|
+
rubygems_version: 2.2.2
|
156
|
+
signing_key:
|
157
|
+
specification_version: 4
|
158
|
+
summary: A more idiomatic interface to SQS.
|
159
|
+
test_files:
|
160
|
+
- spec/better_sqs/client_spec.rb
|
161
|
+
- spec/better_sqs/message_spec.rb
|
162
|
+
- spec/better_sqs_spec.rb
|
163
|
+
- spec/simplecov_custom_profile.rb
|
164
|
+
- spec/spec_helper.rb
|
165
|
+
- spec/support/mocks.rb
|
166
|
+
has_rdoc:
|