carnivore-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.
- data/CHANGELOG.md +2 -0
- data/README.md +24 -0
- data/carnivore-sqs.gemspec +15 -0
- data/lib/carnivore-sqs/sqs.rb +135 -0
- data/lib/carnivore-sqs/version.rb +7 -0
- data/lib/carnivore-sqs.rb +4 -0
- metadata +83 -0
data/CHANGELOG.md
ADDED
data/README.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Carnivore SQS
|
2
|
+
|
3
|
+
Provides SQS `Carnivore::Source`
|
4
|
+
|
5
|
+
# Usage
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
require 'carnivore'
|
9
|
+
require 'carnivore-sqs'
|
10
|
+
|
11
|
+
Carnivore.configure do
|
12
|
+
source = Carnivore::Source.build(
|
13
|
+
:type => {
|
14
|
+
:fog => {...},
|
15
|
+
:queues => ['arn:aws:sqs:...']
|
16
|
+
}
|
17
|
+
)
|
18
|
+
end.start!
|
19
|
+
```
|
20
|
+
|
21
|
+
# Info
|
22
|
+
* Carnivore: https://github.com/heavywater/carnivore
|
23
|
+
* Repository: https://github.com/heavywater/carnivore-sqs
|
24
|
+
* IRC: Freenode @ #heavywater
|
@@ -0,0 +1,15 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__)) + '/lib/'
|
2
|
+
require 'carnivore-sqs/version'
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'carnivore-sqs'
|
5
|
+
s.version = Carnivore::Sqs::VERSION.version
|
6
|
+
s.summary = 'Message processing helper'
|
7
|
+
s.author = 'Chris Roberts'
|
8
|
+
s.email = 'chrisroberts.code@gmail.com'
|
9
|
+
s.homepage = 'https://github.com/heavywater/carnivore-sqs'
|
10
|
+
s.description = 'Carnivore SQS source'
|
11
|
+
s.require_path = 'lib'
|
12
|
+
s.add_dependency 'carnivore', '>= 0.1.8'
|
13
|
+
s.add_dependency 'fog'
|
14
|
+
s.files = Dir['**/*']
|
15
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'fog'
|
2
|
+
require 'carnivore/source'
|
3
|
+
|
4
|
+
module Carnivore
|
5
|
+
class Source
|
6
|
+
class Sqs < Source
|
7
|
+
|
8
|
+
OUTPUT_REPEAT_EVERY=20
|
9
|
+
|
10
|
+
attr_reader :pause_time
|
11
|
+
|
12
|
+
def setup(args={})
|
13
|
+
@fog = nil
|
14
|
+
@connection_args = args[:fog]
|
15
|
+
case args[:queues]
|
16
|
+
when Hash
|
17
|
+
@queues = args[:queues]
|
18
|
+
else
|
19
|
+
@queues = Array(args[:queues]).flatten.compact
|
20
|
+
@queues = Hash[*(
|
21
|
+
@queues.size.times.map(&:to_i).zip(@queues).flatten
|
22
|
+
)]
|
23
|
+
end
|
24
|
+
@queues.values.map do |q|
|
25
|
+
q.replace(format_queue(q))
|
26
|
+
end
|
27
|
+
if(args[:processable_queues])
|
28
|
+
@processable_queues = Array(args[:processable_queues]).flatten.compact
|
29
|
+
end
|
30
|
+
@pause_time = args[:pause] || 5
|
31
|
+
@receive_timeout = after(args[:receive_timeout] || 30){ terminate }
|
32
|
+
debug "Creating SQS source instance <#{name}>"
|
33
|
+
debug "Handled queues: #{@queues.inspect}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_queue(q)
|
37
|
+
q.include?('.com') ? q : "/#{q.split(':')[-2,2].join('/')}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def connect
|
41
|
+
@fog = Fog::AWS::SQS.new(@connection_args)
|
42
|
+
end
|
43
|
+
|
44
|
+
def receive(n=1)
|
45
|
+
count = 0
|
46
|
+
msgs = []
|
47
|
+
while(msgs.empty?)
|
48
|
+
msgs = []
|
49
|
+
@receive_timeout.reset
|
50
|
+
msgs = queues.map do |q|
|
51
|
+
m = @fog.receive_message(q, 'MaxNumberOfMessages' => n).body['Message']
|
52
|
+
m.map! do |msg|
|
53
|
+
msg.merge('SourceQueue' => q)
|
54
|
+
end
|
55
|
+
end.flatten.compact
|
56
|
+
@receive_timeout.reset
|
57
|
+
if(msgs.empty?)
|
58
|
+
if(count == 0)
|
59
|
+
debug "Source<#{name}> no message received. Sleeping for #{pause_time} seconds."
|
60
|
+
elsif(count % OUTPUT_REPEAT_EVERY == 0)
|
61
|
+
debug "Source<#{name}> last message repeated #{count} times"
|
62
|
+
end
|
63
|
+
sleep(pause_time)
|
64
|
+
else
|
65
|
+
debug "Received: #{msgs.inspect}"
|
66
|
+
end
|
67
|
+
count += 1
|
68
|
+
end
|
69
|
+
msgs.map{|m| pre_process(m) }
|
70
|
+
end
|
71
|
+
|
72
|
+
def transmit(message, original=nil)
|
73
|
+
queue = determine_queue(original)
|
74
|
+
@fog.send_message(queue, message)
|
75
|
+
end
|
76
|
+
|
77
|
+
def confirm(message)
|
78
|
+
queue = determine_queue(message)
|
79
|
+
debug "Source<#{name}> Confirming message<#{message}> on Queue<#{queue}>"
|
80
|
+
m = message.is_a?(Message) ? message[:message] : message
|
81
|
+
@fog.delete_message(queue, m['ReceiptHandle'])
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def determine_queue(obj)
|
87
|
+
queue = nil
|
88
|
+
if(obj)
|
89
|
+
if(obj.is_a?(Message))
|
90
|
+
queue = obj[:message]['SourceQueue']
|
91
|
+
else
|
92
|
+
case obj
|
93
|
+
when Numeric
|
94
|
+
queue = @queues[dest]
|
95
|
+
when String, Symbol
|
96
|
+
queue = @queues[dest.to_s] || queues.detect{|q| q.end_with?(dest.to_s)}
|
97
|
+
when Hash
|
98
|
+
queue = obj['SourceQueue']
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
queue || queues.first
|
103
|
+
end
|
104
|
+
|
105
|
+
def queues
|
106
|
+
if(@processable_queues)
|
107
|
+
@queues.map do |k,v|
|
108
|
+
v if @processable_queues.include?(k)
|
109
|
+
end.compact
|
110
|
+
else
|
111
|
+
@queues.values
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def fog
|
116
|
+
unless(@fog)
|
117
|
+
connect
|
118
|
+
end
|
119
|
+
@fog
|
120
|
+
end
|
121
|
+
|
122
|
+
def pre_process(m)
|
123
|
+
if(m['Body'])
|
124
|
+
begin
|
125
|
+
m['Body'] = JSON.load(m['Body'])
|
126
|
+
rescue JSON::ParserError
|
127
|
+
# well, we did our best
|
128
|
+
end
|
129
|
+
end
|
130
|
+
m
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
metadata
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: carnivore-sqs
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chris Roberts
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-10-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: carnivore
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 0.1.8
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.1.8
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: fog
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Carnivore SQS source
|
47
|
+
email: chrisroberts.code@gmail.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- lib/carnivore-sqs/version.rb
|
53
|
+
- lib/carnivore-sqs/sqs.rb
|
54
|
+
- lib/carnivore-sqs.rb
|
55
|
+
- carnivore-sqs.gemspec
|
56
|
+
- README.md
|
57
|
+
- CHANGELOG.md
|
58
|
+
homepage: https://github.com/heavywater/carnivore-sqs
|
59
|
+
licenses: []
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options: []
|
62
|
+
require_paths:
|
63
|
+
- lib
|
64
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ! '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
requirements: []
|
77
|
+
rubyforge_project:
|
78
|
+
rubygems_version: 1.8.24
|
79
|
+
signing_key:
|
80
|
+
specification_version: 3
|
81
|
+
summary: Message processing helper
|
82
|
+
test_files: []
|
83
|
+
has_rdoc:
|