noah 0.1 → 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -14,3 +14,4 @@ Gemfile.lock
14
14
  doc
15
15
  .yardoc/*
16
16
  examples/log/*
17
+ examples/tmp/*
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 = EventMachine::NoahAgent.new
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", "sinatra-namespace", "haml"]
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
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.join(File.dirname(__FILE__), '..','lib','noah','watcher')
3
+ require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
4
4
 
5
- class StdoutWatcher < Noah::Watcher
5
+ class StdoutWatcher < Noah::CustomWatcher
6
6
  redis_host "redis://127.0.0.1:6379/0"
7
- pattern "//noah/configuration/redis_server"
7
+ pattern "//noah/configuration/redis"
8
8
  destination Proc.new {|x| puts x}
9
9
  run!
10
10
  end
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require File.join(File.dirname(__FILE__), '..','lib','noah','watcher')
4
- require 'excon'
3
+ require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
4
+ require 'em-http-request'
5
5
 
6
6
 
7
- class HttpPostWatch < Noah::Watcher
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| ::Excon.post("http://localhost:4567/webhook", :headers => {"Content-Type" => "application/json"}, :body => 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','watcher')
3
+ require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
4
4
  require 'logger'
5
5
 
6
- class LoggingWatcher < Noah::Watcher
7
- redis_host "redis://127.0.0.1:6379/5"
8
- pattern "//noah/application"
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','watcher')
4
- require 'excon'
3
+ require File.join(File.dirname(__FILE__), '..','lib','noah','custom_watcher')
4
+ require 'em-http-request'
5
5
 
6
- class HttpPostWatch < Noah::Watcher
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| puts x; ::Excon.put("http://localhost:4567/webhook", :headers => {"Content-Type" => "application/json"}, :body => 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
@@ -1,3 +1,4 @@
1
+ #!/usr/bin/env ruby
1
2
  require 'sinatra'
2
3
  require 'ohm'
3
4
  require 'open-uri'
@@ -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:3001/");
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() {
@@ -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 => 3001) do |ws|
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 Watcher
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
- e = Noah::Ephemeral.find_or_create(:path => "/#{params[:splat][0]}")
25
- e.data = d
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 #NYI
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 => :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
- find(opts).first.nil? ? (eph = create(opts)) : (eph = find(opts).first)
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Noah
2
- VERSION = "0.1"
2
+ VERSION = "0.2"
3
3
  end
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("hiredis", ["= 0.3.1"])
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.1"
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-11 00:00:00 -05:00
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: hiredis
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.1
24
+ version: 1.0.0.beta.3
25
25
  type: :runtime
26
26
  version_requirements: *id001
27
27
  - !ruby/object:Gem::Dependency
28
- name: redis
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: 2.1.1
35
+ version: 1.0.0.beta.3
36
36
  type: :runtime
37
37
  version_requirements: *id002
38
38
  - !ruby/object:Gem::Dependency
39
- name: nest
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.0
46
+ version: 2.1.1
47
47
  type: :runtime
48
48
  version_requirements: *id003
49
49
  - !ruby/object:Gem::Dependency
50
- name: rack
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.2.1
57
+ version: 1.1.0
58
58
  type: :runtime
59
59
  version_requirements: *id004
60
60
  - !ruby/object:Gem::Dependency
61
- name: tilt
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.2
68
+ version: 1.2.1
69
69
  type: :runtime
70
70
  version_requirements: *id005
71
71
  - !ruby/object:Gem::Dependency
72
- name: sinatra
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.1.2
79
+ version: 1.2.2
80
80
  type: :runtime
81
81
  version_requirements: *id006
82
82
  - !ruby/object:Gem::Dependency
83
- name: ohm
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: 0.1.3
90
+ version: 1.1.2
91
91
  type: :runtime
92
92
  version_requirements: *id007
93
93
  - !ruby/object:Gem::Dependency
94
- name: ohm-contrib
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.1
101
+ version: 0.1.3
102
102
  type: :runtime
103
103
  version_requirements: *id008
104
104
  - !ruby/object:Gem::Dependency
105
- name: haml
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: 3.0.25
112
+ version: 0.1.1
113
113
  type: :runtime
114
114
  version_requirements: *id009
115
115
  - !ruby/object:Gem::Dependency
116
- name: vegas
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.1.8
123
+ version: 3.0.25
124
124
  type: :runtime
125
125
  version_requirements: *id010
126
126
  - !ruby/object:Gem::Dependency
127
- name: yajl-ruby
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: *id011
158
+ version_requirements: *id013
137
159
  - !ruby/object:Gem::Dependency
138
160
  name: thin
139
161
  prerelease: false
140
- requirement: &id012 !ruby/object:Gem::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: *id012
169
+ version_requirements: *id014
148
170
  - !ruby/object:Gem::Dependency
149
171
  name: diff-lcs
150
172
  prerelease: false
151
- requirement: &id013 !ruby/object:Gem::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: *id013
180
+ version_requirements: *id015
159
181
  - !ruby/object:Gem::Dependency
160
182
  name: sinatra-reloader
161
183
  prerelease: false
162
- requirement: &id014 !ruby/object:Gem::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: *id014
191
+ version_requirements: *id016
170
192
  - !ruby/object:Gem::Dependency
171
193
  name: rspec
172
194
  prerelease: false
173
- requirement: &id015 !ruby/object:Gem::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: *id015
202
+ version_requirements: *id017
181
203
  - !ruby/object:Gem::Dependency
182
204
  name: rcov
183
205
  prerelease: false
184
- requirement: &id016 !ruby/object:Gem::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: *id016
213
+ version_requirements: *id018
192
214
  - !ruby/object:Gem::Dependency
193
215
  name: rack-test
194
216
  prerelease: false
195
- requirement: &id017 !ruby/object:Gem::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: *id017
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,4 +0,0 @@
1
- source "http://rubygems.org"
2
-
3
- # Specify your gem's dependencies in em-hiredis.gemspec
4
- gemspec
@@ -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,2 +0,0 @@
1
- require 'bundler'
2
- Bundler::GemHelper.install_tasks
@@ -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
@@ -1,5 +0,0 @@
1
- module EM
2
- module Hiredis
3
- VERSION = "0.0.1"
4
- end
5
- end