eventq_aws 0.1.0 → 0.2.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 +4 -4
- data/lib/eventq_aws/aws_eventq_client.rb +28 -19
- data/lib/eventq_aws/aws_queue_client.rb +29 -19
- data/lib/eventq_aws/aws_queue_manager.rb +36 -23
- data/lib/eventq_aws/aws_queue_worker.rb +131 -101
- data/lib/eventq_aws/aws_subscription_manager.rb +41 -25
- data/lib/eventq_aws/version.rb +4 -2
- data/lib/eventq_aws.rb +6 -1
- metadata +6 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ff66f7c228e5be1bb6fb93fa8fa38162b8d5948b
|
|
4
|
+
data.tar.gz: 3b40922adb6ef8bdec4721d0102dec780365be0c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8db3e65bd7cc17343cf39f8dc5670380ff983b5a190e55bc2a369bf05a630934ca2ab5cb9de4728f53b749c2161be8949ab6ab9287261bb7c956efaf36072168
|
|
7
|
+
data.tar.gz: b6813c2a5a0eef2b01b234ffb670dc9f95e0216381b1bcdcec9a645aaa3a6088e9bf2afacfaff2e0829ad2c4d91de5f02e04ed367c47286bef2af62e51d43535
|
|
@@ -1,28 +1,37 @@
|
|
|
1
|
-
|
|
1
|
+
module EventQ
|
|
2
|
+
module Amazon
|
|
3
|
+
class EventQClient
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
def initialize
|
|
5
|
-
@client = AwsQueueClient.new
|
|
6
|
-
end
|
|
5
|
+
def initialize(options)
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
if options[:client] == nil
|
|
8
|
+
raise ':client (QueueClient) must be specified.'
|
|
9
|
+
end
|
|
9
10
|
|
|
10
|
-
|
|
11
|
+
@client = options[:client]
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
qm.content = event
|
|
14
|
-
qm.type = event_type
|
|
13
|
+
end
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
def raise_event(event_type, event)
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
topic_arn: topic_arn,
|
|
20
|
-
message: message,
|
|
21
|
-
subject: event_type
|
|
22
|
-
})
|
|
17
|
+
topic_arn = @client.get_topic_arn(event_type)
|
|
23
18
|
|
|
24
|
-
|
|
19
|
+
qm = EventQ::QueueMessage.new
|
|
20
|
+
qm.content = event
|
|
21
|
+
qm.type = event_type
|
|
25
22
|
|
|
26
|
-
|
|
23
|
+
message = Oj.dump(qm)
|
|
24
|
+
|
|
25
|
+
response = @client.sns.publish({
|
|
26
|
+
topic_arn: topic_arn,
|
|
27
|
+
message: message,
|
|
28
|
+
subject: event_type
|
|
29
|
+
})
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
return response.message_id
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -1,28 +1,38 @@
|
|
|
1
|
-
|
|
1
|
+
module EventQ
|
|
2
|
+
module Amazon
|
|
3
|
+
class QueueClient
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
attr_reader :sns
|
|
6
|
+
attr_reader :sqs
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
def initialize(options = {})
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
if options.has_key?(:aws_key)
|
|
11
|
+
Aws.config[:credentials] = Aws::Credentials.new(options[:aws_key], options[:aws_secret])
|
|
12
|
+
end
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
if !options.has_key?(:aws_account_number)
|
|
15
|
+
raise ':aws_account_number option must be specified.'
|
|
16
|
+
end
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
|
|
18
|
+
@aws_account = options[:aws_account_number]
|
|
19
|
+
@aws_region = options[:aws_region] || 'eu-west-1'
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
Aws.config[:region] = @aws_region
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
return response.topic_arn
|
|
22
|
-
end
|
|
23
|
+
@sns = Aws::SNS::Client.new
|
|
24
|
+
@sqs = Aws::SQS::Client.new
|
|
23
25
|
|
|
24
|
-
|
|
25
|
-
return "arn:aws:sqs:#{@aws_region}:#{@aws_account}:#{queue.name}"
|
|
26
|
-
end
|
|
26
|
+
end
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
def get_topic_arn(event_type)
|
|
29
|
+
return "arn:aws:sns:#{@aws_region}:#{@aws_account}:#{event_type}"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def get_queue_arn(queue)
|
|
33
|
+
return "arn:aws:sqs:#{@aws_region}:#{@aws_account}:#{queue.name}"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -1,35 +1,48 @@
|
|
|
1
|
-
|
|
1
|
+
module EventQ
|
|
2
|
+
module Amazon
|
|
3
|
+
class QueueManager
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
@@dead_letter_queue = 'dead_letter_archive'
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
@client = AwsQueueClient.new
|
|
7
|
-
end
|
|
7
|
+
def initialize(options)
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
if options[:client] == nil
|
|
10
|
+
raise ':client (QueueClient) must be specified.'
|
|
11
|
+
end
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
attributes: {
|
|
14
|
-
'VisibilityTimeout' => (queue.retry_delay / 1000).to_s
|
|
15
|
-
}
|
|
16
|
-
})
|
|
13
|
+
@client = options[:client]
|
|
14
|
+
end
|
|
17
15
|
|
|
18
|
-
|
|
16
|
+
def get_queue(queue)
|
|
19
17
|
|
|
20
|
-
|
|
18
|
+
response = @client.sqs.create_queue({
|
|
19
|
+
queue_name: queue.name,
|
|
20
|
+
attributes: {
|
|
21
|
+
'VisibilityTimeout' => (queue.retry_delay / 1000).to_s
|
|
22
|
+
}
|
|
23
|
+
})
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
return response.queue_url
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
end
|
|
25
28
|
|
|
26
|
-
|
|
29
|
+
def drop_queue(queue)
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
q = get_queue(queue)
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
end
|
|
33
|
+
@client.sqs.delete_queue({ queue_url: q})
|
|
34
|
+
|
|
35
|
+
return true
|
|
34
36
|
|
|
35
|
-
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def drop_topic(event_type)
|
|
40
|
+
topic_arn = @client.get_topic_arn(event_type)
|
|
41
|
+
@client.sns.delete_topic({ topic_arn: topic_arn})
|
|
42
|
+
|
|
43
|
+
return true
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -1,145 +1,175 @@
|
|
|
1
|
-
|
|
1
|
+
module EventQ
|
|
2
|
+
module Amazon
|
|
3
|
+
class QueueWorker
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
attr_accessor :is_running
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
def initialize
|
|
8
|
+
@threads = []
|
|
9
|
+
@is_running = false
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
@retry_exceeded_block = nil
|
|
12
|
+
end
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
def start(queue, options = {}, &block)
|
|
15
|
+
configure(queue, options)
|
|
14
16
|
|
|
15
|
-
|
|
17
|
+
if options[:client] == nil
|
|
18
|
+
raise ':client (QueueClient) must be specified.'
|
|
19
|
+
end
|
|
16
20
|
|
|
17
|
-
|
|
21
|
+
raise 'Worker is already running.' if running?
|
|
18
22
|
|
|
19
|
-
|
|
20
|
-
@threads = []
|
|
23
|
+
puts '[QUEUE_WORKER] Listening for messages.'
|
|
21
24
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
thr = Thread.new do
|
|
25
|
+
@is_running = true
|
|
26
|
+
@threads = []
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
#loop through each thread count
|
|
29
|
+
@thread_count.times do
|
|
30
|
+
thr = Thread.new do
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
client = options[:client]
|
|
33
|
+
manager = EventQ::Amazon::QueueManager.new({ client: client })
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
#begin the queue loop for this thread
|
|
36
|
+
while true do
|
|
37
|
+
|
|
38
|
+
#check if the worker is still allowed to run and break out of thread loop if not
|
|
39
|
+
if !@is_running
|
|
40
|
+
break
|
|
41
|
+
end
|
|
36
42
|
|
|
37
|
-
|
|
38
|
-
|
|
43
|
+
#get the queue
|
|
44
|
+
q = manager.get_queue(queue)
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
received = false
|
|
47
|
+
error = false
|
|
48
|
+
abort = false
|
|
42
49
|
|
|
43
|
-
|
|
50
|
+
begin
|
|
44
51
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
#request a message from the queue
|
|
53
|
+
response = client.sqs.receive_message({
|
|
54
|
+
queue_url: q,
|
|
55
|
+
max_number_of_messages: 1,
|
|
56
|
+
wait_time_seconds: 1,
|
|
57
|
+
message_attribute_names: ['ApproximateReceiveCount']
|
|
58
|
+
})
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
|
|
60
|
+
#check that a message was received
|
|
61
|
+
if response.messages.length > 0
|
|
55
62
|
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
msg = response.messages[0]
|
|
64
|
+
retry_attempts = msg.message_attributes['ApproximateReceiveCount'].to_i
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
66
|
+
#deserialize the message payload
|
|
67
|
+
message = Oj.load(msg.body)
|
|
68
|
+
payload = Oj.load(message["Message"])
|
|
62
69
|
|
|
63
|
-
|
|
70
|
+
message_args = EventQ::MessageArgs.new(payload.type, retry_attempts)
|
|
71
|
+
|
|
72
|
+
puts "[QUEUE_WORKER] Message received. Retry Attempts: #{retry_attempts}"
|
|
73
|
+
|
|
74
|
+
#begin worker block for queue message
|
|
75
|
+
begin
|
|
76
|
+
|
|
77
|
+
block.call(payload.content, message_args)
|
|
78
|
+
|
|
79
|
+
if message_args.abort == true
|
|
80
|
+
abort = true
|
|
81
|
+
puts '[QUEUE_WORKER] Message aborted.'
|
|
82
|
+
else
|
|
83
|
+
#accept the message as processed
|
|
84
|
+
client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
|
|
85
|
+
puts '[QUEUE_WORKER] Message acknowledged.'
|
|
86
|
+
received = true
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
rescue => e
|
|
90
|
+
puts '[QUEUE_WORKER] An unhandled error happened attempting to process a queue message.'
|
|
91
|
+
puts "Error: #{e}"
|
|
92
|
+
|
|
93
|
+
error = true
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
if abort || error
|
|
98
|
+
puts '[QUEUE_WORKER] Message rejected.'
|
|
99
|
+
reject_message(queue, client, msg, q, retry_attempts)
|
|
100
|
+
end
|
|
64
101
|
|
|
65
|
-
#begin worker block for queue message
|
|
66
|
-
begin
|
|
67
|
-
block.call(payload.content, payload.type, retry_attempts)
|
|
68
|
-
|
|
69
|
-
#accept the message as processed
|
|
70
|
-
client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
|
|
71
|
-
puts '[QUEUE_WORKER] Message acknowledged.'
|
|
72
|
-
received = true
|
|
73
|
-
rescue => e
|
|
74
|
-
puts '[QUEUE_WORKER] An unhandled error happened attempting to process a queue message.'
|
|
75
|
-
puts "Error: #{e}"
|
|
76
|
-
|
|
77
|
-
error = true
|
|
78
|
-
puts '[QUEUE_WORKER] Message rejected.'
|
|
79
|
-
|
|
80
|
-
if !queue.allow_retry
|
|
81
|
-
#remove the message from the queue so that it does not get retried
|
|
82
|
-
client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
|
|
83
102
|
end
|
|
84
103
|
|
|
104
|
+
rescue
|
|
105
|
+
puts 'An error occured attempting to retrieve a message from the queue.'
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
#check if any message was received
|
|
109
|
+
if !received && !error
|
|
110
|
+
puts "[QUEUE_WORKER] No message received. Sleeping for #{@sleep} seconds"
|
|
111
|
+
#no message received so sleep before attempting to pop another message from the queue
|
|
112
|
+
sleep(@sleep)
|
|
85
113
|
end
|
|
86
114
|
|
|
87
115
|
end
|
|
88
116
|
|
|
89
|
-
rescue
|
|
90
|
-
puts 'An error occured attempting to retrieve a message from the queue.'
|
|
91
117
|
end
|
|
118
|
+
@threads.push(thr)
|
|
92
119
|
|
|
93
|
-
|
|
94
|
-
if !received && !error
|
|
95
|
-
puts "[QUEUE_WORKER] No message received. Sleeping for #{@sleep} seconds"
|
|
96
|
-
#no message received so sleep before attempting to pop another message from the queue
|
|
97
|
-
sleep(@sleep)
|
|
98
|
-
end
|
|
120
|
+
end
|
|
99
121
|
|
|
122
|
+
if options.key?(:wait) && options[:wait] == true
|
|
123
|
+
@threads.each { |thr| thr.join }
|
|
100
124
|
end
|
|
101
125
|
|
|
126
|
+
return true
|
|
102
127
|
end
|
|
103
|
-
@threads.push(thr)
|
|
104
128
|
|
|
105
|
-
|
|
129
|
+
def stop
|
|
130
|
+
@is_running = false
|
|
131
|
+
@threads.each { |thr| thr.join }
|
|
132
|
+
return true
|
|
133
|
+
end
|
|
106
134
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
end
|
|
135
|
+
def on_retry_exceeded(&block)
|
|
136
|
+
@retry_exceeded_block = block
|
|
137
|
+
end
|
|
111
138
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
end
|
|
139
|
+
def running?
|
|
140
|
+
return @is_running
|
|
141
|
+
end
|
|
116
142
|
|
|
117
|
-
|
|
118
|
-
@retry_exceeded_block = block
|
|
119
|
-
end
|
|
143
|
+
private
|
|
120
144
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
145
|
+
def reject_message(queue, client, msg, q, retry_attempts)
|
|
146
|
+
if !queue.allow_retry || retry_attempts >= queue.max_retry_attempts
|
|
147
|
+
|
|
148
|
+
#remove the message from the queue so that it does not get retried again
|
|
149
|
+
client.sqs.delete_message({ queue_url: q, receipt_handle: msg.receipt_handle })
|
|
150
|
+
end
|
|
151
|
+
end
|
|
124
152
|
|
|
125
|
-
|
|
153
|
+
def configure(queue, options = {})
|
|
126
154
|
|
|
127
|
-
|
|
155
|
+
@queue = queue
|
|
128
156
|
|
|
129
|
-
|
|
157
|
+
#default thread count
|
|
158
|
+
@thread_count = 5
|
|
159
|
+
if options.key?(:thread_count)
|
|
160
|
+
@thread_count = options[:thread_count]
|
|
161
|
+
end
|
|
130
162
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
163
|
+
#default sleep time in seconds
|
|
164
|
+
@sleep = 15
|
|
165
|
+
if options.key?(:sleep)
|
|
166
|
+
@sleep = options[:sleep]
|
|
167
|
+
end
|
|
136
168
|
|
|
137
|
-
|
|
138
|
-
@sleep = 15
|
|
139
|
-
if options.key?(:sleep)
|
|
140
|
-
@sleep = options[:sleep]
|
|
141
|
-
end
|
|
169
|
+
return true
|
|
142
170
|
|
|
143
|
-
|
|
171
|
+
end
|
|
144
172
|
|
|
145
|
-
end
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
@@ -1,21 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
module EventQ
|
|
2
|
+
module Amazon
|
|
3
|
+
class SubscriptionManager
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
def initialize(options)
|
|
6
|
+
|
|
7
|
+
if options[:client] == nil
|
|
8
|
+
raise ':client (QueueClient) must be specified.'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
@client = options[:client]
|
|
12
|
+
|
|
13
|
+
if options[:queue_manager] == nil
|
|
14
|
+
raise ':queue_manager (QueueManager) must be specified.'
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
@manager = options[:queue_manager]
|
|
18
|
+
end
|
|
7
19
|
|
|
8
|
-
|
|
20
|
+
def subscribe(event_type, queue)
|
|
9
21
|
|
|
10
|
-
|
|
22
|
+
topic_arn = @client.get_topic_arn(event_type)
|
|
11
23
|
|
|
12
|
-
|
|
13
|
-
|
|
24
|
+
q = @manager.get_queue(queue)
|
|
25
|
+
queue_arn = @client.get_queue_arn(queue)
|
|
14
26
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
27
|
+
@client.sqs.set_queue_attributes({
|
|
28
|
+
queue_url: q,
|
|
29
|
+
attributes:{
|
|
30
|
+
'Policy' => '{
|
|
19
31
|
"Version": "2012-10-17",
|
|
20
32
|
"Id": "SNStoSQS",
|
|
21
33
|
"Statement": [
|
|
@@ -33,21 +45,25 @@ class AwsSubscriptionManager
|
|
|
33
45
|
}
|
|
34
46
|
]
|
|
35
47
|
}'
|
|
36
|
-
|
|
37
|
-
|
|
48
|
+
}
|
|
49
|
+
})
|
|
38
50
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
51
|
+
@client.sns.subscribe({
|
|
52
|
+
topic_arn: topic_arn,
|
|
53
|
+
protocol: 'sqs',
|
|
54
|
+
endpoint: queue_arn
|
|
55
|
+
})
|
|
44
56
|
|
|
45
|
-
|
|
57
|
+
return true
|
|
46
58
|
|
|
47
|
-
|
|
59
|
+
end
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
def unsubscribe(queue)
|
|
50
62
|
|
|
51
|
-
|
|
63
|
+
raise 'Not implemented. Please unsubscribe the queue from the topic inside the AWS Management Console.'
|
|
52
64
|
|
|
53
|
-
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
data/lib/eventq_aws/version.rb
CHANGED
data/lib/eventq_aws.rb
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
require
|
|
1
|
+
require 'aws-sdk-core'
|
|
2
|
+
require 'oj'
|
|
3
|
+
require 'eventq_base'
|
|
4
|
+
|
|
5
|
+
require 'eventq_aws/version'
|
|
2
6
|
require 'eventq_aws/aws_eventq_client'
|
|
3
7
|
require 'eventq_aws/aws_queue_client'
|
|
4
8
|
require 'eventq_aws/aws_queue_manager'
|
|
5
9
|
require 'eventq_aws/aws_queue_worker'
|
|
6
10
|
require 'eventq_aws/aws_subscription_manager'
|
|
11
|
+
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: eventq_aws
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- vaughanbrittonsage
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-
|
|
11
|
+
date: 2016-07-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -70,16 +70,16 @@ dependencies:
|
|
|
70
70
|
name: oj
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- -
|
|
73
|
+
- - '='
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version:
|
|
75
|
+
version: 2.15.0
|
|
76
76
|
type: :runtime
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- -
|
|
80
|
+
- - '='
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version:
|
|
82
|
+
version: 2.15.0
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
84
|
name: aws-sdk-core
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|