noah 0.1 → 0.2
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/.gitignore +1 -0
- data/bin/noah-watcher.rb +8 -60
- data/config/warble.rb +1 -1
- data/examples/custom-watcher.rb +3 -3
- data/examples/httpclient.rb +4 -4
- data/examples/logger.rb +4 -4
- data/examples/reconfiguring-sinatra-watcher.rb +4 -4
- data/examples/reconfiguring-sinatra.rb +1 -0
- data/examples/websocket.html +1 -1
- data/examples/websocket.rb +1 -1
- data/lib/noah.rb +1 -0
- data/lib/noah/agent.rb +53 -0
- data/lib/noah/agents/dummy_agent.rb +29 -0
- data/lib/noah/agents/http_agent.rb +37 -0
- data/lib/noah/{watcher.rb → custom_watcher.rb} +6 -2
- data/lib/noah/ephemeral_routes.rb +2 -3
- data/lib/noah/models/ephemerals.rb +5 -3
- data/lib/noah/models/watchers.rb +9 -0
- data/lib/noah/version.rb +1 -1
- data/noah.gemspec +4 -1
- metadata +62 -46
- data/lib/vendor/em-hiredis/Gemfile +0 -4
- data/lib/vendor/em-hiredis/README.md +0 -61
- data/lib/vendor/em-hiredis/Rakefile +0 -2
- data/lib/vendor/em-hiredis/em-hiredis.gemspec +0 -23
- data/lib/vendor/em-hiredis/lib/em-hiredis.rb +0 -22
- data/lib/vendor/em-hiredis/lib/em-hiredis/client.rb +0 -131
- data/lib/vendor/em-hiredis/lib/em-hiredis/connection.rb +0 -61
- data/lib/vendor/em-hiredis/lib/em-hiredis/event_emitter.rb +0 -29
- data/lib/vendor/em-hiredis/lib/em-hiredis/version.rb +0 -5
data/.gitignore
CHANGED
data/bin/noah-watcher.rb
CHANGED
@@ -12,6 +12,7 @@ begin
|
|
12
12
|
require 'eventmachine'
|
13
13
|
require 'em-http-request'
|
14
14
|
require 'noah'
|
15
|
+
require 'noah/agent'
|
15
16
|
require 'json'
|
16
17
|
rescue LoadError
|
17
18
|
puts HELP
|
@@ -20,78 +21,25 @@ end
|
|
20
21
|
|
21
22
|
LOGGER = Logger.new(STDOUT)
|
22
23
|
|
23
|
-
class EventMachine::NoahAgent
|
24
|
-
include EM::Deferrable
|
25
|
-
|
26
|
-
@@watchers = Noah::Watcher.watch_list
|
27
|
-
|
28
|
-
def initialize
|
29
|
-
@logger = LOGGER
|
30
|
-
@logger.debug("Initializing with #{@@watchers.size} registered watches")
|
31
|
-
if EventMachine.reactor_running?
|
32
|
-
@worker = EM.spawn {|event, message, watch_list|
|
33
|
-
logger = LOGGER
|
34
|
-
logger.debug("Worker initiated")
|
35
|
-
logger.info("got event on http worker: #{event}")
|
36
|
-
logger.info("got message on http worker: #{message}")
|
37
|
-
matches = watch_list.find_all{|w| event =~ /^#{Base64.decode64(w)}/}
|
38
|
-
logger.debug("Found #{matches.size} matches for #{event}")
|
39
|
-
EM::Iterator.new(matches).each do |watch, iter|
|
40
|
-
p, ep = Base64.decode64(watch).split("|")
|
41
|
-
logger.info("Sending message to: #{ep} for pattern: #{p}")
|
42
|
-
http = EM::HttpRequest.new(ep, :connection_timeout => 2, :inactivity_timeout => 4).post :body => message
|
43
|
-
http.callback {
|
44
|
-
LOGGER.debug("Message posted to #{ep} successfully")
|
45
|
-
#iter.next
|
46
|
-
}
|
47
|
-
http.errback {
|
48
|
-
LOGGER.debug("Something went wrong")
|
49
|
-
#iter.net
|
50
|
-
}
|
51
|
-
iter.next
|
52
|
-
end
|
53
|
-
}
|
54
|
-
else
|
55
|
-
logger.fatal("Must be inside a reactor!")
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def watchers
|
60
|
-
@@watchers.size
|
61
|
-
end
|
62
|
-
|
63
|
-
def reread_watchers
|
64
|
-
@logger.debug("Found new watches")
|
65
|
-
@logger.debug("Current watch count: #{@@watchers.size}")
|
66
|
-
@@watchers = Noah::Watcher.watch_list
|
67
|
-
@logger.debug("New watch count: #{@@watchers.size}")
|
68
|
-
#@logger.debug(@@watchers)
|
69
|
-
end
|
70
|
-
|
71
|
-
def broker(msg)
|
72
|
-
# This is just for testing for now
|
73
|
-
@logger.warn(msg)
|
74
|
-
e,m = msg.split("|")
|
75
|
-
be = Base64.encode64(e).gsub("\n","")
|
76
|
-
@logger.info("Encoded event: #{be}")
|
77
|
-
@worker.notify e, m, @@watchers.clone
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
24
|
EventMachine.run do
|
25
|
+
EM.error_handler do |e|
|
26
|
+
LOGGER.warn(e)
|
27
|
+
end
|
82
28
|
logger = LOGGER
|
83
29
|
trap("INT") { logger.debug("Shutting down. Watches will not be fired");EM.stop }
|
84
|
-
noah =
|
30
|
+
noah = Noah::Agent.new
|
31
|
+
noah.errback{|x| logger.error("Errback: #{x}")}
|
32
|
+
noah.callback{|y| logger.info("Callback: #{y}")}
|
85
33
|
# Passing messages...like a boss
|
86
34
|
master_channel = EventMachine::Channel.new
|
87
35
|
|
88
36
|
r = EventMachine::Hiredis::Client.connect
|
37
|
+
r.errback{|x| logger.error("Unable to connect to redis: #{x}")}
|
89
38
|
logger.debug("Starting up")
|
90
39
|
r.psubscribe("//noah/*")
|
91
40
|
r.on(:pmessage) do |pattern, event, message|
|
92
41
|
noah.reread_watchers if event =~ /^\/\/noah\/watcher\/.*/
|
93
42
|
master_channel.push "#{event}|#{message}"
|
94
|
-
logger.debug("Saw[#{event}]")
|
95
43
|
end
|
96
44
|
|
97
45
|
sub = master_channel.subscribe {|msg|
|
data/config/warble.rb
CHANGED
@@ -8,7 +8,7 @@ Warbler::Config.new do |config|
|
|
8
8
|
config.includes = FileList["config.ru"]
|
9
9
|
config.excludes = FileList["noah.gemspec", "Gemfile", "Gemfile.lock"]
|
10
10
|
config.bundler = false
|
11
|
-
config.gems += ["json", "ohm", "ohm-contrib", "sinatra", "
|
11
|
+
config.gems += ["json", "ohm", "ohm-contrib", "sinatra", "haml"]
|
12
12
|
config.gem_excludes = [/^(test|spec)\//]
|
13
13
|
config.public_html = FileList["views/**/*"]
|
14
14
|
config.webxml.booter = :rack
|
data/examples/custom-watcher.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), '..','lib','noah','
|
3
|
+
require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
|
4
4
|
|
5
|
-
class StdoutWatcher < Noah::
|
5
|
+
class StdoutWatcher < Noah::CustomWatcher
|
6
6
|
redis_host "redis://127.0.0.1:6379/0"
|
7
|
-
pattern "//noah/configuration/
|
7
|
+
pattern "//noah/configuration/redis"
|
8
8
|
destination Proc.new {|x| puts x}
|
9
9
|
run!
|
10
10
|
end
|
data/examples/httpclient.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), '..','lib','noah','
|
4
|
-
require '
|
3
|
+
require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
|
4
|
+
require 'em-http-request'
|
5
5
|
|
6
6
|
|
7
|
-
class HttpPostWatch < Noah::
|
7
|
+
class HttpPostWatch < Noah::CustomWatcher
|
8
8
|
redis_host "redis://127.0.0.1:6379/0"
|
9
9
|
pattern "//noah/configuration"
|
10
|
-
destination Proc.new {|x| ::
|
10
|
+
destination Proc.new {|x| ::EM::HttpRequest.new('http://localhost:4567/webhook', :connection_timeout => 2, :inactivity_timeout => 4).post :body => x}
|
11
11
|
run!
|
12
12
|
end
|
data/examples/logger.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), '..','lib','noah','
|
3
|
+
require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
|
4
4
|
require 'logger'
|
5
5
|
|
6
|
-
class LoggingWatcher < Noah::
|
7
|
-
redis_host "redis://127.0.0.1:6379/
|
8
|
-
pattern "//noah
|
6
|
+
class LoggingWatcher < Noah::CustomWatcher
|
7
|
+
redis_host "redis://127.0.0.1:6379/0"
|
8
|
+
pattern "//noah"
|
9
9
|
destination Proc.new {|x| log = Logger.new(STDOUT); log.debug(x)}
|
10
10
|
run!
|
11
11
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require File.join(File.dirname(__FILE__), '..','lib','noah','
|
4
|
-
require '
|
3
|
+
require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
|
4
|
+
require 'em-http-request'
|
5
5
|
|
6
|
-
class HttpPostWatch < Noah::
|
6
|
+
class HttpPostWatch < Noah::CustomWatcher
|
7
7
|
redis_host "redis://127.0.0.1:6379/0"
|
8
8
|
pattern "//noah/configuration/redis_server"
|
9
|
-
destination Proc.new {|x|
|
9
|
+
destination Proc.new {|x| ::EM::HttpRequest.new('http://localhost:4567/webhook', :connection_timeout => 2, :inactivity_timeout => 4).post :body => x}
|
10
10
|
run!
|
11
11
|
end
|
data/examples/websocket.html
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
$(document).ready(function(){
|
9
9
|
function debug(str){ $("#debug").append("<p>" + str); };
|
10
10
|
|
11
|
-
ws = new WebSocket("ws://localhost:
|
11
|
+
ws = new WebSocket("ws://localhost:3009/");
|
12
12
|
ws.onmessage = function(evt) { $("#msg").append("<p>"+evt.data+"</p>"); };
|
13
13
|
ws.onclose = function() { debug("socket closed"); };
|
14
14
|
ws.onopen = function() {
|
data/examples/websocket.rb
CHANGED
@@ -20,7 +20,7 @@ EventMachine.run do
|
|
20
20
|
@channel.push "(#{event}) #{message}"
|
21
21
|
end
|
22
22
|
|
23
|
-
EventMachine::WebSocket.start(:host => "0.0.0.0", :port =>
|
23
|
+
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 3009) do |ws|
|
24
24
|
ws.onopen {
|
25
25
|
sub = @channel.subscribe { |msg|
|
26
26
|
ws.send msg
|
data/lib/noah.rb
CHANGED
@@ -10,6 +10,7 @@ require 'haml'
|
|
10
10
|
require 'yaml'
|
11
11
|
require 'sinatra/base'
|
12
12
|
|
13
|
+
require File.join(File.dirname(__FILE__), 'noah', 'custom_watcher')
|
13
14
|
require File.join(File.dirname(__FILE__), 'noah','validations')
|
14
15
|
require File.join(File.dirname(__FILE__), 'noah','models')
|
15
16
|
require File.join(File.dirname(__FILE__), 'noah','app')
|
data/lib/noah/agent.rb
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
2
|
+
require 'rubygems'
|
3
|
+
require 'logger'
|
4
|
+
require 'noah'
|
5
|
+
require 'noah/agents/http_agent'
|
6
|
+
require 'noah/agents/dummy_agent'
|
7
|
+
|
8
|
+
module Noah
|
9
|
+
class Agent
|
10
|
+
include EM::Deferrable
|
11
|
+
|
12
|
+
Noah::Agents::HttpAgent.register
|
13
|
+
Noah::Agents::DummyAgent.register
|
14
|
+
|
15
|
+
@@watchers = Noah::Watcher.watch_list
|
16
|
+
@@agents = Noah::Watchers.agents
|
17
|
+
|
18
|
+
def initialize
|
19
|
+
@logger = LOGGER
|
20
|
+
@logger.debug("Initializing with #{@@watchers.size} registered watches")
|
21
|
+
@logger.debug("#{@@agents} agents registered")
|
22
|
+
if EventMachine.reactor_running?
|
23
|
+
self.succeed("Succeed callback")
|
24
|
+
else
|
25
|
+
logger.fatal("Must be inside a reactor!")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def watchers
|
30
|
+
@@watchers.size
|
31
|
+
end
|
32
|
+
|
33
|
+
def http_worker
|
34
|
+
@http_worker
|
35
|
+
end
|
36
|
+
|
37
|
+
def reread_watchers
|
38
|
+
@logger.debug("Found new watches")
|
39
|
+
@logger.debug("Current watch count: #{@@watchers.size}")
|
40
|
+
@@watchers = Noah::Watcher.watch_list
|
41
|
+
@logger.debug("New watch count: #{@@watchers.size}")
|
42
|
+
end
|
43
|
+
|
44
|
+
def broker(msg)
|
45
|
+
e,m = msg.split("|")
|
46
|
+
be = Base64.encode64(e).gsub("\n","")
|
47
|
+
EM::Iterator.new(@@agents).each do |agent, iter|
|
48
|
+
agent.send(:notify, e, m, @@watchers.clone)
|
49
|
+
iter.next
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Noah::Agents
|
2
|
+
class DummyAgent
|
3
|
+
include EM::Deferrable
|
4
|
+
|
5
|
+
PREFIX = "dummy"
|
6
|
+
NAME = "dummy"
|
7
|
+
|
8
|
+
def self.register
|
9
|
+
Noah::Watchers.register_agent(self)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.notify(event, message, watch_list)
|
13
|
+
logger = LOGGER
|
14
|
+
logger.info("#{NAME}: Worker initiated")
|
15
|
+
logger.debug("#{NAME}: got event - #{event}")
|
16
|
+
matches = watch_list.find_all{|w| event =~ /^#{Base64.decode64(w)}/}
|
17
|
+
logger.debug("#{NAME}: Found #{matches.size} possible matches for #{event}")
|
18
|
+
EM::Iterator.new(matches).each do |watch, iter|
|
19
|
+
p, ep = Base64.decode64(watch).split("|")
|
20
|
+
if ep =~ /^#{PREFIX}/
|
21
|
+
logger.info("#{NAME}: Sending message to: #{ep} for pattern: #{p}")
|
22
|
+
logger.debug("#{NAME}: message received: #{message}")
|
23
|
+
end
|
24
|
+
iter.next
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Noah::Agents
|
4
|
+
class HttpAgent
|
5
|
+
include EM::Deferrable
|
6
|
+
|
7
|
+
PREFIX = "http"
|
8
|
+
NAME = "http"
|
9
|
+
|
10
|
+
def self.register
|
11
|
+
Noah::Watchers.register_agent(self)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.notify(event, message, watch_list)
|
15
|
+
logger = LOGGER
|
16
|
+
logger.info("#{NAME}: Worker initiated")
|
17
|
+
logger.debug("#{NAME}: got event - #{event}")
|
18
|
+
matches = watch_list.find_all{|w| event =~ /^#{Base64.decode64(w)}/}
|
19
|
+
logger.debug("#{PREFIX}: Found #{matches.size} possible matches for #{event}")
|
20
|
+
EM::Iterator.new(matches).each do |watch, iter|
|
21
|
+
p, ep = Base64.decode64(watch).split("|")
|
22
|
+
if ep =~ /^#{PREFIX}/
|
23
|
+
logger.info("#{NAME}: Sending message to (#{ep}) for pattern (#{p})")
|
24
|
+
http = EM::HttpRequest.new(ep, :connection_timeout => 2, :inactivity_timeout => 4).post :body => message
|
25
|
+
http.callback {
|
26
|
+
logger.info("#{NAME}: Message posted to #{ep} successfully")
|
27
|
+
}
|
28
|
+
http.errback {
|
29
|
+
logger.error("#{NAME}: Something went wrong with #{ep}")
|
30
|
+
}
|
31
|
+
iter.next
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -1,16 +1,20 @@
|
|
1
1
|
require 'eventmachine'
|
2
2
|
require 'uri'
|
3
3
|
require 'logger'
|
4
|
+
begin
|
5
|
+
require 'em-hiredis'
|
6
|
+
rescue LoadError
|
7
|
+
puts "Please install: em-hiredis"
|
8
|
+
end
|
4
9
|
|
5
10
|
@log = Logger.new(STDOUT)
|
6
11
|
@log.level = Logger::DEBUG
|
7
12
|
|
8
13
|
require File.join(File.dirname(__FILE__), 'passthrough')
|
9
|
-
require File.join(File.dirname(__FILE__), '..','vendor','em-hiredis','lib','em-hiredis')
|
10
14
|
|
11
15
|
module Noah
|
12
16
|
|
13
|
-
class
|
17
|
+
class CustomWatcher
|
14
18
|
extend Passthrough
|
15
19
|
|
16
20
|
passthrough :redis_host, :pattern, :destination, :run!, :run_watcher
|
@@ -21,10 +21,9 @@ class Noah::App
|
|
21
21
|
put '/e/*' do
|
22
22
|
raise("Data too large") if request.body.size > 512
|
23
23
|
d = request.body.read || nil
|
24
|
-
|
25
|
-
e
|
24
|
+
opts = {:path => "/#{params[:splat][0]}", :data => d}
|
25
|
+
e = Noah::Ephemeral.find_or_create(opts)
|
26
26
|
if e.valid?
|
27
|
-
e.save
|
28
27
|
action = e.is_new? ? "create" : "update"
|
29
28
|
r = {"action" => action, "result" => "success", "id" => e.id, "path" => e.path, "data" => e.data}
|
30
29
|
r.to_json
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Noah
|
2
|
-
class Ephemeral < Model
|
2
|
+
class Ephemeral < Model
|
3
3
|
|
4
4
|
attribute :path
|
5
5
|
attribute :data
|
@@ -18,14 +18,16 @@ module Noah
|
|
18
18
|
end
|
19
19
|
|
20
20
|
def to_hash
|
21
|
-
h = {:path => path, :data => data, :created_at => created_at, :updated_at =>
|
21
|
+
h = {:path => path, :data => data, :created_at => created_at, :updated_at => updated_at}
|
22
22
|
super.merge(h)
|
23
23
|
end
|
24
24
|
|
25
25
|
class << self
|
26
26
|
def find_or_create(opts = {})
|
27
27
|
begin
|
28
|
-
|
28
|
+
path, data = opts[:path], opts[:data]
|
29
|
+
find(:path => path).first.nil? ? (eph = new(:path => path)) : (eph = find(:path => path).first)
|
30
|
+
eph.data = data
|
29
31
|
if eph.valid?
|
30
32
|
eph.save
|
31
33
|
end
|
data/lib/noah/models/watchers.rb
CHANGED
@@ -55,8 +55,17 @@ module Noah
|
|
55
55
|
end
|
56
56
|
|
57
57
|
class Watchers
|
58
|
+
@@agents = []
|
58
59
|
def self.all(options = {})
|
59
60
|
options.empty? ? Watcher.all.sort : Watcher.find(options).sort
|
60
61
|
end
|
62
|
+
|
63
|
+
def self.register_agent(agent_class)
|
64
|
+
@@agents << agent_class
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.agents
|
68
|
+
@@agents
|
69
|
+
end
|
61
70
|
end
|
62
71
|
end
|
data/lib/noah/version.rb
CHANGED
data/noah.gemspec
CHANGED
@@ -6,6 +6,7 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "noah"
|
7
7
|
s.version = Noah::VERSION
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
+
#s.platform = "jruby"
|
9
10
|
s.authors = ["John E. Vincent"]
|
10
11
|
s.email = ["lusis.org+rubygems.org@gmail.com"]
|
11
12
|
s.homepage = "https://github.com/lusis/noah"
|
@@ -19,7 +20,8 @@ Gem::Specification.new do |s|
|
|
19
20
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
21
|
s.require_paths = ["lib"]
|
21
22
|
|
22
|
-
s.add_dependency("
|
23
|
+
s.add_dependency("eventmachine", ["1.0.0.beta.3"])
|
24
|
+
s.add_dependency("em-http-request", ["1.0.0.beta.3"])
|
23
25
|
s.add_dependency("redis", ["= 2.1.1"])
|
24
26
|
s.add_dependency("nest", ["= 1.1.0"])
|
25
27
|
s.add_dependency("rack", ["= 1.2.1"])
|
@@ -36,6 +38,7 @@ Gem::Specification.new do |s|
|
|
36
38
|
s.add_dependency("json")
|
37
39
|
s.add_development_dependency("warbler", ["= 1.2.1"])
|
38
40
|
else
|
41
|
+
s.add_dependency("hiredis", ["= 0.3.1"])
|
39
42
|
s.add_dependency("yajl-ruby")
|
40
43
|
s.add_dependency("SystemTimer") if RUBY_VERSION =~ /1.8/
|
41
44
|
s.add_dependency("thin")
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: noah
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: "0.
|
5
|
+
version: "0.2"
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- John E. Vincent
|
@@ -10,196 +10,218 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-03-
|
13
|
+
date: 2011-03-15 00:00:00 -04:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
|
-
name:
|
17
|
+
name: eventmachine
|
18
18
|
prerelease: false
|
19
19
|
requirement: &id001 !ruby/object:Gem::Requirement
|
20
20
|
none: false
|
21
21
|
requirements:
|
22
22
|
- - "="
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 0.3
|
24
|
+
version: 1.0.0.beta.3
|
25
25
|
type: :runtime
|
26
26
|
version_requirements: *id001
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: em-http-request
|
29
29
|
prerelease: false
|
30
30
|
requirement: &id002 !ruby/object:Gem::Requirement
|
31
31
|
none: false
|
32
32
|
requirements:
|
33
33
|
- - "="
|
34
34
|
- !ruby/object:Gem::Version
|
35
|
-
version:
|
35
|
+
version: 1.0.0.beta.3
|
36
36
|
type: :runtime
|
37
37
|
version_requirements: *id002
|
38
38
|
- !ruby/object:Gem::Dependency
|
39
|
-
name:
|
39
|
+
name: redis
|
40
40
|
prerelease: false
|
41
41
|
requirement: &id003 !ruby/object:Gem::Requirement
|
42
42
|
none: false
|
43
43
|
requirements:
|
44
44
|
- - "="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 1.1
|
46
|
+
version: 2.1.1
|
47
47
|
type: :runtime
|
48
48
|
version_requirements: *id003
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
|
-
name:
|
50
|
+
name: nest
|
51
51
|
prerelease: false
|
52
52
|
requirement: &id004 !ruby/object:Gem::Requirement
|
53
53
|
none: false
|
54
54
|
requirements:
|
55
55
|
- - "="
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: 1.
|
57
|
+
version: 1.1.0
|
58
58
|
type: :runtime
|
59
59
|
version_requirements: *id004
|
60
60
|
- !ruby/object:Gem::Dependency
|
61
|
-
name:
|
61
|
+
name: rack
|
62
62
|
prerelease: false
|
63
63
|
requirement: &id005 !ruby/object:Gem::Requirement
|
64
64
|
none: false
|
65
65
|
requirements:
|
66
66
|
- - "="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 1.2.
|
68
|
+
version: 1.2.1
|
69
69
|
type: :runtime
|
70
70
|
version_requirements: *id005
|
71
71
|
- !ruby/object:Gem::Dependency
|
72
|
-
name:
|
72
|
+
name: tilt
|
73
73
|
prerelease: false
|
74
74
|
requirement: &id006 !ruby/object:Gem::Requirement
|
75
75
|
none: false
|
76
76
|
requirements:
|
77
77
|
- - "="
|
78
78
|
- !ruby/object:Gem::Version
|
79
|
-
version: 1.
|
79
|
+
version: 1.2.2
|
80
80
|
type: :runtime
|
81
81
|
version_requirements: *id006
|
82
82
|
- !ruby/object:Gem::Dependency
|
83
|
-
name:
|
83
|
+
name: sinatra
|
84
84
|
prerelease: false
|
85
85
|
requirement: &id007 !ruby/object:Gem::Requirement
|
86
86
|
none: false
|
87
87
|
requirements:
|
88
88
|
- - "="
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version:
|
90
|
+
version: 1.1.2
|
91
91
|
type: :runtime
|
92
92
|
version_requirements: *id007
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
|
-
name: ohm
|
94
|
+
name: ohm
|
95
95
|
prerelease: false
|
96
96
|
requirement: &id008 !ruby/object:Gem::Requirement
|
97
97
|
none: false
|
98
98
|
requirements:
|
99
99
|
- - "="
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 0.1.
|
101
|
+
version: 0.1.3
|
102
102
|
type: :runtime
|
103
103
|
version_requirements: *id008
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
|
-
name:
|
105
|
+
name: ohm-contrib
|
106
106
|
prerelease: false
|
107
107
|
requirement: &id009 !ruby/object:Gem::Requirement
|
108
108
|
none: false
|
109
109
|
requirements:
|
110
110
|
- - "="
|
111
111
|
- !ruby/object:Gem::Version
|
112
|
-
version:
|
112
|
+
version: 0.1.1
|
113
113
|
type: :runtime
|
114
114
|
version_requirements: *id009
|
115
115
|
- !ruby/object:Gem::Dependency
|
116
|
-
name:
|
116
|
+
name: haml
|
117
117
|
prerelease: false
|
118
118
|
requirement: &id010 !ruby/object:Gem::Requirement
|
119
119
|
none: false
|
120
120
|
requirements:
|
121
121
|
- - "="
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version: 0.
|
123
|
+
version: 3.0.25
|
124
124
|
type: :runtime
|
125
125
|
version_requirements: *id010
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
127
|
+
name: vegas
|
128
128
|
prerelease: false
|
129
129
|
requirement: &id011 !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - "="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: 0.1.8
|
135
|
+
type: :runtime
|
136
|
+
version_requirements: *id011
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: hiredis
|
139
|
+
prerelease: false
|
140
|
+
requirement: &id012 !ruby/object:Gem::Requirement
|
141
|
+
none: false
|
142
|
+
requirements:
|
143
|
+
- - "="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 0.3.1
|
146
|
+
type: :runtime
|
147
|
+
version_requirements: *id012
|
148
|
+
- !ruby/object:Gem::Dependency
|
149
|
+
name: yajl-ruby
|
150
|
+
prerelease: false
|
151
|
+
requirement: &id013 !ruby/object:Gem::Requirement
|
130
152
|
none: false
|
131
153
|
requirements:
|
132
154
|
- - ">="
|
133
155
|
- !ruby/object:Gem::Version
|
134
156
|
version: "0"
|
135
157
|
type: :runtime
|
136
|
-
version_requirements: *
|
158
|
+
version_requirements: *id013
|
137
159
|
- !ruby/object:Gem::Dependency
|
138
160
|
name: thin
|
139
161
|
prerelease: false
|
140
|
-
requirement: &
|
162
|
+
requirement: &id014 !ruby/object:Gem::Requirement
|
141
163
|
none: false
|
142
164
|
requirements:
|
143
165
|
- - ">="
|
144
166
|
- !ruby/object:Gem::Version
|
145
167
|
version: "0"
|
146
168
|
type: :runtime
|
147
|
-
version_requirements: *
|
169
|
+
version_requirements: *id014
|
148
170
|
- !ruby/object:Gem::Dependency
|
149
171
|
name: diff-lcs
|
150
172
|
prerelease: false
|
151
|
-
requirement: &
|
173
|
+
requirement: &id015 !ruby/object:Gem::Requirement
|
152
174
|
none: false
|
153
175
|
requirements:
|
154
176
|
- - "="
|
155
177
|
- !ruby/object:Gem::Version
|
156
178
|
version: 1.1.2
|
157
179
|
type: :development
|
158
|
-
version_requirements: *
|
180
|
+
version_requirements: *id015
|
159
181
|
- !ruby/object:Gem::Dependency
|
160
182
|
name: sinatra-reloader
|
161
183
|
prerelease: false
|
162
|
-
requirement: &
|
184
|
+
requirement: &id016 !ruby/object:Gem::Requirement
|
163
185
|
none: false
|
164
186
|
requirements:
|
165
187
|
- - "="
|
166
188
|
- !ruby/object:Gem::Version
|
167
189
|
version: 0.5.0
|
168
190
|
type: :development
|
169
|
-
version_requirements: *
|
191
|
+
version_requirements: *id016
|
170
192
|
- !ruby/object:Gem::Dependency
|
171
193
|
name: rspec
|
172
194
|
prerelease: false
|
173
|
-
requirement: &
|
195
|
+
requirement: &id017 !ruby/object:Gem::Requirement
|
174
196
|
none: false
|
175
197
|
requirements:
|
176
198
|
- - ~>
|
177
199
|
- !ruby/object:Gem::Version
|
178
200
|
version: "2.5"
|
179
201
|
type: :development
|
180
|
-
version_requirements: *
|
202
|
+
version_requirements: *id017
|
181
203
|
- !ruby/object:Gem::Dependency
|
182
204
|
name: rcov
|
183
205
|
prerelease: false
|
184
|
-
requirement: &
|
206
|
+
requirement: &id018 !ruby/object:Gem::Requirement
|
185
207
|
none: false
|
186
208
|
requirements:
|
187
209
|
- - "="
|
188
210
|
- !ruby/object:Gem::Version
|
189
211
|
version: 0.9.9
|
190
212
|
type: :development
|
191
|
-
version_requirements: *
|
213
|
+
version_requirements: *id018
|
192
214
|
- !ruby/object:Gem::Dependency
|
193
215
|
name: rack-test
|
194
216
|
prerelease: false
|
195
|
-
requirement: &
|
217
|
+
requirement: &id019 !ruby/object:Gem::Requirement
|
196
218
|
none: false
|
197
219
|
requirements:
|
198
220
|
- - "="
|
199
221
|
- !ruby/object:Gem::Version
|
200
222
|
version: 0.5.7
|
201
223
|
type: :development
|
202
|
-
version_requirements: *
|
224
|
+
version_requirements: *id019
|
203
225
|
description: Application registry based on Apache Zookeeper
|
204
226
|
email:
|
205
227
|
- lusis.org+rubygems.org@gmail.com
|
@@ -241,10 +263,14 @@ files:
|
|
241
263
|
- examples/websocket.html
|
242
264
|
- examples/websocket.rb
|
243
265
|
- lib/noah.rb
|
266
|
+
- lib/noah/agent.rb
|
267
|
+
- lib/noah/agents/dummy_agent.rb
|
268
|
+
- lib/noah/agents/http_agent.rb
|
244
269
|
- lib/noah/app.rb
|
245
270
|
- lib/noah/application_routes.rb
|
246
271
|
- lib/noah/ark.rb
|
247
272
|
- lib/noah/configuration_routes.rb
|
273
|
+
- lib/noah/custom_watcher.rb
|
248
274
|
- lib/noah/ephemeral_routes.rb
|
249
275
|
- lib/noah/helpers.rb
|
250
276
|
- lib/noah/host_routes.rb
|
@@ -260,17 +286,7 @@ files:
|
|
260
286
|
- lib/noah/validations.rb
|
261
287
|
- lib/noah/validations/watcher_validations.rb
|
262
288
|
- lib/noah/version.rb
|
263
|
-
- lib/noah/watcher.rb
|
264
289
|
- lib/noah/watcher_routes.rb
|
265
|
-
- lib/vendor/em-hiredis/Gemfile
|
266
|
-
- lib/vendor/em-hiredis/README.md
|
267
|
-
- lib/vendor/em-hiredis/Rakefile
|
268
|
-
- lib/vendor/em-hiredis/em-hiredis.gemspec
|
269
|
-
- lib/vendor/em-hiredis/lib/em-hiredis.rb
|
270
|
-
- lib/vendor/em-hiredis/lib/em-hiredis/client.rb
|
271
|
-
- lib/vendor/em-hiredis/lib/em-hiredis/connection.rb
|
272
|
-
- lib/vendor/em-hiredis/lib/em-hiredis/event_emitter.rb
|
273
|
-
- lib/vendor/em-hiredis/lib/em-hiredis/version.rb
|
274
290
|
- noah.gemspec
|
275
291
|
- spec/application_spec.rb
|
276
292
|
- spec/configuration_spec.rb
|
@@ -1,61 +0,0 @@
|
|
1
|
-
Getting started
|
2
|
-
===============
|
3
|
-
|
4
|
-
Connect to redis
|
5
|
-
|
6
|
-
redis_client = EM::Hiredis.connect
|
7
|
-
|
8
|
-
The client is a deferrable which succeeds when the underlying connection is established so you can bind to this. This isn't necessary however - any commands sent before the connection is established (or while reconnecting) will be sent to redis on connect.
|
9
|
-
|
10
|
-
redis_client.callback { puts "Redis now connected" }
|
11
|
-
|
12
|
-
All redis commands are available without any remapping of names
|
13
|
-
|
14
|
-
redis.set('foo', 'bar').callback {
|
15
|
-
redis.get('foo').callback { |value|
|
16
|
-
p [:returned, value]
|
17
|
-
}
|
18
|
-
}
|
19
|
-
|
20
|
-
As a shortcut, if you're only interested in binding to the success case you can simply provide a block to any command
|
21
|
-
|
22
|
-
redis.get('foo') { |value|
|
23
|
-
p [:returned, value]
|
24
|
-
}
|
25
|
-
|
26
|
-
Handling failure
|
27
|
-
----------------
|
28
|
-
|
29
|
-
All commands return a deferrable. In the case that redis replies with an error (for example you called a hash operation against a set), or in the case that the redis connection is broken before the command returns, the deferrable will fail. If you care about the failure case you should bind to the errback - for example:
|
30
|
-
|
31
|
-
redis.sadd('aset', 'member').callback {
|
32
|
-
response_deferrable = redis.hget('aset', 'member')
|
33
|
-
response_deferrable.errback { |e|
|
34
|
-
p e # => #<RuntimeError: ERR Operation against a key holding the wrong kind of value>
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
Pubsub
|
39
|
-
------
|
40
|
-
|
41
|
-
This example should explain things. Once a redis connection is in a pubsub state, you must make sure you only send pubsub commands.
|
42
|
-
|
43
|
-
redis = EM::Hiredis::Client.connect
|
44
|
-
subscriber = EM::Hiredis::Client.connect
|
45
|
-
|
46
|
-
subscriber.subscribe('bar.0')
|
47
|
-
subscriber.psubscribe('bar.*')
|
48
|
-
|
49
|
-
subscriber.on(:message) { |channel, message|
|
50
|
-
p [:message, channel, message]
|
51
|
-
}
|
52
|
-
|
53
|
-
subscriber.on(:pmessage) { |key, channel, message|
|
54
|
-
p [:pmessage, key, channel, message]
|
55
|
-
}
|
56
|
-
|
57
|
-
EM.add_periodic_timer(1) {
|
58
|
-
redis.publish("bar.#{rand(2)}", "hello").errback { |e|
|
59
|
-
p [:publisherror, e]
|
60
|
-
}
|
61
|
-
}
|
@@ -1,23 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require "em-hiredis/version"
|
4
|
-
|
5
|
-
Gem::Specification.new do |s|
|
6
|
-
s.name = "em-hiredis"
|
7
|
-
s.version = EM::Hiredis::VERSION
|
8
|
-
s.platform = Gem::Platform::RUBY
|
9
|
-
s.authors = ["Martyn Loughran"]
|
10
|
-
s.email = ["me@mloughran.com"]
|
11
|
-
s.homepage = "http://github.com/mloughran/em-hiredis"
|
12
|
-
s.summary = %q{Eventmachine redis client}
|
13
|
-
s.description = %q{Eventmachine redis client using hiredis native parser}
|
14
|
-
|
15
|
-
s.add_dependency 'hiredis', '~> 0.2.0'
|
16
|
-
|
17
|
-
s.rubyforge_project = "em-hiredis"
|
18
|
-
|
19
|
-
s.files = `git ls-files`.split("\n")
|
20
|
-
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
21
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
22
|
-
s.require_paths = ["lib"]
|
23
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
|
3
|
-
module EM
|
4
|
-
module Hiredis
|
5
|
-
class << self
|
6
|
-
attr_writer :logger
|
7
|
-
|
8
|
-
def logger
|
9
|
-
@logger ||= begin
|
10
|
-
require 'logger'
|
11
|
-
log = Logger.new(STDOUT)
|
12
|
-
log.level = Logger::WARN
|
13
|
-
log
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
require 'em-hiredis/event_emitter'
|
21
|
-
require 'em-hiredis/connection'
|
22
|
-
require 'em-hiredis/client'
|
@@ -1,131 +0,0 @@
|
|
1
|
-
module EM::Hiredis
|
2
|
-
class Client
|
3
|
-
PUBSUB_MESSAGES = %w{message pmessage}.freeze
|
4
|
-
|
5
|
-
include EM::Hiredis::EventEmitter
|
6
|
-
include EM::Deferrable
|
7
|
-
|
8
|
-
def self.connect(host = 'localhost', port = 6379)
|
9
|
-
new(host, port)
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(host, port)
|
13
|
-
@host, @port = host, port
|
14
|
-
@subs, @psubs = [], []
|
15
|
-
@defs = []
|
16
|
-
@connection = EM.connect(host, port, Connection, host, port)
|
17
|
-
|
18
|
-
@connection.on(:closed) {
|
19
|
-
if @connected
|
20
|
-
@defs.each { |d| d.fail("Redis disconnected") }
|
21
|
-
@defs = []
|
22
|
-
@deferred_status = nil
|
23
|
-
@connected = false
|
24
|
-
@reconnecting = true
|
25
|
-
reconnect
|
26
|
-
else
|
27
|
-
EM.add_timer(1) { reconnect }
|
28
|
-
end
|
29
|
-
}
|
30
|
-
|
31
|
-
@connection.on(:connected) {
|
32
|
-
@connected = true
|
33
|
-
select(@db) if @db
|
34
|
-
@subs.each { |s| method_missing(:subscribe, s) }
|
35
|
-
@psubs.each { |s| method_missing(:psubscribe, s) }
|
36
|
-
succeed
|
37
|
-
|
38
|
-
if @reconnecting
|
39
|
-
@reconnecting = false
|
40
|
-
emit(:reconnected)
|
41
|
-
end
|
42
|
-
}
|
43
|
-
|
44
|
-
@connection.on(:message) { |reply|
|
45
|
-
if RuntimeError === reply
|
46
|
-
raise "Replies out of sync: #{reply.inspect}" if @defs.empty?
|
47
|
-
deferred = @defs.shift
|
48
|
-
deferred.fail(reply) if deferred
|
49
|
-
else
|
50
|
-
if reply && PUBSUB_MESSAGES.include?(reply[0]) # reply can be nil
|
51
|
-
kind, subscription, d1, d2 = *reply
|
52
|
-
|
53
|
-
case kind.to_sym
|
54
|
-
when :message
|
55
|
-
emit(:message, subscription, d1)
|
56
|
-
when :pmessage
|
57
|
-
emit(:pmessage, subscription, d1, d2)
|
58
|
-
end
|
59
|
-
else
|
60
|
-
raise "Replies out of sync: #{reply.inspect}" if @defs.empty?
|
61
|
-
deferred = @defs.shift
|
62
|
-
deferred.succeed(reply) if deferred
|
63
|
-
end
|
64
|
-
end
|
65
|
-
}
|
66
|
-
|
67
|
-
@connected = false
|
68
|
-
@reconnecting = false
|
69
|
-
end
|
70
|
-
|
71
|
-
# Indicates that commands have been sent to redis but a reply has not yet
|
72
|
-
# been received.
|
73
|
-
#
|
74
|
-
# This can be useful for example to avoid stopping the
|
75
|
-
# eventmachine reactor while there are outstanding commands
|
76
|
-
#
|
77
|
-
def pending_commands?
|
78
|
-
@connected && @defs.size > 0
|
79
|
-
end
|
80
|
-
|
81
|
-
def subscribe(channel)
|
82
|
-
@subs << channel
|
83
|
-
method_missing(:subscribe, channel)
|
84
|
-
end
|
85
|
-
|
86
|
-
def unsubscribe(channel)
|
87
|
-
@subs.delete(channel)
|
88
|
-
method_missing(:unsubscribe, channel)
|
89
|
-
end
|
90
|
-
|
91
|
-
def psubscribe(channel)
|
92
|
-
@psubs << channel
|
93
|
-
method_missing(:psubscribe, channel)
|
94
|
-
end
|
95
|
-
|
96
|
-
def punsubscribe(channel)
|
97
|
-
@psubs.delete(channel)
|
98
|
-
method_missing(:punsubscribe, channel)
|
99
|
-
end
|
100
|
-
|
101
|
-
def select(db)
|
102
|
-
@db = db
|
103
|
-
method_missing(:select, db)
|
104
|
-
end
|
105
|
-
|
106
|
-
def method_missing(sym, *args)
|
107
|
-
deferred = EM::DefaultDeferrable.new
|
108
|
-
# Shortcut for defining the callback case with just a block
|
109
|
-
deferred.callback { |result| yield(result) } if block_given?
|
110
|
-
|
111
|
-
if @connected
|
112
|
-
@connection.send_command(sym, *args)
|
113
|
-
@defs.push(deferred)
|
114
|
-
else
|
115
|
-
callback {
|
116
|
-
@connection.send_command(sym, *args)
|
117
|
-
@defs.push(deferred)
|
118
|
-
}
|
119
|
-
end
|
120
|
-
|
121
|
-
return deferred
|
122
|
-
end
|
123
|
-
|
124
|
-
private
|
125
|
-
|
126
|
-
def reconnect
|
127
|
-
EM::Hiredis.logger.debug("Trying to reconnect to Redis")
|
128
|
-
@connection.reconnect @host, @port
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
@@ -1,61 +0,0 @@
|
|
1
|
-
require 'hiredis/reader'
|
2
|
-
|
3
|
-
module EM::Hiredis
|
4
|
-
class Connection < EM::Connection
|
5
|
-
include EM::Hiredis::EventEmitter
|
6
|
-
|
7
|
-
def initialize(host, port)
|
8
|
-
super
|
9
|
-
@host, @port = host, port
|
10
|
-
end
|
11
|
-
|
12
|
-
def connection_completed
|
13
|
-
EM::Hiredis.logger.info("Connected to Redis")
|
14
|
-
@reader = ::Hiredis::Reader.new
|
15
|
-
emit(:connected)
|
16
|
-
end
|
17
|
-
|
18
|
-
def receive_data(data)
|
19
|
-
@reader.feed(data)
|
20
|
-
until (reply = @reader.gets) == false
|
21
|
-
emit(:message, reply)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def unbind
|
26
|
-
EM::Hiredis.logger.info("Disconnected from Redis")
|
27
|
-
emit(:closed)
|
28
|
-
end
|
29
|
-
|
30
|
-
def send_command(sym, *args)
|
31
|
-
send_data(command(sym, *args))
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
COMMAND_DELIMITER = "\r\n"
|
37
|
-
|
38
|
-
def command(*args)
|
39
|
-
command = []
|
40
|
-
command << "*#{args.size}"
|
41
|
-
|
42
|
-
args.each do |arg|
|
43
|
-
arg = arg.to_s
|
44
|
-
command << "$#{string_size arg}"
|
45
|
-
command << arg
|
46
|
-
end
|
47
|
-
|
48
|
-
command.join(COMMAND_DELIMITER) + COMMAND_DELIMITER
|
49
|
-
end
|
50
|
-
|
51
|
-
if "".respond_to?(:bytesize)
|
52
|
-
def string_size(string)
|
53
|
-
string.to_s.bytesize
|
54
|
-
end
|
55
|
-
else
|
56
|
-
def string_size(string)
|
57
|
-
string.to_s.size
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module EM::Hiredis
|
2
|
-
module EventEmitter
|
3
|
-
def on(event, &listener)
|
4
|
-
_listeners[event] << listener
|
5
|
-
end
|
6
|
-
|
7
|
-
def emit(event, *args)
|
8
|
-
_listeners[event].each { |l| l.call(*args) }
|
9
|
-
end
|
10
|
-
|
11
|
-
def remove_listener(event, &listener)
|
12
|
-
_listeners[event].delete(listener)
|
13
|
-
end
|
14
|
-
|
15
|
-
def remove_all_listeners(event)
|
16
|
-
_listeners.delete(event)
|
17
|
-
end
|
18
|
-
|
19
|
-
def listeners(event)
|
20
|
-
_listeners[event]
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def _listeners
|
26
|
-
@_listeners ||= Hash.new { |h,k| h[k] = [] }
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|