firehose 0.0.14 → 0.0.15

Sign up to get free protection for your applications and to get access to all the features.
data/firehose.gemspec CHANGED
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_runtime_dependency "em-http-request", "~> 1.0.0"
29
29
 
30
30
  s.add_development_dependency "rspec"
31
+ s.add_development_dependency "webmock"
31
32
  s.add_development_dependency "guard-rspec"
32
33
  s.add_development_dependency "guard-bundler"
33
34
  s.add_development_dependency "guard-coffeescript"
@@ -2,6 +2,7 @@ require 'uri'
2
2
 
3
3
  module Firehose
4
4
  module Default
5
+ # Default URI for the Firehose server. Consider the port "well-known" and bindable from other apps.
5
6
  URI = URI.parse("//127.0.0.1:7474").freeze
6
7
  end
7
8
  end
@@ -5,7 +5,13 @@ module Firehose
5
5
  # Publish messages to Firehose via an HTTP interface.
6
6
  class Producer
7
7
 
8
- # A DSL for publishing requests.
8
+ # Exception gets raised when a 202 is _not_ received from the server after a message is published.
9
+ PublishError = Class.new(RuntimeError)
10
+ TimeoutError = Class.new(Faraday::Error::TimeoutError)
11
+
12
+ # A DSL for publishing requests. This doesn't so much, but lets us call
13
+ # Firehose::Producer#publish('message').to('channel'). Slick eh? If you don't like it,
14
+ # just all Firehose::Producer#put('message', 'channel')
9
15
  class Builder
10
16
  def initialize(producer, message)
11
17
  @producer, @message = producer, message
@@ -17,6 +23,7 @@ module Firehose
17
23
  end
18
24
  end
19
25
 
26
+ # URI for the Firehose server. This URI does not include the path of the channel.
20
27
  attr_reader :uri
21
28
 
22
29
  def initialize(uri = Firehose::Default::URI)
@@ -35,11 +42,32 @@ module Firehose
35
42
  req.path = channel
36
43
  req.body = message
37
44
  end
38
- response.on_complete(&block) if block
45
+ response.on_complete do
46
+ case response.status
47
+ when 202 # Fire off the callback if everything worked out OK.
48
+ block.call(response) if block
49
+ else
50
+ error_handler.call PublishError.new("Could not publish #{message.inspect} to '#{uri.to_s}/#{channel}': #{response.inspect}")
51
+ end
52
+ end
53
+
54
+ # Hide Faraday with this Timeout exception, and through the error handler.
55
+ rescue Faraday::Error::TimeoutError => e
56
+ error_handler.call TimeoutError.new(e)
57
+ end
58
+
59
+ # Handle errors that could happen while publishing a message.
60
+ def on_error(&block)
61
+ @error_handler = block
62
+ end
63
+
64
+ # Raise an exception if an error occurs when connecting to the Firehose.
65
+ def error_handler
66
+ @error_handler || Proc.new{ |e| raise e }
39
67
  end
40
68
 
41
69
  # What adapter should Firehose use to PUT the message? List of adapters is
42
- # available at
70
+ # available at https://github.com/technoweenie/faraday.
43
71
  def self.adapter=(adapter)
44
72
  @adapter = adapter
45
73
  end
@@ -53,8 +81,7 @@ module Firehose
53
81
  # Build out a Faraday connection
54
82
  def conn
55
83
  @conn ||= Faraday.new(:url => uri.to_s) do |builder|
56
- builder.adapter self.class.adapter
57
- builder.response :logger
84
+ builder.adapter self.class.adapter
58
85
  end
59
86
  end
60
87
  end
@@ -1,4 +1,4 @@
1
1
  module Firehose
2
- VERSION = "0.0.14"
3
- CODENAME = "Chug Bug"
2
+ VERSION = "0.0.15"
3
+ CODENAME = "Error Reportin' Roberto"
4
4
  end
@@ -1,14 +1,14 @@
1
1
  require 'spec_helper'
2
2
 
3
- require 'thin'
4
- require 'em-http'
5
- require 'em-websocket-client'
6
-
7
3
  describe Firehose::Rack do
8
- before(:each) do
4
+ before(:all) do
9
5
  Firehose::Producer.adapter = :em_http
10
6
  end
11
7
 
8
+ after(:all) do
9
+ Firehose::Producer.adapter = nil
10
+ end
11
+
12
12
  let(:app) { Firehose::Rack::App.new }
13
13
  let(:messages) { (1..1000).map(&:to_s) }
14
14
  let(:channel) { "/firehose/integration/#{Time.now.to_i}" }
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ describe Firehose::Producer do
4
+ let(:channel) { "/channel-awesome" }
5
+ let(:url) { "#{Firehose::Default::URI}#{channel}"}
6
+ let(:publish_stub) { stub_request(:put, url) }
7
+ let(:message) { "hey dude" }
8
+
9
+ before(:all) do
10
+ Firehose::Producer.adapter = :net_http
11
+ end
12
+
13
+ after(:all) do
14
+ Firehose::Producer.adapter = nil
15
+ end
16
+
17
+ it "should publish message to channel" do
18
+ publish_stub.to_return(:body => "", :status => 202)
19
+
20
+ Firehose::Producer.new.publish(message).to(channel)
21
+ WebMock.should have_requested(:put, url).with { |req| req.body == message }
22
+ end
23
+
24
+ describe "connection error handling" do
25
+ it "should raise PublishError if not 201" do
26
+ publish_stub.to_return(:body => "", :status => 500)
27
+
28
+ lambda{
29
+ Firehose::Producer.new.publish(message).to(channel)
30
+ }.should raise_exception(Firehose::Producer::PublishError)
31
+ end
32
+
33
+ it "should use .error_handler if not 201" do
34
+ publish_stub.to_return(:body => "", :status => 500)
35
+
36
+ producer = Firehose::Producer.new
37
+ producer.on_error do |e|
38
+ e.message.should =~ /could not publish.+to/i
39
+ end
40
+ producer.publish(message).to(channel)
41
+ end
42
+
43
+ it "should raise TimeoutError if timed out" do
44
+ publish_stub.to_timeout
45
+
46
+ lambda{
47
+ Firehose::Producer.new.publish(message).to(channel)
48
+ }.should raise_exception(Firehose::Producer::TimeoutError)
49
+ end
50
+ end
51
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,19 @@
1
+ require 'logger'
2
+ require 'em-http'
3
+ require 'em-websocket-client'
4
+
1
5
  require 'firehose'
6
+ Firehose.logger = Logger.new('/dev/null')
7
+
8
+ # Lets skip the verbosity of the thin for the test output.
9
+ require 'thin'
10
+ Thin::Logging.silent = true
11
+
12
+ # We use both EM::Http and Net::Http in this test lib. When EM:Http is fired up
13
+ # we're usually hitting thins for integrations, and when Net::Http we want to mock that up.
14
+ require 'webmock/rspec'
15
+ WebMock.allow_net_connect!
2
16
 
3
- # This file was generated by the `rspec --init` command. Conventionally, all
4
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
- # Require this file using `require "spec_helper.rb"` to ensure that it is only
6
- # loaded once.
7
- #
8
17
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
9
18
  RSpec.configure do |config|
10
19
  config.treat_symbols_as_metadata_keys_with_true_values = true
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: firehose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.15
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-05-01 00:00:00.000000000 Z
13
+ date: 2012-05-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: eventmachine
17
- requirement: &70255960339200 !ruby/object:Gem::Requirement
17
+ requirement: &70353146415780 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 1.0.0.beta
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70255960339200
25
+ version_requirements: *70353146415780
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: amqp
28
- requirement: &70255960386800 !ruby/object:Gem::Requirement
28
+ requirement: &70353146414160 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 0.9.4
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70255960386800
36
+ version_requirements: *70353146414160
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: thin
39
- requirement: &70255960386300 !ruby/object:Gem::Requirement
39
+ requirement: &70353146412800 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,10 +44,10 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70255960386300
47
+ version_requirements: *70353146412800
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: thor
50
- requirement: &70255960385780 !ruby/object:Gem::Requirement
50
+ requirement: &70353146411120 !ruby/object:Gem::Requirement
51
51
  none: false
52
52
  requirements:
53
53
  - - ! '>='
@@ -55,10 +55,10 @@ dependencies:
55
55
  version: '0'
56
56
  type: :runtime
57
57
  prerelease: false
58
- version_requirements: *70255960385780
58
+ version_requirements: *70353146411120
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: faraday
61
- requirement: &70255960385320 !ruby/object:Gem::Requirement
61
+ requirement: &70353146454620 !ruby/object:Gem::Requirement
62
62
  none: false
63
63
  requirements:
64
64
  - - ! '>='
@@ -66,10 +66,10 @@ dependencies:
66
66
  version: '0'
67
67
  type: :runtime
68
68
  prerelease: false
69
- version_requirements: *70255960385320
69
+ version_requirements: *70353146454620
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: websocket-rack
72
- requirement: &70255960384580 !ruby/object:Gem::Requirement
72
+ requirement: &70353146454100 !ruby/object:Gem::Requirement
73
73
  none: false
74
74
  requirements:
75
75
  - - ! '>='
@@ -77,10 +77,10 @@ dependencies:
77
77
  version: '0'
78
78
  type: :runtime
79
79
  prerelease: false
80
- version_requirements: *70255960384580
80
+ version_requirements: *70353146454100
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: em-http-request
83
- requirement: &70255960381700 !ruby/object:Gem::Requirement
83
+ requirement: &70353146453540 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ~>
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: 1.0.0
89
89
  type: :runtime
90
90
  prerelease: false
91
- version_requirements: *70255960381700
91
+ version_requirements: *70353146453540
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: rspec
94
- requirement: &70255960381020 !ruby/object:Gem::Requirement
94
+ requirement: &70353146453060 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ! '>='
@@ -99,10 +99,21 @@ dependencies:
99
99
  version: '0'
100
100
  type: :development
101
101
  prerelease: false
102
- version_requirements: *70255960381020
102
+ version_requirements: *70353146453060
103
+ - !ruby/object:Gem::Dependency
104
+ name: webmock
105
+ requirement: &70353146452280 !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ type: :development
112
+ prerelease: false
113
+ version_requirements: *70353146452280
103
114
  - !ruby/object:Gem::Dependency
104
115
  name: guard-rspec
105
- requirement: &70255960380000 !ruby/object:Gem::Requirement
116
+ requirement: &70353146451380 !ruby/object:Gem::Requirement
106
117
  none: false
107
118
  requirements:
108
119
  - - ! '>='
@@ -110,10 +121,10 @@ dependencies:
110
121
  version: '0'
111
122
  type: :development
112
123
  prerelease: false
113
- version_requirements: *70255960380000
124
+ version_requirements: *70353146451380
114
125
  - !ruby/object:Gem::Dependency
115
126
  name: guard-bundler
116
- requirement: &70255960378880 !ruby/object:Gem::Requirement
127
+ requirement: &70353146448880 !ruby/object:Gem::Requirement
117
128
  none: false
118
129
  requirements:
119
130
  - - ! '>='
@@ -121,10 +132,10 @@ dependencies:
121
132
  version: '0'
122
133
  type: :development
123
134
  prerelease: false
124
- version_requirements: *70255960378880
135
+ version_requirements: *70353146448880
125
136
  - !ruby/object:Gem::Dependency
126
137
  name: guard-coffeescript
127
- requirement: &70255960402740 !ruby/object:Gem::Requirement
138
+ requirement: &70353146448120 !ruby/object:Gem::Requirement
128
139
  none: false
129
140
  requirements:
130
141
  - - ! '>='
@@ -132,10 +143,10 @@ dependencies:
132
143
  version: '0'
133
144
  type: :development
134
145
  prerelease: false
135
- version_requirements: *70255960402740
146
+ version_requirements: *70353146448120
136
147
  - !ruby/object:Gem::Dependency
137
148
  name: em-websocket-client
138
- requirement: &70255960401900 !ruby/object:Gem::Requirement
149
+ requirement: &70353146447120 !ruby/object:Gem::Requirement
139
150
  none: false
140
151
  requirements:
141
152
  - - ! '>='
@@ -143,7 +154,7 @@ dependencies:
143
154
  version: '0'
144
155
  type: :development
145
156
  prerelease: false
146
- version_requirements: *70255960401900
157
+ version_requirements: *70353146447120
147
158
  description: Firehose is a realtime web application toolkit for building realtime
148
159
  Ruby web applications.
149
160
  email:
@@ -183,6 +194,7 @@ files:
183
194
  - spec/integrations/amqp_resources_spec.rb
184
195
  - spec/integrations/thin_spec.rb
185
196
  - spec/lib/default_spec.rb
197
+ - spec/lib/producer_spec.rb
186
198
  - spec/spec_helper.rb
187
199
  homepage: http://firehose.io/
188
200
  licenses: []
@@ -212,4 +224,5 @@ test_files:
212
224
  - spec/integrations/amqp_resources_spec.rb
213
225
  - spec/integrations/thin_spec.rb
214
226
  - spec/lib/default_spec.rb
227
+ - spec/lib/producer_spec.rb
215
228
  - spec/spec_helper.rb