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 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