firehose 1.1.1 → 1.2.0
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.
- checksums.yaml +15 -0
- data/.rbenv-version +1 -1
- data/README.md +1 -1
- data/config/rainbows.rb +4 -3
- data/lib/firehose.rb +6 -8
- data/lib/firehose/assets.rb +1 -3
- data/lib/firehose/cli.rb +6 -8
- data/lib/firehose/client.rb +2 -84
- data/lib/firehose/client/consumer.rb +94 -0
- data/lib/firehose/client/producer.rb +106 -0
- data/lib/firehose/logging.rb +1 -4
- data/lib/{rainbows_em_swf_policy.rb → firehose/patches/rainbows.rb} +4 -2
- data/lib/firehose/patches/swf_policy_request.rb +26 -0
- data/lib/{thin_em_swf_policy.rb → firehose/patches/thin.rb} +2 -1
- data/lib/firehose/rack.rb +12 -39
- data/lib/firehose/rack/app.rb +42 -0
- data/lib/firehose/rack/{consumer_app.rb → consumer.rb} +7 -5
- data/lib/firehose/rack/{ping_app.rb → ping.rb} +4 -2
- data/lib/firehose/rack/{publisher_app.rb → publisher.rb} +3 -3
- data/lib/firehose/server.rb +16 -42
- data/lib/firehose/server/app.rb +53 -0
- data/lib/firehose/server/channel.rb +80 -0
- data/lib/firehose/server/publisher.rb +134 -0
- data/lib/firehose/server/subscriber.rb +50 -0
- data/lib/firehose/version.rb +2 -2
- data/spec/integrations/integration_test_helper.rb +2 -2
- data/spec/integrations/shared_examples.rb +3 -3
- data/spec/lib/{client_spec.rb → client/consumer_spec.rb} +0 -0
- data/spec/lib/{producer_spec.rb → client/producer_spec.rb} +13 -13
- data/spec/lib/firehose_spec.rb +7 -0
- data/spec/lib/rack/{consumer_app_spec.rb → consumer_spec.rb} +2 -2
- data/spec/lib/rack/{ping_app_spec.rb → ping_spec.rb} +3 -3
- data/spec/lib/rack/{publisher_app_spec.rb → publisher_spec.rb} +3 -3
- data/spec/lib/server/app_spec.rb +1 -0
- data/spec/lib/{channel_spec.rb → server/channel_spec.rb} +4 -4
- data/spec/lib/{publisher_spec.rb → server/publisher_spec.rb} +9 -9
- data/spec/lib/{subscriber_spec.rb → server/subscriber_spec.rb} +4 -4
- data/spec/spec_helper.rb +0 -5
- metadata +38 -77
- data/lib/firehose/channel.rb +0 -84
- data/lib/firehose/default.rb +0 -8
- data/lib/firehose/producer.rb +0 -104
- data/lib/firehose/publisher.rb +0 -127
- data/lib/firehose/subscriber.rb +0 -54
- data/lib/firehose/swf_policy_request.rb +0 -23
- data/spec/lib/broker_spec.rb +0 -30
- data/spec/lib/consumer_spec.rb +0 -66
- data/spec/lib/default_spec.rb +0 -7
@@ -0,0 +1,134 @@
|
|
1
|
+
module Firehose
|
2
|
+
module Server
|
3
|
+
class Publisher
|
4
|
+
# Number of messages that Redis buffers for the client if its
|
5
|
+
# connection drops, then reconnects.
|
6
|
+
MAX_MESSAGES = 100
|
7
|
+
|
8
|
+
# Seconds that the message buffer should live before Redis expires it.
|
9
|
+
TTL = 60*60*24
|
10
|
+
|
11
|
+
# Delimited used to frame different parts of a message that's published
|
12
|
+
# over Firehose.
|
13
|
+
PAYLOAD_DELIMITER = "\n"
|
14
|
+
|
15
|
+
# Publish a message to a Firehose channel via Redis.
|
16
|
+
def publish(channel_key, message, opts={})
|
17
|
+
# How long should we hang on to the resource once is published?
|
18
|
+
ttl = (opts[:ttl] || TTL).to_i
|
19
|
+
|
20
|
+
# TODO hi-redis isn't that awesome... we have to setup an errback per even for wrong
|
21
|
+
# commands because of the lack of a method_missing whitelist. Perhaps implement a whitelist in
|
22
|
+
# em-hiredis or us a diff lib?
|
23
|
+
if (deferrable = opts[:deferrable]).nil?
|
24
|
+
deferrable = EM::DefaultDeferrable.new
|
25
|
+
deferrable.errback do |e|
|
26
|
+
# Handle missing Lua publishing script in cache
|
27
|
+
# (such as Redis restarting or someone executing SCRIPT FLUSH)
|
28
|
+
if e.message =~ /NOSCRIPT/
|
29
|
+
deferrable.succeed
|
30
|
+
EM.next_tick do
|
31
|
+
@publish_script_digest = nil
|
32
|
+
combined_opts = opts.merge :deferrable => deferrable
|
33
|
+
self.publish channel_key, message, combined_opts
|
34
|
+
end
|
35
|
+
else
|
36
|
+
EM.next_tick { raise e }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
if @publish_script_digest.nil?
|
42
|
+
register_publish_script.errback do |e|
|
43
|
+
deferrable.fail e
|
44
|
+
end.callback do |digest|
|
45
|
+
@publish_script_digest = digest
|
46
|
+
Firehose.logger.debug "Registered Lua publishing script with Redis => #{digest}"
|
47
|
+
eval_publish_script channel_key, message, ttl, deferrable
|
48
|
+
end
|
49
|
+
else
|
50
|
+
eval_publish_script channel_key, message, ttl, deferrable
|
51
|
+
end
|
52
|
+
|
53
|
+
deferrable
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
def redis
|
58
|
+
@redis ||= EM::Hiredis.connect
|
59
|
+
end
|
60
|
+
|
61
|
+
# Serialize components of a message into something that can be dropped into Redis.
|
62
|
+
def self.to_payload(channel_key, sequence, message)
|
63
|
+
[channel_key, sequence, message].join(PAYLOAD_DELIMITER)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Deserealize components of a message back into Ruby.
|
67
|
+
def self.from_payload(payload)
|
68
|
+
payload.split(PAYLOAD_DELIMITER, method(:to_payload).arity)
|
69
|
+
end
|
70
|
+
|
71
|
+
# TODO: Make this FAR more robust. Ideally we'd whitelist the permitted
|
72
|
+
# characters and then escape or remove everything else.
|
73
|
+
# See: http://en.wikibooks.org/wiki/Lua_Programming/How_to_Lua/escape_sequence
|
74
|
+
def lua_escape(str)
|
75
|
+
str.gsub(/\\/,'\\\\\\').gsub(/"/,'\"').gsub(/\n/,'\n').gsub(/\r/,'\r')
|
76
|
+
end
|
77
|
+
|
78
|
+
def register_publish_script
|
79
|
+
redis.script 'LOAD', REDIS_PUBLISH_SCRIPT
|
80
|
+
end
|
81
|
+
|
82
|
+
def eval_publish_script(channel_key, message, ttl, deferrable)
|
83
|
+
list_key = Server.key(channel_key, :list)
|
84
|
+
script_args = [
|
85
|
+
Server.key(channel_key, :sequence),
|
86
|
+
list_key,
|
87
|
+
Server.key(:channel_updates),
|
88
|
+
ttl,
|
89
|
+
message,
|
90
|
+
MAX_MESSAGES,
|
91
|
+
PAYLOAD_DELIMITER,
|
92
|
+
channel_key
|
93
|
+
]
|
94
|
+
redis.evalsha(
|
95
|
+
@publish_script_digest, script_args.length, *script_args
|
96
|
+
).errback do |e|
|
97
|
+
deferrable.fail e
|
98
|
+
end.callback do |sequence|
|
99
|
+
Firehose.logger.debug "Redis stored/published `#{message}` to list `#{list_key}` with sequence `#{sequence}`"
|
100
|
+
deferrable.succeed
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
REDIS_PUBLISH_SCRIPT = <<-LUA
|
105
|
+
local sequence_key = KEYS[1]
|
106
|
+
local list_key = KEYS[2]
|
107
|
+
local channel_key = KEYS[3]
|
108
|
+
local ttl = KEYS[4]
|
109
|
+
local message = KEYS[5]
|
110
|
+
local max_messages = KEYS[6]
|
111
|
+
local payload_delimiter = KEYS[7]
|
112
|
+
local firehose_resource = KEYS[8]
|
113
|
+
|
114
|
+
local current_sequence = redis.call('get', sequence_key)
|
115
|
+
if current_sequence == nil or current_sequence == false then
|
116
|
+
current_sequence = 0
|
117
|
+
end
|
118
|
+
|
119
|
+
local sequence = current_sequence + 1
|
120
|
+
local message_payload = firehose_resource .. payload_delimiter .. sequence .. payload_delimiter .. message
|
121
|
+
|
122
|
+
redis.call('set', sequence_key, sequence)
|
123
|
+
redis.call('expire', sequence_key, ttl)
|
124
|
+
redis.call('lpush', list_key, message)
|
125
|
+
redis.call('ltrim', list_key, 0, max_messages - 1)
|
126
|
+
redis.call('expire', list_key, ttl)
|
127
|
+
redis.call('publish', channel_key, message_payload)
|
128
|
+
|
129
|
+
return sequence
|
130
|
+
LUA
|
131
|
+
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Firehose
|
2
|
+
module Server
|
3
|
+
# Setups a connetion to Redis to listen for new resources...
|
4
|
+
class Subscriber
|
5
|
+
attr_reader :pubsub
|
6
|
+
|
7
|
+
def initialize(redis)
|
8
|
+
@pubsub = redis.pubsub
|
9
|
+
# TODO: Instead of just raising an exception, it would probably be better
|
10
|
+
# for the errback to set some sort of 'disconnected' state. Then
|
11
|
+
# whenever a deferrable was 'subscribed' we could instantly fail
|
12
|
+
# the deferrable with whatever connection error we had.
|
13
|
+
# An alternative which would have a similar result would be to
|
14
|
+
# subscribe lazily (i.e. not until we have a deferrable to subscribe).
|
15
|
+
# Then, if connecting failed, it'd be super easy to fail the deferrable
|
16
|
+
# with the same error.
|
17
|
+
# The final goal is to allow the failed deferrable bubble back up
|
18
|
+
# so we can send back a nice, clean 500 error to the client.
|
19
|
+
pubsub.subscribe('firehose:channel_updates').
|
20
|
+
errback{|e| EM.next_tick { raise e } }.
|
21
|
+
callback { Firehose.logger.debug "Redis subscribed to `firehose:channel_updates`" }
|
22
|
+
pubsub.on(:message) do |_, payload|
|
23
|
+
channel_key, sequence, message = Server::Publisher.from_payload(payload)
|
24
|
+
|
25
|
+
if deferrables = subscriptions.delete(channel_key)
|
26
|
+
Firehose.logger.debug "Redis notifying #{deferrables.count} deferrable(s) at `#{channel_key}` with sequence `#{sequence}` and message `#{message}`"
|
27
|
+
deferrables.each do |deferrable|
|
28
|
+
Firehose.logger.debug "Sending message #{message} and sequence #{sequence} to client from subscriber"
|
29
|
+
deferrable.succeed message, sequence.to_i
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def subscribe(channel_key, deferrable)
|
36
|
+
subscriptions[channel_key].push deferrable
|
37
|
+
end
|
38
|
+
|
39
|
+
def unsubscribe(channel_key, deferrable)
|
40
|
+
subscriptions[channel_key].delete deferrable
|
41
|
+
subscriptions.delete(channel_key) if subscriptions[channel_key].empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
def subscriptions
|
46
|
+
@subscriptions ||= Hash.new{|h,k| h[k] = []}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/firehose/version.rb
CHANGED
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module IntegrationTestHelper
|
4
4
|
def start_server
|
5
5
|
@server_pid = fork do
|
6
|
-
Firehose::Server.new(:server => server, :port => uri.port).start
|
6
|
+
Firehose::Server::App.new(:server => server, :port => uri.port).start
|
7
7
|
end
|
8
8
|
|
9
9
|
# Need to give the server a chance to boot up.
|
@@ -17,6 +17,6 @@ module IntegrationTestHelper
|
|
17
17
|
|
18
18
|
# Let isn't allowed in before(:all)
|
19
19
|
def uri
|
20
|
-
Firehose::
|
20
|
+
Firehose::URI
|
21
21
|
end
|
22
22
|
end
|
@@ -7,12 +7,12 @@ shared_examples_for 'Firehose::Rack::App' do
|
|
7
7
|
include IntegrationTestHelper
|
8
8
|
|
9
9
|
before(:all) do
|
10
|
-
Firehose::Producer.adapter = :em_http
|
10
|
+
Firehose::Client::Producer::Http.adapter = :em_http
|
11
11
|
start_server
|
12
12
|
end
|
13
13
|
|
14
14
|
after(:all) do
|
15
|
-
Firehose::Producer.adapter = nil
|
15
|
+
Firehose::Client::Producer::Http.adapter = nil
|
16
16
|
stop_server
|
17
17
|
end
|
18
18
|
|
@@ -41,7 +41,7 @@ shared_examples_for 'Firehose::Rack::App' do
|
|
41
41
|
|
42
42
|
# Setup a publisher
|
43
43
|
publish = Proc.new do
|
44
|
-
Firehose::Producer.new.publish(outgoing.shift).to(channel) do
|
44
|
+
Firehose::Client::Producer::Http.new.publish(outgoing.shift).to(channel) do
|
45
45
|
# The random timer ensures that sometimes the clients will be behind
|
46
46
|
# and sometimes they will be caught up.
|
47
47
|
EM::add_timer(rand*0.005) { publish.call } unless outgoing.empty?
|
File without changes
|
@@ -1,34 +1,34 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Firehose::Producer do
|
3
|
+
describe Firehose::Client::Producer::Http do
|
4
4
|
let(:channel) { "/channel-awesome" }
|
5
|
-
let(:url) { "#{Firehose::
|
5
|
+
let(:url) { "#{Firehose::URI}#{channel}"}
|
6
6
|
let(:publish_stub) { stub_request(:put, url) }
|
7
7
|
let(:message) { "hey dude" }
|
8
8
|
|
9
9
|
before(:all) do
|
10
|
-
Firehose::Producer.adapter = :net_http
|
10
|
+
Firehose::Client::Producer::Http.adapter = :net_http
|
11
11
|
end
|
12
12
|
|
13
13
|
after(:all) do
|
14
|
-
Firehose::Producer.adapter = nil
|
14
|
+
Firehose::Client::Producer::Http.adapter = nil
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should publish message to channel" do
|
18
18
|
publish_stub.to_return(:body => "", :status => 202)
|
19
19
|
|
20
|
-
Firehose::Producer.new.publish(message).to(channel)
|
20
|
+
Firehose::Client::Producer::Http.new.publish(message).to(channel)
|
21
21
|
WebMock.should have_requested(:put, url).with { |req| req.body == message }
|
22
22
|
end
|
23
23
|
|
24
24
|
context 'prefix is specified in URI' do
|
25
|
-
let(:firehose_uri) {"#{Firehose::
|
25
|
+
let(:firehose_uri) {"#{Firehose::URI}/prefix"}
|
26
26
|
let(:url) { "#{firehose_uri}#{channel}"}
|
27
27
|
|
28
28
|
it "should publish message to channel" do
|
29
29
|
publish_stub.to_return(:body => "", :status => 202)
|
30
30
|
|
31
|
-
Firehose::Producer.new(firehose_uri).publish(message).to(channel)
|
31
|
+
Firehose::Client::Producer::Http.new(firehose_uri).publish(message).to(channel)
|
32
32
|
WebMock.should have_requested(:put, url).with { |req| req.body == message }
|
33
33
|
end
|
34
34
|
end
|
@@ -37,7 +37,7 @@ describe Firehose::Producer do
|
|
37
37
|
publish_stub.to_return(:body => "", :status => 202)
|
38
38
|
ttl = 20
|
39
39
|
|
40
|
-
Firehose::Producer.new.publish(message).to(channel, :ttl => ttl)
|
40
|
+
Firehose::Client::Producer::Http.new.publish(message).to(channel, :ttl => ttl)
|
41
41
|
WebMock.should have_requested(:put, url).with { |req| req.body == message and req.headers['Cache-Control'] == "max-age=#{ttl}" }
|
42
42
|
end
|
43
43
|
|
@@ -46,14 +46,14 @@ describe Firehose::Producer do
|
|
46
46
|
publish_stub.to_return(:body => "", :status => 500)
|
47
47
|
|
48
48
|
lambda{
|
49
|
-
Firehose::Producer.new.publish(message).to(channel)
|
50
|
-
}.should raise_exception(Firehose::Producer::PublishError)
|
49
|
+
Firehose::Client::Producer::Http.new.publish(message).to(channel)
|
50
|
+
}.should raise_exception(Firehose::Client::Producer::Http::PublishError)
|
51
51
|
end
|
52
52
|
|
53
53
|
it "should use .error_handler if not 201" do
|
54
54
|
publish_stub.to_return(:body => "", :status => 500)
|
55
55
|
|
56
|
-
producer = Firehose::Producer.new
|
56
|
+
producer = Firehose::Client::Producer::Http.new
|
57
57
|
producer.on_error do |e|
|
58
58
|
e.message.should =~ /could not publish.+to/i
|
59
59
|
end
|
@@ -64,8 +64,8 @@ describe Firehose::Producer do
|
|
64
64
|
publish_stub.to_timeout
|
65
65
|
|
66
66
|
lambda{
|
67
|
-
Firehose::Producer.new.publish(message).to(channel)
|
68
|
-
}.should raise_exception(Firehose::Producer::TimeoutError)
|
67
|
+
Firehose::Client::Producer::Http.new.publish(message).to(channel)
|
68
|
+
}.should raise_exception(Firehose::Client::Producer::Http::TimeoutError)
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'rack/test'
|
3
3
|
|
4
|
-
describe Firehose::Rack::
|
4
|
+
describe Firehose::Rack::Consumer, :type => :request do
|
5
5
|
include Rack::Test::Methods
|
6
|
-
let(:app) { Firehose::Rack::
|
6
|
+
let(:app) { Firehose::Rack::Consumer.new }
|
7
7
|
let(:path) { "/test/path/#{Time.now.to_i}" }
|
8
8
|
|
9
9
|
it "should have Content-Length on OPTIONS request"
|
@@ -2,15 +2,15 @@ require 'spec_helper'
|
|
2
2
|
require 'rack/test'
|
3
3
|
require 'async_rack_test'
|
4
4
|
|
5
|
-
describe Firehose::Rack::
|
5
|
+
describe Firehose::Rack::Ping, :type => :request do
|
6
6
|
include AsyncRackTest::Methods
|
7
|
-
let(:app) { Firehose::Rack::
|
7
|
+
let(:app) { Firehose::Rack::Ping.new dummy_redis }
|
8
8
|
let(:path) { "/test/path/#{Time.now.to_i}" }
|
9
9
|
let(:deferrable) { EM::DefaultDeferrable.new }
|
10
10
|
let(:dummy_redis) { double 'redis', :set => deferrable, :get => deferrable, :expire => deferrable }
|
11
11
|
|
12
12
|
context 'redis is available' do
|
13
|
-
before { deferrable.succeed Firehose::Rack::
|
13
|
+
before { deferrable.succeed Firehose::Rack::Ping::PingCheck::TEST_VALUE }
|
14
14
|
|
15
15
|
it "should return 200" do
|
16
16
|
ahead path
|
@@ -2,9 +2,9 @@ require 'spec_helper'
|
|
2
2
|
require 'rack/test'
|
3
3
|
require 'async_rack_test'
|
4
4
|
|
5
|
-
describe Firehose::Rack::
|
5
|
+
describe Firehose::Rack::Publisher, :type => :request do
|
6
6
|
include AsyncRackTest::Methods
|
7
|
-
let(:app) { Firehose::Rack::
|
7
|
+
let(:app) { Firehose::Rack::Publisher.new }
|
8
8
|
let(:path) { "/test/path/#{Time.now.to_i}" }
|
9
9
|
let(:deferrable) { EM::DefaultDeferrable.new }
|
10
10
|
|
@@ -27,7 +27,7 @@ describe Firehose::Rack::PublisherApp, :type => :request do
|
|
27
27
|
body = "howdy dude!"
|
28
28
|
ttl = '92'
|
29
29
|
|
30
|
-
Firehose::Publisher.any_instance.stub(:publish).with(path, body, :ttl => ttl).and_return(deferrable)
|
30
|
+
Firehose::Server::Publisher.any_instance.stub(:publish).with(path, body, :ttl => ttl).and_return(deferrable)
|
31
31
|
aput path, body, 'HTTP_CACHE_CONTROL' => 'max-age=92'
|
32
32
|
end
|
33
33
|
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# The Firehose::Server::App class is tested via the spec/integrations suite.
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Firehose::Channel do
|
3
|
+
describe Firehose::Server::Channel do
|
4
4
|
include EM::TestHelper
|
5
5
|
|
6
6
|
let(:channel_key) { '/bears/are/mean' }
|
7
|
-
let(:channel) { Firehose::Channel.new(channel_key, EM::Hiredis.connect, subscriber) }
|
8
|
-
let(:subscriber) { Firehose::Subscriber.new(EM::Hiredis.connect) }
|
7
|
+
let(:channel) { Firehose::Server::Channel.new(channel_key, EM::Hiredis.connect, subscriber) }
|
8
|
+
let(:subscriber) { Firehose::Server::Subscriber.new(EM::Hiredis.connect) }
|
9
9
|
let(:message) { 'Raaaarrrrrr!!!!' }
|
10
|
-
let(:publisher) { Firehose::Publisher.new }
|
10
|
+
let(:publisher) { Firehose::Server::Publisher.new }
|
11
11
|
|
12
12
|
describe "#next_message" do
|
13
13
|
it "should wait for message if message was not published before subscription" do
|
@@ -1,18 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Firehose::Publisher do
|
3
|
+
describe Firehose::Server::Publisher do
|
4
4
|
include EM::TestHelper
|
5
5
|
|
6
|
-
let(:publisher) { Firehose::Publisher.new }
|
6
|
+
let(:publisher) { Firehose::Server::Publisher.new }
|
7
7
|
let(:channel_key) { "/firehose/publisher/test/#{Time.now.to_i}" }
|
8
8
|
let(:message) { "howdy friends!" }
|
9
9
|
|
10
10
|
it "should have 100 MAX_MESSAGES" do
|
11
|
-
Firehose::Publisher::MAX_MESSAGES.should == 100
|
11
|
+
Firehose::Server::Publisher::MAX_MESSAGES.should == 100
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should have 1 day TTL" do
|
15
|
-
Firehose::Publisher::TTL.should == 86400
|
15
|
+
Firehose::Server::Publisher::TTL.should == 86400
|
16
16
|
end
|
17
17
|
|
18
18
|
describe "#publish" do
|
@@ -24,7 +24,7 @@ describe Firehose::Publisher do
|
|
24
24
|
msg.should == "#{channel_key}\n1\n#{message}"
|
25
25
|
em.next_tick { em.stop }
|
26
26
|
}
|
27
|
-
Firehose::Publisher.new.publish channel_key, message
|
27
|
+
Firehose::Server::Publisher.new.publish channel_key, message
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
@@ -32,7 +32,7 @@ describe Firehose::Publisher do
|
|
32
32
|
it "should publish messages with the '#{char.inspect}' character" do
|
33
33
|
msg = [char, message, char].join
|
34
34
|
em 1 do
|
35
|
-
Firehose::Publisher.new.publish(channel_key, msg).callback { em.stop }
|
35
|
+
Firehose::Server::Publisher.new.publish(channel_key, msg).callback { em.stop }
|
36
36
|
end
|
37
37
|
redis_exec('lpop', "firehose:#{channel_key}:list").should == msg
|
38
38
|
end
|
@@ -40,19 +40,19 @@ describe Firehose::Publisher do
|
|
40
40
|
|
41
41
|
it "should add message to list" do
|
42
42
|
em do
|
43
|
-
Firehose::Publisher.new.publish(channel_key, message).callback { em.stop }
|
43
|
+
Firehose::Server::Publisher.new.publish(channel_key, message).callback { em.stop }
|
44
44
|
end
|
45
45
|
redis_exec('lpop', "firehose:#{channel_key}:list").should == message
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should limit list to MAX_MESSAGES messages" do
|
49
49
|
em do
|
50
|
-
Firehose::Publisher::MAX_MESSAGES.times do |n|
|
50
|
+
Firehose::Server::Publisher::MAX_MESSAGES.times do |n|
|
51
51
|
publisher.publish(channel_key, message)
|
52
52
|
end
|
53
53
|
publisher.publish(channel_key, message).callback { em.stop }
|
54
54
|
end
|
55
|
-
redis_exec('llen', "firehose:#{channel_key}:list").should == Firehose::Publisher::MAX_MESSAGES
|
55
|
+
redis_exec('llen', "firehose:#{channel_key}:list").should == Firehose::Server::Publisher::MAX_MESSAGES
|
56
56
|
end
|
57
57
|
|
58
58
|
it "should increment sequence" do
|