firehose 0.0.10 → 0.0.11

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,7 @@
1
1
  require 'firehose/version'
2
2
 
3
3
  require 'amqp'
4
+ require 'logger'
4
5
 
5
6
  module Firehose
6
7
  autoload :Subscription, 'firehose/subscription'
@@ -20,4 +21,13 @@ module Firehose
20
21
  def self.reset!
21
22
  @amqp = nil
22
23
  end
24
+
25
+ # Logging
26
+ def self.logger
27
+ @logger ||= Logger.new($stdout)
28
+ end
29
+
30
+ def self.logger=(logger)
31
+ @logger = logger
32
+ end
23
33
  end
@@ -5,6 +5,7 @@ module Firehose
5
5
  exchange = AMQP::Exchange.new(channel, :fanout, path, :auto_delete => true)
6
6
  # TODO How do I clean up this exchange at this point? Do I close it somehow or the channel?
7
7
  # The exchange just hangs out indefinitely now.
8
+ Firehose.logger.debug "AMQP publishing `#{message}` to `#{path}`"
8
9
  exchange.publish(message)
9
10
  exchange.delete(:if_unused => true)
10
11
  end
@@ -21,8 +21,6 @@ module Firehose
21
21
  # GET is how clients subscribe to the queue. When a messages comes in, we flush out a response,
22
22
  # close down the requeust, and the client then reconnects.
23
23
  when 'GET'
24
- p [:subscribed, cid, path]
25
-
26
24
  EM.next_tick do
27
25
  # Setup a subscription with a client id. We haven't subscribed yet here.
28
26
  subscription = Firehose::Subscription.new(cid)
@@ -32,24 +30,24 @@ module Firehose
32
30
  timer = EM.add_timer(timeout) do
33
31
  # We send a 204 OK to tell the client to reconnect.
34
32
  env['async.callback'].call [204, cors_headers, []]
35
- p [:timeout]
33
+ Firehose.logger.debug "HTTP wait `#{cid}@#{path}` timed out"
36
34
  end
37
35
 
38
36
  # Ok, now subscribe to the subscription.
39
- subscription.subscribe path do |payload|
37
+ subscription.subscribe path do |message|
40
38
  subscription.unsubscribe
41
39
  subscription = nil # Set this to nil so that our heart beat timer doesn't try to double unsub.
42
40
  EM.cancel_timer timer # Turn off the heart beat so we don't execute any of that business.
43
- env['async.callback'].call [200, cors_headers, [payload]]
41
+ env['async.callback'].call [200, cors_headers, [message]]
42
+ Firehose.logger.debug "HTTP sent `#{message}` to `#{cid}@#{path}`"
44
43
  end
44
+ Firehose.logger.debug "HTTP subscribed to `#{cid}@#{path}`"
45
45
 
46
46
  # Unsubscribe from the subscription if its still open and something bad happened
47
47
  # or the heart beat triggered before we could finish.
48
48
  env['async.close'].callback do
49
- if subscription
50
- subscription.unsubscribe
51
- p [:close_unsubscription]
52
- end
49
+ subscription.unsubscribe if subscription
50
+ Firehose.logger.debug "HTTP connection `#{cid}@#{path}` closing"
53
51
  end
54
52
  end
55
53
 
@@ -59,36 +57,43 @@ module Firehose
59
57
  # PUT is how we throw messages on to the fan-out queue.
60
58
  when 'PUT'
61
59
  body = env['rack.input'].read
62
- p [:put, path, body]
60
+ Firehose.logger.debug "HTTP published `#{body}` to `#{path}`"
63
61
  Firehose::Publisher.new.publish(path, body)
64
62
 
65
63
  [202, {}, []]
66
64
  else
65
+ Firehose.logger.debug "HTTP #{method} not supported"
67
66
  [501, {'Content-Type' => 'text/plain'}, ["#{method} not supported."]]
68
67
  end
69
68
  end
70
69
  end
71
70
 
72
71
  class WebSocket < ::Rack::WebSocket::Application
72
+ attr_reader :cid, :path
73
+
73
74
  # Subscribe to a path and make some magic happen, mmkmay?
74
75
  def on_open(env)
75
76
  req = ::Rack::Request.new(env)
76
- cid = req.params['cid']
77
- path = req.path
77
+ @cid = req.params['cid']
78
+ @path = req.path
78
79
 
79
80
  @subscription = Firehose::Subscription.new(cid)
80
- @subscription.subscribe path do |payload|
81
- send_data payload
81
+ @subscription.subscribe path do |message|
82
+ Firehose.logger.debug "WS sent `#{message}` to `#{cid}@#{path}`"
83
+ send_data message
82
84
  end
85
+ Firehose.logger.debug "WS subscribed to `#{cid}@#{path}`"
83
86
  end
84
87
 
85
88
  # Delete the subscription if the thing even happened.
86
89
  def on_close(env)
87
90
  @subscription.unsubscribe if @subscription
91
+ Firehose.logger.debug "WS connection `#{cid}@#{path}` closing"
88
92
  end
89
93
 
90
94
  # Log websocket level errors
91
95
  def on_error(env, error)
96
+ Firehose.logger.error "WS connection `#{cid}@#{path}` error `#{error}`: #{env.inspect}"
92
97
  @subscription.unsubscribe if @subscription
93
98
  end
94
99
  end
@@ -14,6 +14,8 @@ module Firehose
14
14
  @subscriber_id = subscriber_id || self.class.subscriber_id
15
15
  end
16
16
 
17
+ # TODO - Move the path to an initializer so that we can force on AMQP subscription per one
18
+ # Firehose subscription. As it stands now, you could fire off multple subscriptions to diff channels
17
19
  def subscribe(path, &block)
18
20
  queue_name = "#{subscriber_id}@#{path}"
19
21
  channel = AMQP::Channel.new(Firehose.amqp.connection).prefetch(1)
@@ -25,16 +27,18 @@ module Firehose
25
27
  # ttl starts ticking down. On the reconnect, the consumer connects to the queue and resets the
26
28
  # timer on x-expires... in theory at least.
27
29
  @consumer = AMQP::Consumer.new(channel, queue, subscriber_id)
28
- @consumer.on_delivery do |metadata, payload|
29
- p [:get, subscriber_id, @consumer.consumer_tag, path, payload]
30
- block.call(payload)
30
+ @consumer.on_delivery do |metadata, message|
31
+ Firehose.logger.debug "AMQP delivering `#{message}` to `#{subscriber_id}@#{path}`"
32
+ block.call(message)
31
33
  # The ack needs to go after the block is called. This makes sure that all processing
32
34
  # happens downstream before we remove it from the queue entirely.
33
35
  metadata.ack
34
36
  end.consume
37
+ Firehose.logger.debug "AMQP subscribed to `#{subscriber_id}@#{path}`"
35
38
  end
36
39
 
37
40
  def unsubscribe
41
+ Firehose.logger.debug "AMQP unsubscribed"
38
42
  @consumer.cancel if @consumer
39
43
  end
40
44
 
@@ -1,4 +1,4 @@
1
1
  module Firehose
2
- VERSION = "0.0.10"
3
- CODENAME = "Garden Hose"
2
+ VERSION = "0.0.11"
3
+ CODENAME = "Shouty Shamous"
4
4
  end
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.10
4
+ version: 0.0.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -14,7 +14,7 @@ date: 2012-04-28 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: eventmachine
17
- requirement: &70248892020200 !ruby/object:Gem::Requirement
17
+ requirement: &70308648263700 !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: *70248892020200
25
+ version_requirements: *70308648263700
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: amqp
28
- requirement: &70248892017640 !ruby/object:Gem::Requirement
28
+ requirement: &70308648262880 !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: *70248892017640
36
+ version_requirements: *70308648262880
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: thin
39
- requirement: &70248892031220 !ruby/object:Gem::Requirement
39
+ requirement: &70308648261900 !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: *70248892031220
47
+ version_requirements: *70308648261900
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: thor
50
- requirement: &70248892024520 !ruby/object:Gem::Requirement
50
+ requirement: &70308648260860 !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: *70248892024520
58
+ version_requirements: *70308648260860
59
59
  - !ruby/object:Gem::Dependency
60
60
  name: websocket-rack
61
- requirement: &70248892039500 !ruby/object:Gem::Requirement
61
+ requirement: &70308648260100 !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: *70248892039500
69
+ version_requirements: *70308648260100
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: faraday
72
- requirement: &70248892037240 !ruby/object:Gem::Requirement
72
+ requirement: &70308648258940 !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: *70248892037240
80
+ version_requirements: *70308648258940
81
81
  - !ruby/object:Gem::Dependency
82
82
  name: rspec
83
- requirement: &70248892032840 !ruby/object:Gem::Requirement
83
+ requirement: &70308648258020 !ruby/object:Gem::Requirement
84
84
  none: false
85
85
  requirements:
86
86
  - - ! '>='
@@ -88,10 +88,10 @@ dependencies:
88
88
  version: '0'
89
89
  type: :development
90
90
  prerelease: false
91
- version_requirements: *70248892032840
91
+ version_requirements: *70308648258020
92
92
  - !ruby/object:Gem::Dependency
93
93
  name: rack-test
94
- requirement: &70248892042160 !ruby/object:Gem::Requirement
94
+ requirement: &70308648257080 !ruby/object:Gem::Requirement
95
95
  none: false
96
96
  requirements:
97
97
  - - ! '>='
@@ -99,10 +99,10 @@ dependencies:
99
99
  version: '0'
100
100
  type: :development
101
101
  prerelease: false
102
- version_requirements: *70248892042160
102
+ version_requirements: *70308648257080
103
103
  - !ruby/object:Gem::Dependency
104
104
  name: guard-rspec
105
- requirement: &70248892053200 !ruby/object:Gem::Requirement
105
+ requirement: &70308648271320 !ruby/object:Gem::Requirement
106
106
  none: false
107
107
  requirements:
108
108
  - - ! '>='
@@ -110,10 +110,10 @@ dependencies:
110
110
  version: '0'
111
111
  type: :development
112
112
  prerelease: false
113
- version_requirements: *70248892053200
113
+ version_requirements: *70308648271320
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: guard-bundler
116
- requirement: &70248892049780 !ruby/object:Gem::Requirement
116
+ requirement: &70308648267980 !ruby/object:Gem::Requirement
117
117
  none: false
118
118
  requirements:
119
119
  - - ! '>='
@@ -121,10 +121,10 @@ dependencies:
121
121
  version: '0'
122
122
  type: :development
123
123
  prerelease: false
124
- version_requirements: *70248892049780
124
+ version_requirements: *70308648267980
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: em-http-request
127
- requirement: &70248892059480 !ruby/object:Gem::Requirement
127
+ requirement: &70308648266640 !ruby/object:Gem::Requirement
128
128
  none: false
129
129
  requirements:
130
130
  - - ~>
@@ -132,10 +132,10 @@ dependencies:
132
132
  version: 0.3.0
133
133
  type: :development
134
134
  prerelease: false
135
- version_requirements: *70248892059480
135
+ version_requirements: *70308648266640
136
136
  - !ruby/object:Gem::Dependency
137
137
  name: guard-coffeescript
138
- requirement: &70248892071480 !ruby/object:Gem::Requirement
138
+ requirement: &70308648265120 !ruby/object:Gem::Requirement
139
139
  none: false
140
140
  requirements:
141
141
  - - ! '>='
@@ -143,7 +143,7 @@ dependencies:
143
143
  version: '0'
144
144
  type: :development
145
145
  prerelease: false
146
- version_requirements: *70248892071480
146
+ version_requirements: *70308648265120
147
147
  description: Firehose is a realtime web application toolkit for building realtime
148
148
  Ruby web applications.
149
149
  email: