firehose 0.0.14 → 0.0.15

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