firering 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -84,6 +84,7 @@ end
84
84
  #
85
85
  #############################################################################
86
86
 
87
+ desc "release gem"
87
88
  task :release => :build do
88
89
  unless `git branch` =~ /^\* master$/
89
90
  puts "You must be on the master branch to release!"
data/bin/campf-notify CHANGED
@@ -12,7 +12,7 @@ if subdomain.to_s =~ /^\s*$/ || token.to_s =~ /^\s*$/ || room_name.to_s =~ /^\s*
12
12
  puts "Icon path #{icon_path} is incorrect" unless icon_path && File.exists?(icon_path)
13
13
  puts "Room name #{room_name} is missing" unless room_name =~ /\S/
14
14
  puts
15
- puts "The following environment variables are needed: "
15
+ puts "The following environment variables will be used: "
16
16
  puts
17
17
  puts "CAMPFIRE_SUBDOMAIN: #{subdomain || 'missing!'}"
18
18
  puts "CAMPFIRE_TOKEN: #{token || 'missing!'}"
data/firering.gemspec CHANGED
@@ -4,8 +4,8 @@ Gem::Specification.new do |s|
4
4
  s.rubygems_version = '1.3.5'
5
5
 
6
6
  s.name = 'firering'
7
- s.version = '1.0.1'
8
- s.date = '2010-08-16'
7
+ s.version = '1.0.2'
8
+ s.date = '2010-10-01'
9
9
  s.rubyforge_project = 'firering'
10
10
 
11
11
  s.summary = "Campfire API interface powered by EventMachine and Yajl."
@@ -12,8 +12,10 @@ module Firering
12
12
  attr_accessor :token
13
13
  attr_accessor :login
14
14
 
15
+ attr_reader :performed_retries
16
+
15
17
  def initialize(host, streaming_host = "https://streaming.campfirenow.com")
16
- @retry_delay, @redirects, @max_retries = 2, 1, 2
18
+ @retry_delay, @redirects, @max_retries, @performed_retries = 2, 1, 2, 0
17
19
  self.host, self.streaming_host = host, streaming_host
18
20
  yield self if block_given?
19
21
  end
@@ -30,6 +32,10 @@ module Firering
30
32
  @streaming_host = Addressable::URI.parse(host)
31
33
  end
32
34
 
35
+ def subdomain
36
+ host.host.split(".").first
37
+ end
38
+
33
39
  def auth_headers
34
40
  token ? {'authorization' => [token, "X"] } : {'authorization' => [login, password] }
35
41
  end
@@ -56,7 +62,7 @@ module Firering
56
62
  end
57
63
 
58
64
  http.callback {
59
- @performed_retries = 0
65
+ reset_retries_counter
60
66
  if callback
61
67
  data = Yajl::Parser.parse(http.response, :symbolize_keys => true) rescue Hash.new
62
68
  callback.call(data, http)
@@ -82,7 +88,15 @@ module Firering
82
88
  logger.info("performing streaming request to #{uri.to_s}")
83
89
  http = EventMachine::HttpRequest.new(uri).get(parameters)
84
90
 
85
- http.stream { |chunk| parser << chunk; @performed_retries= 0 }
91
+ http.stream do |chunk|
92
+ begin
93
+ parser << chunk; reset_retries_counter
94
+ rescue Yajl::ParseError
95
+ perform_retry(http) do
96
+ stream(room_id, &callback)
97
+ end
98
+ end
99
+ end
86
100
 
87
101
  # Campfire servers will try to hold the streaming connections open indefinitely.
88
102
  # However, API clients must be able to handle occasional timeouts or
@@ -97,19 +111,42 @@ module Firering
97
111
  http
98
112
  end
99
113
 
114
+ def max_retries_reached?
115
+ @performed_retries && @performed_retries >= @max_retries
116
+ end
117
+
100
118
  def perform_retry(http, &callback)
101
- if EventMachine.reactor_running? && (@performed_retries.nil? || @performed_retries < @max_retries)
102
- logger.error("http error #{http.error}. Trying again in #{retry_delay} seconds...")
103
- EventMachine::add_timer(retry_delay) do
104
- @performed_retries = (@performed_retries || 0) + 1
105
- logger.info("Reconnecting...")
106
- callback.call
119
+ if EventMachine.reactor_running?
120
+
121
+ if max_retries_reached?
122
+ logger.error("Firering performed #{performed_retries} but did not get any answer. Increase Firering::Connection.max_retries or check your internet connection.")
123
+ raise Firering::Connection::HTTPError.new(http)
124
+ else
125
+ logger.error("http error #{http.error}. Trying again in #{retry_delay} seconds...")
126
+
127
+ EventMachine::add_timer(retry_delay) do
128
+ logger.info("Reconnecting...")
129
+ increase_retries_counter
130
+ callback.call
131
+ end
107
132
  end
133
+
108
134
  else
109
135
  logger.error("The event machine loop is not running")
110
136
  raise Firering::Connection::HTTPError.new(http)
111
137
  end
112
138
  end
139
+ private :perform_retry
140
+
141
+ def reset_retries_counter
142
+ @performed_retries = 0
143
+ end
144
+ private :reset_retries_counter
145
+
146
+ def increase_retries_counter
147
+ @performed_retries = (@performed_retries || 0) + 1
148
+ end
149
+ private :increase_retries_counter
113
150
 
114
151
  class HTTPError < RuntimeError
115
152
  attr_reader :http
data/lib/firering.rb CHANGED
@@ -5,7 +5,7 @@ require 'yajl'
5
5
  require 'em-http'
6
6
 
7
7
  module Firering
8
- VERSION = '1.0.1'
8
+ VERSION = '1.0.2'
9
9
 
10
10
  class Error < StandardError; end
11
11
 
@@ -16,10 +16,46 @@ describe Firering::Connection do
16
16
  conn.stream(304355) do |message|
17
17
  message.should be_an_instance_of(Firering::Message)
18
18
  end
19
+
19
20
  EM.add_timer(1) do
20
21
  EM.stop
21
22
  end
22
23
  }
23
24
  end
24
25
 
26
+ it "performs connection retries if the connection drops" do
27
+ conn.retry_delay = 1
28
+ make_fixture_server_fail_times(conn.max_retries)
29
+ messages = []
30
+
31
+ EM.run {
32
+ conn.stream(304355) do |message|
33
+ messages << message
34
+ end
35
+ EM.add_timer(conn.max_retries * conn.retry_delay + 1) do
36
+ EM.stop
37
+ end
38
+ }
39
+
40
+ messages.should_not be_empty
41
+ end
42
+
43
+ it "raises an exception if the connection drops and performed enough retries" do
44
+ conn.retry_delay = 1
45
+ make_fixture_server_fail_times(conn.max_retries + 1)
46
+ messages = []
47
+
48
+ begin
49
+ EM.run {
50
+ conn.stream(304355) { |message| messages << message }
51
+
52
+ EM.add_timer(conn.max_retries * conn.retry_delay + 1) { EM.stop }
53
+ }
54
+ rescue Firering::Connection::HTTPError
55
+ ensure
56
+ EM.stop if EventMachine.reactor_running?
57
+ end
58
+
59
+ messages.should be_empty
60
+ end
25
61
  end
@@ -5,21 +5,72 @@ class MyLogger < Logger
5
5
  end
6
6
 
7
7
  class FixtureServer < Struct.new(:logger)
8
+
9
+ def initialize(*args)
10
+ super
11
+ @fails = 0
12
+ end
13
+
8
14
  def call(env)
9
15
  req = Rack::Request.new(env)
10
16
  res = Rack::Response.new
11
- res.write read_fixture(req)
17
+
18
+ if adjusted_fails?(req)
19
+ res.write("OK")
20
+ else
21
+ if @fails > 0
22
+ log_hi("I was requested to fail, fails left: #{ @fails }")
23
+ @fails -= 1
24
+ res.write("")
25
+ res.status = 404
26
+ else
27
+ log_hi("Trying to open fixture")
28
+ res.write read_fixture(req)
29
+ end
30
+ end
31
+
12
32
  res.finish
13
33
  end
14
34
 
35
+ def adjusted_fails?(req)
36
+ if req.path =~ /fail\/(\d+)/
37
+ log_hi("I was requested to fail next #{ @fails = $1.to_i } requests")
38
+ true
39
+ elsif req.path =~ /fail\/reset/
40
+ @fails = 0
41
+ log_hi("Fail count reset, next requests should not fail (unless a fixture is missing)")
42
+ true
43
+ else
44
+ false
45
+ end
46
+ end
47
+
48
+ def log(msg)
49
+ logger.info(" FIXTURES: #{msg}")
50
+ end
51
+
52
+ def log_hi(msg)
53
+ log("/" * 80) ; log(msg) ; log("/" * 80)
54
+ end
55
+
15
56
  def read_fixture(req)
16
57
  return "It Works!" if req.path == "" || req.path == "/"
17
- fixture = ([req.request_method.to_s.downcase] + req.path.split("/")).join("_").squeeze("_").gsub(/\d+/, "ID")
18
- path = File.expand_path(File.join(File.dirname(__FILE__), "json", fixture))
19
- logger.info("opening fixture: #{path}, #{File.file?(path)}")
20
- output = File.file?(path) ? File.read(path) : "FIXTURE NOT FOUND #{path}"
21
- logger.info("\n\n#{output}\n")
22
- output
58
+
59
+ path = fixture_path(req)
60
+
61
+ if File.file?(path)
62
+ log("Fixture found: #{path}")
63
+ File.read(path).tap { |output| logger.info("\n\n#{output}\n") }
64
+ else
65
+ log("Fixture not found: #{path}")
66
+ "FIXTURE NOT FOUND #{path}"
67
+ end
68
+ end
69
+
70
+ def fixture_path(req)
71
+ name_parts = [req.request_method.to_s.downcase] + req.path.split("/")
72
+ name = name_parts.join("_").squeeze("_").gsub(/\d+/, "ID")
73
+ File.expand_path(File.join(File.dirname(__FILE__), "json", name))
23
74
  end
24
75
  end
25
76
 
@@ -56,3 +107,11 @@ def start_fixtures_server(port)
56
107
 
57
108
  pid
58
109
  end
110
+
111
+ def make_fixture_server_fail_times(times)
112
+ open(URI("http://localhost:#{$specs_port}/fail/#{times}"))
113
+ end
114
+
115
+ def reset_fixture_server_fails
116
+ make_fixture_server_fail_times("reset")
117
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firering
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 1
10
- version: 1.0.1
9
+ - 2
10
+ version: 1.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Emmanuel Oga
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-08-16 00:00:00 -03:00
18
+ date: 2010-10-01 00:00:00 -03:00
19
19
  default_executable: campf-notify
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency