qswarm 0.0.21 → 1.0.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/README.md +264 -1
- data/bin/qswarm +9 -6
- data/lib/qswarm.rb +17 -3
- data/lib/qswarm/agent.rb +160 -40
- data/lib/qswarm/connection.rb +25 -0
- data/lib/qswarm/connections/amqp.rb +167 -0
- data/lib/qswarm/connections/logger.rb +27 -0
- data/lib/qswarm/connections/twitter.rb +148 -0
- data/lib/qswarm/connections/xmpp.rb +92 -0
- data/lib/qswarm/dsl.rb +56 -12
- data/lib/qswarm/swarm.rb +5 -24
- data/lib/qswarm/version.rb +1 -1
- data/qswarm.gemspec +6 -2
- metadata +64 -23
- data/lib/qswarm/broker.rb +0 -118
- data/lib/qswarm/listener.rb +0 -99
- data/lib/qswarm/loggable.rb +0 -15
- data/lib/qswarm/speaker.rb +0 -76
- data/lib/qswarm/speakers/http.rb +0 -67
- data/lib/qswarm/speakers/irc.rb +0 -107
- data/lib/qswarm/speakers/mysql.rb +0 -39
- data/lib/qswarm/speakers/nc.rb +0 -41
data/lib/qswarm/dsl.rb
CHANGED
@@ -1,17 +1,61 @@
|
|
1
1
|
module Qswarm
|
2
2
|
module DSL
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
module Config
|
4
|
+
@@caller = nil
|
5
|
+
|
6
|
+
def self.caller
|
7
|
+
@@caller
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.caller=(caller)
|
11
|
+
@@caller = caller
|
12
|
+
end
|
13
|
+
|
14
|
+
class Swarm; extend Qswarm::DSL::Config; end
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.included(base)
|
18
|
+
base.extend(ClassMethods)
|
19
|
+
end
|
20
|
+
|
21
|
+
def dsl_load(config)
|
22
|
+
dsl_call(File.read(config))
|
23
|
+
end
|
24
|
+
|
25
|
+
def dsl_call(string = nil, &block)
|
26
|
+
parent = Config.caller
|
27
|
+
Config.caller = self
|
28
|
+
if string.nil?
|
29
|
+
res = Config::Swarm.module_eval(&block)
|
30
|
+
else
|
31
|
+
res = Config::Swarm.module_eval(string)
|
32
|
+
end
|
33
|
+
Config.caller = parent
|
34
|
+
res
|
35
|
+
end
|
36
|
+
|
37
|
+
module ClassMethods
|
38
|
+
def dsl_accessor(*symbols)
|
39
|
+
symbols.each do |sym|
|
40
|
+
Qswarm::DSL::Config.module_eval %{
|
41
|
+
def #{sym}
|
42
|
+
@@#{sym}
|
43
|
+
end
|
44
|
+
|
45
|
+
def #{sym}=(*val)
|
46
|
+
@@#{sym} = val.size == 1 ? val[0] : val
|
11
47
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def dsl(*symbols)
|
53
|
+
symbols.each do |sym|
|
54
|
+
Qswarm::DSL::Config.module_eval "def #{sym}(*args, &block) @@caller.send(#{sym.inspect}, *args, &block); end"
|
55
|
+
#Qswarm::DSL::Config.module_eval "def #{sym}(name, args = nil, &block) @@caller.send(#{sym.inspect}, name, args, &block); end"
|
56
|
+
#Qswarm::DSL::Config.module_eval { define_method(sym, -> (name, args = nil, &block) { @@caller.send(sym.inspect, name, args, &block) } ) }
|
57
|
+
end
|
58
|
+
end
|
15
59
|
end
|
16
60
|
end
|
17
|
-
end
|
61
|
+
end
|
data/lib/qswarm/swarm.rb
CHANGED
@@ -1,43 +1,24 @@
|
|
1
1
|
require 'andand'
|
2
2
|
require 'eventmachine'
|
3
3
|
|
4
|
-
require 'qswarm/agent'
|
5
|
-
require 'qswarm/broker'
|
6
|
-
|
7
4
|
module Qswarm
|
8
5
|
class Swarm
|
9
|
-
include Qswarm::
|
6
|
+
include Qswarm::DSL
|
10
7
|
|
11
|
-
|
12
|
-
dsl = new
|
13
|
-
dsl.instance_eval(File.read(config), config)
|
14
|
-
dsl
|
15
|
-
end
|
8
|
+
dsl :agent
|
16
9
|
|
17
|
-
def initialize
|
10
|
+
def initialize(config)
|
18
11
|
@agents = []
|
19
12
|
$fqdn = Socket.gethostbyname(Socket.gethostname).first
|
20
|
-
@brokers = {}
|
21
|
-
end
|
22
13
|
|
23
|
-
|
24
|
-
logger
|
14
|
+
dsl_load(config)
|
25
15
|
end
|
26
16
|
|
27
17
|
def agent(name, args = nil, &block)
|
28
|
-
logger.info "Registering agent: #{name}"
|
18
|
+
Qswarm.logger.info "Registering agent: #{name.inspect}"
|
29
19
|
@agents << Qswarm::Agent.new(self, name, args, &block)
|
30
20
|
end
|
31
21
|
|
32
|
-
def broker(name, &block)
|
33
|
-
logger.info "Registering broker: #{name}"
|
34
|
-
@brokers[name] = Qswarm::Broker.new(name, &block)
|
35
|
-
end
|
36
|
-
|
37
|
-
def get_broker(name)
|
38
|
-
@brokers[name]
|
39
|
-
end
|
40
|
-
|
41
22
|
def run
|
42
23
|
EventMachine.run do
|
43
24
|
@agents.map { |a| a.run }
|
data/lib/qswarm/version.rb
CHANGED
data/qswarm.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["Mark Cheverton"]
|
9
9
|
s.email = ["mark.cheverton@ecafe.org"]
|
10
10
|
s.homepage = "http://github.com/ennui2342/qswarm"
|
11
|
-
s.summary = %q{
|
12
|
-
s.description = %q{
|
11
|
+
s.summary = %q{Streaming event processing DSL for Ruby}
|
12
|
+
s.description = %q{Defines a DSL to allow stream processing from various sources for output to various sinks}
|
13
13
|
|
14
14
|
s.rubyforge_project = "qswarm"
|
15
15
|
|
@@ -27,4 +27,8 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_dependency 'uuid'
|
28
28
|
s.add_dependency 'json'
|
29
29
|
s.add_dependency 'andand'
|
30
|
+
s.add_dependency 'nokogiri'
|
31
|
+
s.add_dependency 'tweetstream'
|
32
|
+
s.add_dependency 'twitter'
|
33
|
+
s.add_dependency 'trollop'
|
30
34
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: qswarm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-12-17 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: eventmachine
|
16
|
-
requirement: &
|
16
|
+
requirement: &70217708776120 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70217708776120
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: amqp
|
27
|
-
requirement: &
|
27
|
+
requirement: &70217708775700 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70217708775700
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: uuid
|
38
|
-
requirement: &
|
38
|
+
requirement: &70217708775280 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70217708775280
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: json
|
49
|
-
requirement: &
|
49
|
+
requirement: &70217708774860 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70217708774860
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: andand
|
60
|
-
requirement: &
|
60
|
+
requirement: &70217708774440 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,9 +65,53 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
69
|
-
|
70
|
-
|
68
|
+
version_requirements: *70217708774440
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
requirement: &70217708774020 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70217708774020
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: tweetstream
|
82
|
+
requirement: &70217708773600 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70217708773600
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: twitter
|
93
|
+
requirement: &70217708773180 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :runtime
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70217708773180
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: trollop
|
104
|
+
requirement: &70217708772760 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :runtime
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *70217708772760
|
113
|
+
description: Defines a DSL to allow stream processing from various sources for output
|
114
|
+
to various sinks
|
71
115
|
email:
|
72
116
|
- mark.cheverton@ecafe.org
|
73
117
|
executables:
|
@@ -82,15 +126,12 @@ files:
|
|
82
126
|
- bin/qswarm
|
83
127
|
- lib/qswarm.rb
|
84
128
|
- lib/qswarm/agent.rb
|
85
|
-
- lib/qswarm/
|
129
|
+
- lib/qswarm/connection.rb
|
130
|
+
- lib/qswarm/connections/amqp.rb
|
131
|
+
- lib/qswarm/connections/logger.rb
|
132
|
+
- lib/qswarm/connections/twitter.rb
|
133
|
+
- lib/qswarm/connections/xmpp.rb
|
86
134
|
- lib/qswarm/dsl.rb
|
87
|
-
- lib/qswarm/listener.rb
|
88
|
-
- lib/qswarm/loggable.rb
|
89
|
-
- lib/qswarm/speaker.rb
|
90
|
-
- lib/qswarm/speakers/http.rb
|
91
|
-
- lib/qswarm/speakers/irc.rb
|
92
|
-
- lib/qswarm/speakers/mysql.rb
|
93
|
-
- lib/qswarm/speakers/nc.rb
|
94
135
|
- lib/qswarm/swarm.rb
|
95
136
|
- lib/qswarm/version.rb
|
96
137
|
- qswarm.gemspec
|
@@ -117,5 +158,5 @@ rubyforge_project: qswarm
|
|
117
158
|
rubygems_version: 1.8.15
|
118
159
|
signing_key:
|
119
160
|
specification_version: 3
|
120
|
-
summary:
|
161
|
+
summary: Streaming event processing DSL for Ruby
|
121
162
|
test_files: []
|
data/lib/qswarm/broker.rb
DELETED
@@ -1,118 +0,0 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
require 'amqp'
|
3
|
-
require 'cgi'
|
4
|
-
|
5
|
-
require 'qswarm/dsl'
|
6
|
-
|
7
|
-
module Qswarm
|
8
|
-
class Broker
|
9
|
-
include Qswarm::Loggable
|
10
|
-
extend Qswarm::DSL
|
11
|
-
|
12
|
-
dsl_accessor :name, :host, :port, :user, :pass, :vhost, :exchange_type, :exchange_name, :durable
|
13
|
-
@@connection = {}
|
14
|
-
|
15
|
-
def initialize(name, &block)
|
16
|
-
@name = name
|
17
|
-
|
18
|
-
# Set some defaults
|
19
|
-
@host = 'localhost'
|
20
|
-
@port = 5672
|
21
|
-
@user = 'guest'
|
22
|
-
@pass = 'guest'
|
23
|
-
@vhost = ''
|
24
|
-
@exchange_type = :direct
|
25
|
-
@exchange_name = ''
|
26
|
-
@durable = true
|
27
|
-
@prefetch = nil
|
28
|
-
|
29
|
-
# if block.arity == 1
|
30
|
-
# yield self
|
31
|
-
# else
|
32
|
-
# instance_eval &block
|
33
|
-
# end
|
34
|
-
|
35
|
-
self.instance_eval(&block)
|
36
|
-
|
37
|
-
@queues = {}
|
38
|
-
@channels = {}
|
39
|
-
@exchange = nil
|
40
|
-
|
41
|
-
Signal.trap("INT") do
|
42
|
-
@@connection["#{@host}:#{@port}#{@vhost}"].close do
|
43
|
-
EM.stop { exit }
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def queue name, routing_key = '', args = nil
|
49
|
-
@queues["#{name}/#{routing_key}"] ||= begin
|
50
|
-
logger.debug "Binding queue #{name}/#{routing_key}"
|
51
|
-
@queues["#{name}/#{routing_key}"] = channel(name, routing_key).queue(name, args).bind(exchange(channel(name, routing_key)), :routing_key => routing_key)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def exchange(channel = nil)
|
56
|
-
@exchange ||= begin
|
57
|
-
@exchange = AMQP::Exchange.new(channel ||= AMQP::Channel.new(connection, :auto_recovery => true), @exchange_type, @exchange_name, :durable => @durable) do |exchange|
|
58
|
-
logger.debug "Declared #{@exchange_type} exchange #{@vhost}/#{@exchange_name}"
|
59
|
-
@exchange.on_return do |basic_return, metadata, payload|
|
60
|
-
logger.error "#{payload} was returned! reply_code = #{basic_return.reply_code}, reply_text = #{basic_return.reply_text}"
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
# ruby-amqp currently limits to 1 consumer per queue (to be fixed in future) so can't pool channels
|
67
|
-
def channel name, routing_key = ''
|
68
|
-
@channels["#{name}/#{routing_key}"] ||= begin
|
69
|
-
logger.debug "Opening channel for #{name}/#{routing_key}"
|
70
|
-
@channels["#{name}/#{routing_key}"] = AMQP::Channel.new(connection, AMQP::Channel.next_channel_id, :auto_recovery => true) do |c|
|
71
|
-
@channels["#{name}/#{routing_key}"].on_error do |channel, channel_close|
|
72
|
-
logger.error "[channel.close] Reply code = #{channel_close.reply_code}, reply text = #{channel_close.reply_text}"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
def connection
|
79
|
-
# Pool connections at the class level
|
80
|
-
@@connection["#{@host}:#{@port}#{@vhost}"] ||= begin
|
81
|
-
logger.debug "Connecting to AMQP broker at #{self.to_s}"
|
82
|
-
@@connection["#{@host}:#{@port}#{@vhost}"] = AMQP.connect(self.to_s, :heartbeat => 30, :on_tcp_connection_failure => Proc.new { |settings|
|
83
|
-
logger.error "AMQP initial connection failure to #{settings[:host]}:#{settings[:port]}#{settings[:vhost]}"
|
84
|
-
EM.stop
|
85
|
-
}, :on_possible_authentication_failure => Proc.new { |settings|
|
86
|
-
logger.error "AMQP initial authentication failed for #{settings[:host]}:#{settings[:port]}#{settings[:vhost]}"
|
87
|
-
EM.stop
|
88
|
-
}
|
89
|
-
) do |c|
|
90
|
-
@@connection["#{@host}:#{@port}#{@vhost}"].on_recovery do |connection|
|
91
|
-
logger.debug "Recovered from AMQP network failure"
|
92
|
-
end
|
93
|
-
@@connection["#{@host}:#{@port}#{@vhost}"].on_connection_interruption do |connection|
|
94
|
-
# reconnect in 10 seconds
|
95
|
-
logger.error "AMQP connection interruption, reconnecting in 10s"
|
96
|
-
connection.reconnect(false, 10)
|
97
|
-
end
|
98
|
-
# Force reconnect on heartbeat loss to cope with our funny firewall issues
|
99
|
-
@@connection["#{@host}:#{@port}#{@vhost}"].on_skipped_heartbeats do |connection, settings|
|
100
|
-
logger.error "Skipped heartbeats detected"
|
101
|
-
end
|
102
|
-
@@connection["#{@host}:#{@port}#{@vhost}"].on_error do |connection, connection_close|
|
103
|
-
logger.error "AMQP connection has been closed. Reply code = #{connection_close.reply_code}, reply text = #{connection_close.reply_text}"
|
104
|
-
if connection_close.reply_code == 320
|
105
|
-
logger.error "Set a 30s reconnection timer"
|
106
|
-
# every 30 seconds
|
107
|
-
connection.periodically_reconnect(30)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
def to_s
|
115
|
-
"amqp://#{@user}:#{@pass}@#{@host}:#{@port}/#{CGI.escape(@vhost)}"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
end
|
data/lib/qswarm/listener.rb
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
require 'uuid'
|
2
|
-
require 'eventmachine'
|
3
|
-
|
4
|
-
require 'qswarm/dsl'
|
5
|
-
require 'qswarm/speaker'
|
6
|
-
|
7
|
-
module Qswarm
|
8
|
-
class Listener
|
9
|
-
include Qswarm::Loggable
|
10
|
-
extend Qswarm::DSL
|
11
|
-
|
12
|
-
dsl_accessor :name, :broker, :format
|
13
|
-
attr_reader :agent
|
14
|
-
|
15
|
-
def initialize(agent, name, args, &block)
|
16
|
-
@agent = agent
|
17
|
-
@name = name.to_s
|
18
|
-
@speakers = []
|
19
|
-
@sinks = []
|
20
|
-
@format = :json
|
21
|
-
@instances = nil
|
22
|
-
|
23
|
-
@queue_args = { :auto_delete => true, :durable => true, :exclusive => true }
|
24
|
-
@subscribe_args = { :exclusive => false, :ack => false }
|
25
|
-
|
26
|
-
@speaker = args.delete :speaker unless args.nil?
|
27
|
-
|
28
|
-
# @subscribe_args.merge! args.delete(:subscribe) unless args.nil?
|
29
|
-
@queue_args.merge! args unless args.nil?
|
30
|
-
|
31
|
-
self.instance_eval(&block)
|
32
|
-
end
|
33
|
-
|
34
|
-
def bind(routing_key, options = nil)
|
35
|
-
@bind = routing_key
|
36
|
-
@queue_args.merge! options unless options.nil?
|
37
|
-
logger.info "Binding listener #{@name} < #{routing_key}"
|
38
|
-
end
|
39
|
-
|
40
|
-
# Not sure about this
|
41
|
-
def subscribe(*options)
|
42
|
-
Array[*options].each { |o| @subscribe_args[o] = true }
|
43
|
-
end
|
44
|
-
|
45
|
-
def ack?
|
46
|
-
@subscribe_args[:ack]
|
47
|
-
end
|
48
|
-
|
49
|
-
def swarm(instances = nil)
|
50
|
-
@instances = instances
|
51
|
-
end
|
52
|
-
|
53
|
-
# Should this be subscribe options?
|
54
|
-
def uniq
|
55
|
-
@uuid = '-' + UUID.generate
|
56
|
-
end
|
57
|
-
|
58
|
-
def speak(name, args = nil, &block)
|
59
|
-
if !args.nil? && !args[:type].nil?
|
60
|
-
require "qswarm/speakers/#{args[:type].downcase}"
|
61
|
-
@speakers << eval("Qswarm::Speakers::#{args[:type].capitalize}").new(self, name, args, &block)
|
62
|
-
else
|
63
|
-
@speakers << Qswarm::Speaker.new(self, name, args, &block)
|
64
|
-
end
|
65
|
-
logger.info "Registering speaker: #{name} < #{@name}"
|
66
|
-
end
|
67
|
-
|
68
|
-
def get_broker(name = nil)
|
69
|
-
name ||= @broker
|
70
|
-
@agent.get_broker(name)
|
71
|
-
end
|
72
|
-
|
73
|
-
def run
|
74
|
-
# Any setup that needs to be done
|
75
|
-
@speakers.map { |s| s.run }
|
76
|
-
|
77
|
-
@bind ||= @name
|
78
|
-
logger.info "Listening on #{@name} < #{@bind}"
|
79
|
-
|
80
|
-
get_broker.channel(@name, @bind).prefetch(@instances) unless @instances.nil?
|
81
|
-
get_broker.queue(@name + @uuid ||= '', @bind, @queue_args).subscribe(@subscribe_args) do |metadata, payload|
|
82
|
-
logger.debug "[#{@agent.name}] Received '#{payload.inspect}' on listener #{@name}/#{metadata.routing_key}"
|
83
|
-
|
84
|
-
running = @speakers.map { |s| s.object_id }
|
85
|
-
callback = proc do |speaker|
|
86
|
-
running.delete speaker.object_id
|
87
|
-
metadata.ack if ack? && running.empty?
|
88
|
-
end
|
89
|
-
|
90
|
-
@speakers.map do |speaker|
|
91
|
-
EM.defer nil, callback do
|
92
|
-
speaker.parse(metadata, payload)
|
93
|
-
speaker
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|