cloud_powers 0.2.2 → 0.2.3
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 +4 -4
- data/.gitignore +2 -0
- data/.test.env.example +1 -0
- data/Gemfile.lock +6 -6
- data/cloud_powers.gemspec +4 -3
- data/lib/cloud_powers/.DS_Store +0 -0
- data/lib/cloud_powers/auth.rb +15 -2
- data/lib/cloud_powers/aws_resources.rb +11 -3
- data/lib/cloud_powers/helper.rb +0 -2
- data/lib/cloud_powers/self_awareness.rb +4 -1
- data/lib/cloud_powers/synapse/broadcast/broadcast.rb +85 -0
- data/lib/cloud_powers/synapse/{pipe.rb → pipe/pipe.rb} +1 -1
- data/lib/cloud_powers/synapse/queue/board.rb +116 -0
- data/lib/cloud_powers/synapse/queue/queue.rb +128 -0
- data/lib/cloud_powers/synapse/synapse.rb +11 -2
- data/lib/cloud_powers/version.rb +1 -1
- metadata +11 -7
- data/lib/cloud_powers/synapse/queue.rb +0 -142
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 345005638bc5e69081209792b8b9884ba2db2605
|
|
4
|
+
data.tar.gz: f5b69e0a4d366da8e6512b2ea6062c18bf17dc34
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 09ec8ecacab90dc97ea58cfe3b70c1359d3ed381076403edbca261265bc9eeee71d5e1ace2b5dea55401eb57d2c79c2ea258aef8242846c75ccd57d1eceb2542
|
|
7
|
+
data.tar.gz: e4c21cdb59a03d37fd45d4dba3cf8e3b5d6732a3deaa6351ef7c24220035f5cc42c2f78a81fec804abed81f8d211b3d6441caeecc6d26d021fb93479a2a0d8de
|
data/.gitignore
CHANGED
data/.test.env.example
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
cloud_powers (0.2.
|
|
4
|
+
cloud_powers (0.2.3)
|
|
5
5
|
activesupport-core-ext (~> 4)
|
|
6
6
|
aws-sdk (~> 2)
|
|
7
7
|
dotenv (~> 2.1)
|
|
@@ -13,12 +13,12 @@ GEM
|
|
|
13
13
|
remote: https://rubygems.org/
|
|
14
14
|
specs:
|
|
15
15
|
activesupport-core-ext (4.0.0.3)
|
|
16
|
-
aws-sdk (2.
|
|
17
|
-
aws-sdk-resources (= 2.
|
|
18
|
-
aws-sdk-core (2.
|
|
16
|
+
aws-sdk (2.6.3)
|
|
17
|
+
aws-sdk-resources (= 2.6.3)
|
|
18
|
+
aws-sdk-core (2.6.3)
|
|
19
19
|
jmespath (~> 1.0)
|
|
20
|
-
aws-sdk-resources (2.
|
|
21
|
-
aws-sdk-core (= 2.
|
|
20
|
+
aws-sdk-resources (2.6.3)
|
|
21
|
+
aws-sdk-core (= 2.6.3)
|
|
22
22
|
byebug (9.0.5)
|
|
23
23
|
diff-lcs (1.2.5)
|
|
24
24
|
dotenv (2.1.1)
|
data/cloud_powers.gemspec
CHANGED
|
@@ -14,9 +14,10 @@ Gem::Specification.new do |spec|
|
|
|
14
14
|
CloudPowers is a wrapper around AWS and other cloud services.
|
|
15
15
|
It was developed specifically for the Brain project
|
|
16
16
|
but hopefully can be used in any other ruby project that needs to use cloud
|
|
17
|
-
service providers' resources. Version 0.2.3 has a little EC2, S3, SQS
|
|
18
|
-
Kinesis.
|
|
19
|
-
and
|
|
17
|
+
service providers' resources. Version 0.2.3 has a little EC2, S3, SQS, SNS
|
|
18
|
+
and Kinesis. V-0.2.4 should be out in a day or so and it will include IoT
|
|
19
|
+
basics and specs too. This project is actively being developed, so more
|
|
20
|
+
additions, specs and docs will be updated frequently. I always welcome input.
|
|
20
21
|
Enjoy!
|
|
21
22
|
EOF
|
|
22
23
|
spec.homepage = 'https://github.com/adam-phillipps/cloud_powers'
|
|
Binary file
|
data/lib/cloud_powers/auth.rb
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
require 'aws-sdk'
|
|
2
2
|
Aws.use_bundled_cert!
|
|
3
|
+
require_relative 'zenv'
|
|
3
4
|
|
|
4
5
|
module Smash
|
|
5
6
|
module CloudPowers
|
|
6
7
|
module Auth
|
|
8
|
+
extend Smash::CloudPowers::Zenv
|
|
9
|
+
|
|
10
|
+
# This method is able to be called before an object is instantiated in order
|
|
11
|
+
# to provide a region in AWS-land.
|
|
12
|
+
def self.region
|
|
13
|
+
zfind(:aws_region) || 'us-west-2'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# This method is able to be called before an object is instantiated in order
|
|
17
|
+
# to provide an Aws::Credentials object that will allow access to all the
|
|
18
|
+
# resources in the account that zfind searches for, using the "ACCOUNT_NUMBER"
|
|
19
|
+
# key.
|
|
7
20
|
def self.creds
|
|
8
21
|
@creds ||= Aws::Credentials.new(
|
|
9
|
-
|
|
10
|
-
|
|
22
|
+
zfind(:aws_access_key_id),
|
|
23
|
+
zfind(:aws_secret_access_key)
|
|
11
24
|
)
|
|
12
25
|
end
|
|
13
26
|
end
|
|
@@ -10,7 +10,7 @@ module Smash
|
|
|
10
10
|
include Smash::CloudPowers::Zenv
|
|
11
11
|
|
|
12
12
|
def region
|
|
13
|
-
zfind(
|
|
13
|
+
zfind(:aws_region) || 'us-west-2'
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def ec2
|
|
@@ -34,15 +34,23 @@ module Smash
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def s3
|
|
37
|
-
byebug
|
|
38
37
|
@s3 ||= Aws::S3::Client.new(
|
|
39
38
|
region: region,
|
|
40
39
|
credentials: Auth.creds
|
|
41
40
|
)
|
|
42
41
|
end
|
|
43
42
|
|
|
43
|
+
def sns
|
|
44
|
+
@sns ||= Aws::SNS::Client.new(
|
|
45
|
+
region: region,
|
|
46
|
+
credentials: Auth.creds
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
44
50
|
def sqs
|
|
45
|
-
@sqs ||= Aws::SQS::Client.new(
|
|
51
|
+
@sqs ||= Aws::SQS::Client.new(
|
|
52
|
+
credentials: Auth.creds
|
|
53
|
+
)
|
|
46
54
|
end
|
|
47
55
|
end
|
|
48
56
|
end
|
data/lib/cloud_powers/helper.rb
CHANGED
|
@@ -2,13 +2,11 @@ require 'logger'
|
|
|
2
2
|
require 'pathname'
|
|
3
3
|
require 'syslog/logger'
|
|
4
4
|
require_relative 'smash_error'
|
|
5
|
-
require_relative 'auth'
|
|
6
5
|
require 'byebug'
|
|
7
6
|
|
|
8
7
|
module Smash
|
|
9
8
|
module CloudPowers
|
|
10
9
|
module Helper
|
|
11
|
-
include Smash::CloudPowers::Auth
|
|
12
10
|
|
|
13
11
|
def attr_map!(keys)
|
|
14
12
|
keys.map do |attr|
|
|
@@ -139,8 +139,11 @@ module Smash
|
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
|
|
142
|
+
# This method will return true if:
|
|
143
|
+
# * The run time is more than 5 minutes
|
|
144
|
+
# and
|
|
145
|
+
# * The run time is 5 minutes from the hour mark from when the instance started
|
|
142
146
|
def time_is_up?
|
|
143
|
-
# returns true when the hour mark approaches
|
|
144
147
|
an_hours_time = 60 * 60
|
|
145
148
|
five_minutes_time = 60 * 5
|
|
146
149
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module Smash
|
|
2
|
+
module CloudPowers
|
|
3
|
+
module Synapse
|
|
4
|
+
module Broadcast
|
|
5
|
+
include Smash::CloudPowers::Helper
|
|
6
|
+
include Smash::CloudPowers::AwsResources
|
|
7
|
+
include Smash::CloudPowers::Zenv
|
|
8
|
+
|
|
9
|
+
# A simple Struct to bind the name with the arn of the topic
|
|
10
|
+
Channel = Struct.new(:set_name, :set_arn, :set_endpoint) do
|
|
11
|
+
include Smash::CloudPowers::Zenv
|
|
12
|
+
|
|
13
|
+
# Prefers the given arn but it can make a best guess if none is given
|
|
14
|
+
def arn
|
|
15
|
+
set_arn || "arn:aws:sns:#{zfind(:region)}:#{zfind(:accound_number)}:#{set_name}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Prefers the given name but it can parse the arn to find one
|
|
19
|
+
def name
|
|
20
|
+
set_name || set_arn.split(':').last
|
|
21
|
+
end
|
|
22
|
+
end # end Channel
|
|
23
|
+
#################
|
|
24
|
+
|
|
25
|
+
# Creates a connection point for 1..N nodes to create a connection with the Broadcast
|
|
26
|
+
# def create_distributor(channel)
|
|
27
|
+
# sns.create_application_platform()
|
|
28
|
+
# end
|
|
29
|
+
|
|
30
|
+
# Creates a point to connect to for information about a given topic
|
|
31
|
+
# @params: name <String>: the name of the Channel/Topic to be created
|
|
32
|
+
# @returns: Broadcast::Channel representing the created channel
|
|
33
|
+
def create_channel!(name)
|
|
34
|
+
resp = sns.create_topic(name: name)
|
|
35
|
+
Channel.new(nil, resp.topic_arn)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Deletes a topic from SNS-land
|
|
39
|
+
# @params: channel <Broadcast::Channel>
|
|
40
|
+
def delete_channel!(channel)
|
|
41
|
+
sns.delete_topic(topic_arn: channel.arn)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Creates a connection to the Broadcast so that new messages will be picked up
|
|
45
|
+
# @params: channel <Broadcast::Channel>
|
|
46
|
+
def listen_on(channel)
|
|
47
|
+
sns.subscribe(
|
|
48
|
+
topic_arn: channel.arn,
|
|
49
|
+
protocol: 'application',
|
|
50
|
+
endpoint: channel.endpoint
|
|
51
|
+
)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Lists the created topics in SNS.
|
|
55
|
+
# @returns results <Array
|
|
56
|
+
def real_channels
|
|
57
|
+
results = []
|
|
58
|
+
next_token = ''
|
|
59
|
+
loop do
|
|
60
|
+
resp = sns.list_topics((next_token.empty? ? {} : { next_token: next_token }))
|
|
61
|
+
results.concat(resp.topics.map(&:topic_arn))
|
|
62
|
+
next_token = (resp.next_token.empty? ? '' : resp.next_token)
|
|
63
|
+
break if next_token.empty?
|
|
64
|
+
end
|
|
65
|
+
results
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Send a message to a Channel using SNS#publish
|
|
69
|
+
# @params: [opts <Hash>]:
|
|
70
|
+
# this includes all the keys AWS uses but for now it only has defaults
|
|
71
|
+
# for topic_arn and the message
|
|
72
|
+
def send_broadcast(opts = {})
|
|
73
|
+
msg = opts.delete(:message) || ""
|
|
74
|
+
|
|
75
|
+
package = {
|
|
76
|
+
topic_arn: "topicARN",
|
|
77
|
+
message: msg.to_json
|
|
78
|
+
}.merge(opts)
|
|
79
|
+
|
|
80
|
+
sns.publish(package)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
module Smash
|
|
2
|
+
module CloudPowers
|
|
3
|
+
module Synapse
|
|
4
|
+
module Queue
|
|
5
|
+
# The Queue::Board class helps wrap up information and functionality of a Queue on SQS.
|
|
6
|
+
# It is basically just an abstraction to make using SQS simpler
|
|
7
|
+
class Board
|
|
8
|
+
include Smash::CloudPowers::AwsResources
|
|
9
|
+
include Smash::CloudPowers::Synapse::Queue
|
|
10
|
+
include Smash::CloudPowers::Helper
|
|
11
|
+
include Smash::CloudPowers::Zenv
|
|
12
|
+
|
|
13
|
+
attr_accessor :address, :name, :poller
|
|
14
|
+
|
|
15
|
+
# Takes a `name` and creates a Board object.
|
|
16
|
+
# The #new method is wrapped in #build() and #create!() but isn't labeled private so
|
|
17
|
+
# #new can be used instead of build.
|
|
18
|
+
# The Board doesn't create Queue(s) or any other API calls until it is instructed to.
|
|
19
|
+
# @params: name <String>: the name of the board can be used to find its arn/url etc
|
|
20
|
+
# @returns: Queue::Board
|
|
21
|
+
# not.new
|
|
22
|
+
def initialize(name)
|
|
23
|
+
@name = name
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Gives back a string representation of the instance variable for this board.
|
|
27
|
+
# @returns: instance_variable <String>: the instance variable for this Board in string format
|
|
28
|
+
# Example:
|
|
29
|
+
# board = Board.new(:backlog)
|
|
30
|
+
# Smash.instance_variable_get(board.i_var)
|
|
31
|
+
# #=> Board <name: :backlog ...>
|
|
32
|
+
def i_var
|
|
33
|
+
"@#{@name}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Gives the Queue address (URL). First the environment is searched, using Zenv and if nothing is
|
|
37
|
+
# found, the best guess attempt at the correct address is used.
|
|
38
|
+
# @returns: queue address <String>
|
|
39
|
+
def address
|
|
40
|
+
zfind(@name) || best_guess_address
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Gives a best guess at the URL that points toward this Board's Queue. It uses a couple params
|
|
44
|
+
# to build a standard URL for SQS. The only problem with using this last resort is you may need
|
|
45
|
+
# to use a Queue from a different region, account or name but it can be a handy catch-all for the URLs
|
|
46
|
+
# for most cases.
|
|
47
|
+
def best_guess_address
|
|
48
|
+
"https://sqs.#{zfind(:aws_region)}.amazonaws.com/#{zfind(:account_number)}/#{@name}"
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Builds a Queue::Board object and returns it. No API calls are sent using this method
|
|
52
|
+
# @params: name <String>
|
|
53
|
+
# @returns: Queue::Board
|
|
54
|
+
def self.build(name)
|
|
55
|
+
new(name)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Builds then Creates the Object and makes the API call to SQS to create the queue
|
|
59
|
+
# @params: name <String>
|
|
60
|
+
# @returns: Queue::Board with an actual queue in SQS
|
|
61
|
+
def self.create!(name)
|
|
62
|
+
built_board = build(name)
|
|
63
|
+
built_board.create_queue!
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# Creates an actual Queue in SQS using the standard format for a queue name (camel case)
|
|
67
|
+
# @returns: Queue::Board
|
|
68
|
+
def create_queue!
|
|
69
|
+
sqs.create_queue(queue_name: to_camel(@name))
|
|
70
|
+
self
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
# Deletes an actual Queue from SQS
|
|
74
|
+
def destroy!
|
|
75
|
+
sqs.delete_queue(queue_url: address)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Predicate method to query SQS for the queue
|
|
79
|
+
def exists?
|
|
80
|
+
queue_exists?(@name)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Gets the approximate message count for a Queue using the 'ApproximateMessageCount' attribute
|
|
84
|
+
def message_count
|
|
85
|
+
get_queue_message_count(address)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Gets a QueuePoller for the Queue attached to this Board instance
|
|
89
|
+
def poller
|
|
90
|
+
@poller ||= Aws::SQS::QueuePoller.new(address)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Retrieves a message from the Queue and deletes it from the Queue in SQS
|
|
94
|
+
def pluck_message
|
|
95
|
+
pluck_queue_message(@name)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# This method creates the queue in SQS for the given Board instance
|
|
99
|
+
# It can be coupled with the #build() method in order to use a queue without
|
|
100
|
+
# making the call to create it on AWS
|
|
101
|
+
def save!
|
|
102
|
+
create_queue!
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Sends the given message to the queue
|
|
106
|
+
# @params: message, which is either used as JSON or converted into it
|
|
107
|
+
def send_message(message)
|
|
108
|
+
send_queue_message(
|
|
109
|
+
address, (valid_json?(message) ? message : message.to_json)
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require_relative 'board'
|
|
3
|
+
|
|
4
|
+
module Smash
|
|
5
|
+
module CloudPowers
|
|
6
|
+
module Synapse
|
|
7
|
+
module Queue
|
|
8
|
+
include Smash::CloudPowers::Helper
|
|
9
|
+
include Smash::CloudPowers::AwsResources
|
|
10
|
+
|
|
11
|
+
# This method can be used to parse a queue name from its address. It can be handy if you need the name
|
|
12
|
+
# of a queue but you don't want the overhead of creating a Board object.
|
|
13
|
+
def board_name(url)
|
|
14
|
+
url.to_s.split('/').last
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# This method allows you to create a queue on SQS without explicitly creating a Board object
|
|
18
|
+
# @params: name <String>: The name of the queue to be created
|
|
19
|
+
# @returns: Queue::Board
|
|
20
|
+
def create_queue!(name)
|
|
21
|
+
begin
|
|
22
|
+
Board.create!(to_camel(name))
|
|
23
|
+
rescue Aws::SQS::Errors::QueueDeletedRecently => e
|
|
24
|
+
sleep 5
|
|
25
|
+
retry
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# This method builds a Queue::Board object for you to use but doesn't invoke the #create! method, so
|
|
30
|
+
# no API call is made to create the queue on SQS. This can be used if the board already exists.
|
|
31
|
+
# @params: name <String>: name of the queue you want to interact with
|
|
32
|
+
# @returns: Queue::Board
|
|
33
|
+
def build_queue(name)
|
|
34
|
+
Board.build(to_camel(name))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Deletes a queue message without caring about reading/interacting with the message.
|
|
38
|
+
# This is usually used for progress tracking, ie; a Neuron takes a message from the Backlog, moves it to
|
|
39
|
+
# WIP and deletes it from Backlog. Then repeats these steps for the remaining States in the Workflow
|
|
40
|
+
# @params: queue <String>[, opts <Hash>]
|
|
41
|
+
# queue is the name of the queue to interact with
|
|
42
|
+
# opts is a configuration hash for the SQS::QueuePoller
|
|
43
|
+
def delete_queue_message(queue, opts = {})
|
|
44
|
+
poll(queue, opts) do |msg, stats|
|
|
45
|
+
poller(queue).delete_message(msg)
|
|
46
|
+
throw :stop_polling
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# This method is used to gain the approximate count of messages in a given queue
|
|
51
|
+
# @params: board_url <String>: The URL for the board you need to get a count from
|
|
52
|
+
# @returns: float representation of the count
|
|
53
|
+
def get_queue_message_count(board_url)
|
|
54
|
+
sqs.get_queue_attributes(
|
|
55
|
+
queue_url: board_url,
|
|
56
|
+
attribute_names: ['ApproximateNumberOfMessages']
|
|
57
|
+
).attributes['ApproximateNumberOfMessages'].to_f
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @params: board<String|symbol>: The name of the board
|
|
61
|
+
# @returns a message and deletes it from its origin
|
|
62
|
+
def pluck_queue_message(board)
|
|
63
|
+
poll(board) do |msg, poller|
|
|
64
|
+
poller.delete_message(msg)
|
|
65
|
+
return valid_json?(msg.body) ? JSON.parse(msg.body) : msg.body
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Polls the given board with the given options hash and a block that interacts with
|
|
70
|
+
# the message that is retrieved from the queue
|
|
71
|
+
# @params: board <String>[, opts <Hash>]
|
|
72
|
+
# board is the name of the queue you want to poll
|
|
73
|
+
# opts can have any AWS::SQS polling option
|
|
74
|
+
# &block is the block that is used to interact with the message that was retrieved
|
|
75
|
+
# @returns the results from the `message` and the `block` that interacts with the message(s)
|
|
76
|
+
def poll(board, opts = {})
|
|
77
|
+
this_poller = queue_poller(board)
|
|
78
|
+
results = nil
|
|
79
|
+
this_poller.poll(opts) do |msg|
|
|
80
|
+
results = yield msg, this_poller if block_given?
|
|
81
|
+
this_poller.delete_message(msg)
|
|
82
|
+
throw :stop_polling
|
|
83
|
+
end
|
|
84
|
+
results
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# This method can be used to gain a SQS::QueuePoller. It creates a Board object,
|
|
88
|
+
# the Board then sends the API call to SQS to create the queue and sets an instance
|
|
89
|
+
# variable, using the board's name, to the Board object itself
|
|
90
|
+
# @params: board_name <String>: name of the Queue you want to gain a QueuePoller for
|
|
91
|
+
# @returns: @<board_name:Queue::Board>
|
|
92
|
+
def queue_poller(board_name)
|
|
93
|
+
board = Board.create!(board_name)
|
|
94
|
+
|
|
95
|
+
unless instance_variable_defined?(board.i_var)
|
|
96
|
+
instance_variable_set(
|
|
97
|
+
board.i_var,
|
|
98
|
+
board
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
instance_variable_get(board.i_var).poller
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Checks SQS for the existence of this queue
|
|
105
|
+
def queue_exists?(name)
|
|
106
|
+
!sqs.list_queues(queue_name_prefix: name).queue_urls.empty?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Searches for a queue based on the name
|
|
110
|
+
# @params: name <String>
|
|
111
|
+
# @returns: queue_urls <Array>
|
|
112
|
+
def queue_search(name)
|
|
113
|
+
sqs.list_queues(queue_name_prefix: name).queue_urls
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Sends a given message to a given queue
|
|
117
|
+
# @params: address <String>: address of the queue you want to interact with
|
|
118
|
+
# @returns: queue_urls <Array<String>>
|
|
119
|
+
def send_queue_message(address, message)
|
|
120
|
+
sqs.send_message(
|
|
121
|
+
queue_url: address,
|
|
122
|
+
message_body: message
|
|
123
|
+
)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
require_relative '
|
|
2
|
-
require_relative '
|
|
1
|
+
require_relative './broadcast/broadcast'
|
|
2
|
+
require_relative './queue/board'
|
|
3
|
+
require_relative './queue/queue'
|
|
4
|
+
require_relative './pipe/pipe'
|
|
3
5
|
|
|
4
6
|
module Smash
|
|
5
7
|
module CloudPowers
|
|
8
|
+
# The Synapse module provides all communications functionality
|
|
9
|
+
# - Broadcast is a module that is useful for sending 1 message to multiple recipients
|
|
10
|
+
# - Pipe is a module that is useful for sending large result sets, data to be processed
|
|
11
|
+
# or loaded, logging info and any other high-throughput/data-centric application with
|
|
12
|
+
# - Queue is a module that is primarily used for asynchronous communications between a sender
|
|
13
|
+
# and any number of users or apps that _might_ need to use it
|
|
6
14
|
module Synapse
|
|
15
|
+
include Smash::CloudPowers::Synapse::Broadcast
|
|
7
16
|
include Smash::CloudPowers::Synapse::Pipe
|
|
8
17
|
include Smash::CloudPowers::Synapse::Queue
|
|
9
18
|
end
|
data/lib/cloud_powers/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cloud_powers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Adam Phillipps
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-09-
|
|
11
|
+
date: 2016-09-30 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport-core-ext
|
|
@@ -154,9 +154,10 @@ description: |2
|
|
|
154
154
|
CloudPowers is a wrapper around AWS and other cloud services.
|
|
155
155
|
It was developed specifically for the Brain project
|
|
156
156
|
but hopefully can be used in any other ruby project that needs to use cloud
|
|
157
|
-
service providers' resources. Version 0.2.3 has a little EC2, S3, SQS
|
|
158
|
-
Kinesis.
|
|
159
|
-
and
|
|
157
|
+
service providers' resources. Version 0.2.3 has a little EC2, S3, SQS, SNS
|
|
158
|
+
and Kinesis. V-0.2.4 should be out in a day or so and it will include IoT
|
|
159
|
+
basics and specs too. This project is actively being developed, so more
|
|
160
|
+
additions, specs and docs will be updated frequently. I always welcome input.
|
|
160
161
|
Enjoy!
|
|
161
162
|
email: adam.phillipps@gmail.com
|
|
162
163
|
executables: []
|
|
@@ -177,6 +178,7 @@ files:
|
|
|
177
178
|
- bin/setup
|
|
178
179
|
- cloud_powers.gemspec
|
|
179
180
|
- lib/cloud_powers.rb
|
|
181
|
+
- lib/cloud_powers/.DS_Store
|
|
180
182
|
- lib/cloud_powers/auth.rb
|
|
181
183
|
- lib/cloud_powers/aws_resources.rb
|
|
182
184
|
- lib/cloud_powers/delegator.rb
|
|
@@ -184,8 +186,10 @@ files:
|
|
|
184
186
|
- lib/cloud_powers/self_awareness.rb
|
|
185
187
|
- lib/cloud_powers/smash_error.rb
|
|
186
188
|
- lib/cloud_powers/storage.rb
|
|
187
|
-
- lib/cloud_powers/synapse/
|
|
188
|
-
- lib/cloud_powers/synapse/
|
|
189
|
+
- lib/cloud_powers/synapse/broadcast/broadcast.rb
|
|
190
|
+
- lib/cloud_powers/synapse/pipe/pipe.rb
|
|
191
|
+
- lib/cloud_powers/synapse/queue/board.rb
|
|
192
|
+
- lib/cloud_powers/synapse/queue/queue.rb
|
|
189
193
|
- lib/cloud_powers/synapse/synapse.rb
|
|
190
194
|
- lib/cloud_powers/version.rb
|
|
191
195
|
- lib/cloud_powers/workflow.rb
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
require 'uri'
|
|
2
|
-
|
|
3
|
-
module Smash
|
|
4
|
-
module CloudPowers
|
|
5
|
-
module Synapse
|
|
6
|
-
module Queue
|
|
7
|
-
include Smash::CloudPowers::Helper
|
|
8
|
-
include Smash::CloudPowers::AwsResources
|
|
9
|
-
# Board <Struct>
|
|
10
|
-
# This groups common functionality for a queue
|
|
11
|
-
Board = Struct.new(:sqs, :set_name, :set_address, :workflow) do
|
|
12
|
-
include Smash::CloudPowers::Synapse::Queue
|
|
13
|
-
include Smash::CloudPowers::Helper
|
|
14
|
-
include Smash::CloudPowers::Zenv
|
|
15
|
-
|
|
16
|
-
def i_var
|
|
17
|
-
"@#{name}"
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def address
|
|
21
|
-
set_address || zfind(set_name) ||
|
|
22
|
-
"https://sqs.us-west-2.amazonaws.com/#{zfind(:account_number)}/#{name}"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def create_queue!
|
|
26
|
-
sqs.create_queue(queue_name: to_camel(name))
|
|
27
|
-
self
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def destroy!
|
|
31
|
-
sqs.delete_queue(queue_url: address)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def message_count
|
|
35
|
-
get_queue_message_count(address)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
def name
|
|
39
|
-
set_name || address.split('/').last
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def next_board
|
|
43
|
-
workflow.next
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def pluck_message(board_name = name)
|
|
47
|
-
pluck_queue_message(board_name)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def real?
|
|
51
|
-
queue_exists?(name)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
def send_message(message)
|
|
55
|
-
send_queue_message(
|
|
56
|
-
address, (valid_json?(message) ? message : message.to_json)
|
|
57
|
-
)
|
|
58
|
-
end
|
|
59
|
-
end # end Board
|
|
60
|
-
#############################################
|
|
61
|
-
|
|
62
|
-
def board_name(url)
|
|
63
|
-
url.to_s.split('/').last
|
|
64
|
-
end
|
|
65
|
-
|
|
66
|
-
def create_queue!(name)
|
|
67
|
-
begin
|
|
68
|
-
Board.new(sqs, to_camel(name)).create_queue!
|
|
69
|
-
rescue Aws::SQS::Errors::QueueDeletedRecently => e
|
|
70
|
-
sleep 5
|
|
71
|
-
retry
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def build_queue(name)
|
|
76
|
-
Board.new(sqs, to_camel(name))
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def delete_queue_message(queue, opts = {})
|
|
80
|
-
poll(queue, opts) do |msg, stats|
|
|
81
|
-
poller(queue).delete_message(msg)
|
|
82
|
-
throw :stop_polling
|
|
83
|
-
end
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
def get_queue_message_count(board_url)
|
|
87
|
-
sqs.get_queue_attributes(
|
|
88
|
-
queue_url: board_url,
|
|
89
|
-
attribute_names: ['ApproximateNumberOfMessages']
|
|
90
|
-
).attributes['ApproximateNumberOfMessages'].to_f
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
# @params: board<String|symbol>: The name of the board
|
|
94
|
-
# @returns a message and deletes it from its origin
|
|
95
|
-
def pluck_queue_message(board)
|
|
96
|
-
poll(board) do |msg, poller|
|
|
97
|
-
poller.delete_message(msg)
|
|
98
|
-
return valid_json?(msg.body) ? JSON.parse(msg.body) : msg.body
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def poll(board, opts = {})
|
|
103
|
-
this_poller = poller(board)
|
|
104
|
-
results = nil
|
|
105
|
-
this_poller.poll(opts) do |msg|
|
|
106
|
-
results = yield msg, this_poller if block_given?
|
|
107
|
-
this_poller.delete_message(msg)
|
|
108
|
-
throw :stop_polling
|
|
109
|
-
end
|
|
110
|
-
results
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def poller(board_name)
|
|
114
|
-
board = Board.new(sqs, board_name)
|
|
115
|
-
|
|
116
|
-
unless instance_variable_defined?(board.i_var)
|
|
117
|
-
instance_variable_set(
|
|
118
|
-
board.i_var,
|
|
119
|
-
Aws::SQS::QueuePoller.new(board.address)
|
|
120
|
-
)
|
|
121
|
-
end
|
|
122
|
-
instance_variable_get(board.i_var)
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
def queue_exists?(name)
|
|
126
|
-
!sqs.list_queues(queue_name_prefix: name).queue_urls.empty?
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
def queue_search(name)
|
|
130
|
-
sqs.list_queues(queue_name_prefix: name).queue_urls
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
def send_queue_message(address, message)
|
|
134
|
-
sqs.send_message(
|
|
135
|
-
queue_url: address,
|
|
136
|
-
message_body: message
|
|
137
|
-
)
|
|
138
|
-
end
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
end
|
|
142
|
-
end
|