firehose 1.2.20 → 2.1.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.
Files changed (91) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +36 -0
  3. data/{LICENSE.txt → LICENSE} +6 -6
  4. data/README.md +389 -139
  5. data/app/assets/javascripts/firehose.js +258 -0
  6. data/config/importmap.rb +1 -0
  7. data/db/migrate/20260214185244_create_firehose_events.rb +23 -0
  8. data/lib/commands/firehose_command.rb +119 -0
  9. data/lib/firehose/channel.rb +40 -0
  10. data/lib/firehose/cleanup_job.rb +21 -0
  11. data/lib/firehose/engine.rb +36 -0
  12. data/lib/firehose/helper.rb +40 -0
  13. data/lib/firehose/models/channel.rb +12 -0
  14. data/lib/firehose/models/message.rb +11 -0
  15. data/lib/firehose/queue.rb +44 -0
  16. data/lib/firehose/server.rb +931 -18
  17. data/lib/firehose/sse.rb +187 -0
  18. data/lib/firehose/stream.rb +32 -0
  19. data/lib/firehose/streamable.rb +25 -0
  20. data/lib/firehose/websocket.rb +242 -0
  21. data/lib/firehose.rb +67 -15
  22. data/lib/generators/firehose/install/install_generator.rb +43 -0
  23. data/lib/generators/firehose/install/templates/firehose_controller.rb +16 -0
  24. metadata +40 -428
  25. data/.env.sample +0 -17
  26. data/.gitignore +0 -12
  27. data/.rbenv-version +0 -1
  28. data/.rspec +0 -1
  29. data/.travis.yml +0 -16
  30. data/Gemfile +0 -4
  31. data/Guardfile +0 -31
  32. data/Procfile +0 -1
  33. data/Procfile.dev +0 -4
  34. data/Rakefile +0 -53
  35. data/bin/firehose +0 -9
  36. data/config/evergreen.rb +0 -9
  37. data/config/rainbows.rb +0 -17
  38. data/firehose.gemspec +0 -49
  39. data/lib/assets/javascripts/firehose/base.js.coffee +0 -4
  40. data/lib/assets/javascripts/firehose/consumer.js.coffee +0 -70
  41. data/lib/assets/javascripts/firehose/core.js.coffee +0 -5
  42. data/lib/assets/javascripts/firehose/long_poll.js.coffee +0 -149
  43. data/lib/assets/javascripts/firehose/transport.js.coffee +0 -42
  44. data/lib/assets/javascripts/firehose/version.js.coffee.erb +0 -2
  45. data/lib/assets/javascripts/firehose/web_socket.js.coffee +0 -102
  46. data/lib/assets/javascripts/firehose.js.coffee +0 -3
  47. data/lib/assets/javascripts/vendor/json2.js +0 -487
  48. data/lib/firehose/assets.rb +0 -56
  49. data/lib/firehose/cli.rb +0 -78
  50. data/lib/firehose/client/consumer.rb +0 -94
  51. data/lib/firehose/client/producer.rb +0 -108
  52. data/lib/firehose/client.rb +0 -10
  53. data/lib/firehose/logging.rb +0 -32
  54. data/lib/firehose/rack/app.rb +0 -49
  55. data/lib/firehose/rack/consumer/http_long_poll.rb +0 -86
  56. data/lib/firehose/rack/consumer/web_socket.rb +0 -95
  57. data/lib/firehose/rack/consumer.rb +0 -39
  58. data/lib/firehose/rack/ping.rb +0 -88
  59. data/lib/firehose/rack/publisher.rb +0 -53
  60. data/lib/firehose/rack.rb +0 -32
  61. data/lib/firehose/rails.rb +0 -7
  62. data/lib/firehose/server/app.rb +0 -52
  63. data/lib/firehose/server/channel.rb +0 -80
  64. data/lib/firehose/server/publisher.rb +0 -134
  65. data/lib/firehose/server/subscriber.rb +0 -51
  66. data/lib/firehose/version.rb +0 -4
  67. data/package.json +0 -5
  68. data/spec/integrations/integration_test_helper.rb +0 -22
  69. data/spec/integrations/rainbows_spec.rb +0 -7
  70. data/spec/integrations/shared_examples.rb +0 -120
  71. data/spec/integrations/thin_spec.rb +0 -7
  72. data/spec/javascripts/firehose/base_spec.coffee +0 -2
  73. data/spec/javascripts/firehose/consumer_spec.coffee +0 -45
  74. data/spec/javascripts/firehose/long_poll_spec.coffee +0 -44
  75. data/spec/javascripts/firehose/transport_spec.coffee +0 -32
  76. data/spec/javascripts/firehose/websocket_spec.coffee +0 -25
  77. data/spec/javascripts/helpers/spec_helper.js +0 -30
  78. data/spec/javascripts/support/sinon-1.7.3.js +0 -4290
  79. data/spec/lib/assets_spec.rb +0 -35
  80. data/spec/lib/client/consumer_spec.rb +0 -13
  81. data/spec/lib/client/producer_spec.rb +0 -71
  82. data/spec/lib/firehose_spec.rb +0 -7
  83. data/spec/lib/rack/consumer/http_long_poll_spec.rb +0 -12
  84. data/spec/lib/rack/consumer_spec.rb +0 -19
  85. data/spec/lib/rack/ping_spec.rb +0 -28
  86. data/spec/lib/rack/publisher_spec.rb +0 -34
  87. data/spec/lib/server/app_spec.rb +0 -15
  88. data/spec/lib/server/channel_spec.rb +0 -164
  89. data/spec/lib/server/publisher_spec.rb +0 -84
  90. data/spec/lib/server/subscriber_spec.rb +0 -69
  91. data/spec/spec_helper.rb +0 -77
@@ -1,35 +0,0 @@
1
- require 'spec_helper'
2
- require 'sprockets'
3
-
4
- describe Firehose::Assets do
5
- describe ".path" do
6
- it "should have root path" do
7
- Firehose::Assets.path('poop').should == File.expand_path('../../../lib/assets/poop', __FILE__)
8
- end
9
-
10
- it "should accept folders" do
11
- Firehose::Assets.path('poop').should == File.join(Firehose::Assets.path, 'poop')
12
- end
13
- end
14
-
15
- describe "Sprockets.configure" do
16
- it "should configure environment" do
17
- env = Firehose::Assets::Sprockets.configure Sprockets::Environment.new
18
- env.paths.should include(Firehose::Assets.path('javascripts'))
19
- end
20
- end
21
-
22
- describe "Sprockets.javascript" do
23
- let(:js_spot_checks) do
24
- [
25
- "Firehose.Transport",
26
- "Firehose.version",
27
- "global.Firehose || (global.Firehose = {})",
28
- "window.Firehose || (window.Firehose = {})"
29
- ]
30
- end
31
- it "should compile javascript" do
32
- Firehose::Assets::Sprockets.javascript.should include(*js_spot_checks)
33
- end
34
- end
35
- end
@@ -1,13 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose::Client::Consumer::WebSocket do
4
- context "transport" do
5
- # Transport for Firehose::Client::App class is tested via the spec/integrations suite.
6
- end
7
- end
8
-
9
- describe Firehose::Client::Consumer::HttpLongPoll do
10
- context "transport" do
11
- # Transport for Firehose::Client::App class is tested via the spec/integrations suite.
12
- end
13
- end
@@ -1,71 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose::Client::Producer::Http do
4
- let(:channel) { "/channel-awesome" }
5
- let(:url) { "#{Firehose::URI}#{channel}"}
6
- let(:publish_stub) { stub_request(:put, url) }
7
- let(:message) { "hey dude" }
8
-
9
- before(:all) do
10
- Firehose::Client::Producer::Http.adapter = :net_http
11
- end
12
-
13
- after(:all) do
14
- Firehose::Client::Producer::Http.adapter = nil
15
- end
16
-
17
- it "should publish message to channel" do
18
- publish_stub.to_return(:body => "", :status => 202)
19
-
20
- Firehose::Client::Producer::Http.new.publish(message).to(channel)
21
- WebMock.should have_requested(:put, url).with { |req| req.body == message }
22
- end
23
-
24
- context 'prefix is specified in URI' do
25
- let(:firehose_uri) {"#{Firehose::URI}/prefix"}
26
- let(:url) { "#{firehose_uri}#{channel}"}
27
-
28
- it "should publish message to channel" do
29
- publish_stub.to_return(:body => "", :status => 202)
30
-
31
- Firehose::Client::Producer::Http.new(firehose_uri).publish(message).to(channel)
32
- WebMock.should have_requested(:put, url).with { |req| req.body == message }
33
- end
34
- end
35
-
36
- it "should publish message to channel with expiry headers" do
37
- publish_stub.to_return(:body => "", :status => 202)
38
- ttl = 20
39
-
40
- Firehose::Client::Producer::Http.new.publish(message).to(channel, :ttl => ttl)
41
- WebMock.should have_requested(:put, url).with { |req| req.body == message and req.headers['Cache-Control'] == "max-age=#{ttl}" }
42
- end
43
-
44
- describe "connection error handling" do
45
- it "should raise PublishError if not 201" do
46
- publish_stub.to_return(:body => "", :status => 500)
47
-
48
- lambda{
49
- Firehose::Client::Producer::Http.new.publish(message).to(channel)
50
- }.should raise_exception(Firehose::Client::Producer::Http::PublishError)
51
- end
52
-
53
- it "should use .error_handler if not 201" do
54
- publish_stub.to_return(:body => "", :status => 500)
55
-
56
- producer = Firehose::Client::Producer::Http.new
57
- producer.on_error do |e|
58
- e.message.should =~ /could not publish.+to/i
59
- end
60
- producer.publish(message).to(channel)
61
- end
62
-
63
- it "should raise TimeoutError if timed out" do
64
- publish_stub.to_timeout
65
-
66
- lambda{
67
- Firehose::Client::Producer::Http.new.publish(message).to(channel)
68
- }.should raise_exception(Firehose::Client::Producer::Http::TimeoutError)
69
- end
70
- end
71
- end
@@ -1,7 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose do
4
- it "should have 7474 for default port" do
5
- Firehose::URI.to_s.should == '//0.0.0.0:7474'
6
- end
7
- end
@@ -1,12 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose::Rack::Consumer::HttpLongPoll do
4
- context "transport" do
5
- # Transport for Firehose::Rack::App class is tested via the spec/integrations suite.
6
- end
7
- context "configuration" do
8
- it "should have #timeout" do
9
- Firehose::Rack::Consumer::HttpLongPoll.new(200).timeout.should == 200
10
- end
11
- end
12
- end
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
- require 'rack/test'
3
-
4
- describe Firehose::Rack::Consumer, :type => :request do
5
- include Rack::Test::Methods
6
- let(:app) { Firehose::Rack::Consumer.new }
7
- let(:path) { "/test/path/#{Time.now.to_i}" }
8
-
9
- it "should have Content-Length on OPTIONS request"
10
- it "should have Content-Length on GET request"
11
-
12
- context "configuration" do
13
- let(:app) { Firehose::Rack::Consumer }
14
-
15
- it "should configure long polling timeout" do
16
- app.new{ |a| a.http_long_poll.timeout = 300 }.http_long_poll.timeout.should == 300
17
- end
18
- end
19
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
- require 'rack/test'
3
- require 'async_rack_test'
4
-
5
- describe Firehose::Rack::Ping, :type => :request do
6
- include AsyncRackTest::Methods
7
- let(:app) { Firehose::Rack::Ping.new dummy_redis }
8
- let(:path) { "/test/path/#{Time.now.to_i}" }
9
- let(:deferrable) { EM::DefaultDeferrable.new }
10
- let(:dummy_redis) { double 'redis', :set => deferrable, :get => deferrable, :expire => deferrable }
11
-
12
- context 'redis is available' do
13
- before { deferrable.succeed Firehose::Rack::Ping::PingCheck::TEST_VALUE }
14
-
15
- it "should return 200" do
16
- ahead path
17
- last_response.status.should == 200
18
- end
19
- end
20
-
21
- context 'redis is not available' do
22
- before { deferrable.fail 'some error' }
23
- it "should return 500" do
24
- ahead path
25
- last_response.status.should == 500
26
- end
27
- end
28
- end
@@ -1,34 +0,0 @@
1
- require 'spec_helper'
2
- require 'rack/test'
3
- require 'async_rack_test'
4
-
5
- describe Firehose::Rack::Publisher, :type => :request do
6
- include AsyncRackTest::Methods
7
- let(:app) { Firehose::Rack::Publisher.new }
8
- let(:path) { "/test/path/#{Time.now.to_i}" }
9
- let(:deferrable) { EM::DefaultDeferrable.new }
10
-
11
- context 'publishing is successful' do
12
- before { deferrable.succeed }
13
-
14
- it "should return 202" do
15
- app.stub(:publisher => double('publisher', :publish => deferrable))
16
- aput path, :body => "some nice little message"
17
- last_response.status.should == 202
18
- end
19
-
20
- it "should have Content-Length of zero" do
21
- app.stub(:publisher => double('publisher', :publish => deferrable))
22
- aput path, :body => "some nice little message"
23
- last_response.headers['Content-Length'].should == '0'
24
- end
25
-
26
- it "should parse Cache-Control max-age" do
27
- body = "howdy dude!"
28
- ttl = '92'
29
-
30
- Firehose::Server::Publisher.any_instance.stub(:publish).with(path, body, :ttl => ttl).and_return(deferrable)
31
- aput path, body, 'HTTP_CACHE_CONTROL' => 'max-age=92'
32
- end
33
- end
34
- end
@@ -1,15 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose::Rack::App do
4
- context "transport" do
5
- # Transport for Firehose::Rack::App class is tested via the spec/integrations suite.
6
- end
7
-
8
- context "configuration" do
9
- let(:app) { Firehose::Rack::App }
10
-
11
- it "should configure long polling timeout" do
12
- app.new{ |a| a.consumer.http_long_poll.timeout = 300 }.consumer.http_long_poll.timeout.should == 300
13
- end
14
- end
15
- end
@@ -1,164 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose::Server::Channel do
4
- include EM::TestHelper
5
-
6
- let(:channel_key) { '/bears/are/mean' }
7
- let(:channel) { Firehose::Server::Channel.new(channel_key, EM::Hiredis.connect, subscriber) }
8
- let(:subscriber) { Firehose::Server::Subscriber.new(EM::Hiredis.connect) }
9
- let(:message) { 'Raaaarrrrrr!!!!' }
10
- let(:publisher) { Firehose::Server::Publisher.new }
11
-
12
- describe "#next_message" do
13
- it "should wait for message if message was not published before subscription" do
14
- em do
15
- channel.next_message.callback do |msg, seq|
16
- msg.should == message
17
- seq.should == 1
18
- em.next_tick { em.stop }
19
- end
20
-
21
- publisher.publish(channel_key, message)
22
- end
23
- end
24
-
25
- it "should return the latest message and sequence if no sequence is given" do
26
- redis_exec 'lpush', "firehose:#{channel_key}:list", message
27
- redis_exec 'set', "firehose:#{channel_key}:sequence", '100'
28
-
29
- em do
30
- channel.next_message.callback do |msg, seq|
31
- msg.should == message
32
- seq.should == 100
33
-
34
- # This must happen _after_ the callback runs in order to pass consistently.
35
- em.next_tick { em.stop }
36
- end
37
- end
38
- end
39
-
40
- it "should wait for message if most recent sequence is given" do
41
- redis_exec 'lpush', "firehose:#{channel_key}:list", message
42
- redis_exec 'set', "firehose:#{channel_key}:sequence", '100'
43
-
44
- em 3 do
45
- channel.next_message(100).callback do |msg, seq|
46
- msg.should == message
47
- seq.should == 101
48
- em.next_tick { em.stop }
49
- end.errback
50
-
51
- publisher.publish(channel_key, message)
52
- end
53
- end
54
-
55
- it "should wait for message if a future sequence is given" do
56
- redis_exec 'lpush', "firehose:#{channel_key}:list", message
57
- redis_exec 'set', "firehose:#{channel_key}:sequence", '100'
58
-
59
- em 3 do
60
- channel.next_message(101).callback do |msg, seq|
61
- msg.should == message
62
- seq.should == 101
63
- em.next_tick { em.stop }
64
- end.errback
65
-
66
- publisher.publish(channel_key, message)
67
- end
68
- end
69
-
70
- it "should immediatly get a message if message sequence is behind and in list" do
71
- messages = %w[a b c d e]
72
-
73
- em 3 do
74
- publish_messages(messages) do
75
- channel.next_message(2).callback do |msg, seq|
76
- msg.should == 'c'
77
- seq.should == 3
78
-
79
- # This must happen _after_ the callback runs in order to pass consistently.
80
- em.next_tick { em.stop }
81
- end
82
- end
83
- end
84
- end
85
-
86
- it "should get current message if sequence is really far behind in list" do
87
- messages = ('aa'..'zz').to_a
88
-
89
- em 3 do
90
- publish_messages(messages) do
91
- channel.next_message(2).callback do |msg, seq|
92
- msg.should == messages.last
93
- seq.should == messages.size
94
-
95
- # This must happen _after_ the callback runs in order to pass consistently.
96
- em.next_tick { em.stop }
97
- end
98
- end
99
- end
100
- end
101
-
102
- context "a timeout is set" do
103
- it "should timeout if message isn't published in time" do
104
- redis_exec 'lpush', "firehose:#{channel_key}:list", message
105
- redis_exec 'set', "firehose:#{channel_key}:sequence", '100'
106
-
107
- em 3 do
108
- channel.next_message(100, :timeout => 1).callback do |msg, seq|
109
- raise 'test failed'
110
- end.errback do |e|
111
- e.should == :timeout
112
- em.next_tick { em.stop }
113
- end
114
-
115
- EM::add_timer(2) do
116
- publisher.publish(channel_key, message)
117
- end
118
- end
119
- end
120
-
121
- it "should not timeout if message is published in time" do
122
- redis_exec 'lpush', "firehose:#{channel_key}:list", message
123
- redis_exec 'set', "firehose:#{channel_key}:sequence", '100'
124
-
125
- em 3 do
126
- d = channel.next_message(100, :timeout => 2).callback do |msg, seq|
127
- msg.should == message
128
- seq.should == 101
129
- EM::add_timer(1) do
130
- em.stop
131
- end
132
- end.errback do |e|
133
- raise 'test failed'
134
- end
135
-
136
- d.should_not_receive(:fail)
137
-
138
- EM::add_timer(1) do
139
- publisher.publish(channel_key, message)
140
- end
141
- end
142
- end
143
- end
144
- end
145
-
146
-
147
- # Publishes the given messages and executes the given block when finished.
148
- def publish_messages(all_messages)
149
- publish = Proc.new do |messages_to_publish|
150
- msg = messages_to_publish.shift
151
- publisher.publish(channel_key, msg).callback do
152
- if messages_to_publish.empty?
153
- # Publishing is done, proceed with the test
154
- yield
155
- else
156
- # Publish the next message
157
- publish.call messages_to_publish
158
- end
159
- end
160
- end
161
-
162
- publish.call all_messages.dup
163
- end
164
- end
@@ -1,84 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose::Server::Publisher do
4
- include EM::TestHelper
5
-
6
- let(:publisher) { Firehose::Server::Publisher.new }
7
- let(:channel_key) { "/firehose/publisher/test/#{Time.now.to_i}" }
8
- let(:message) { "howdy friends!" }
9
-
10
- it "should have 100 MAX_MESSAGES" do
11
- Firehose::Server::Publisher::MAX_MESSAGES.should == 100
12
- end
13
-
14
- it "should have 1 day TTL" do
15
- Firehose::Server::Publisher::TTL.should == 86400
16
- end
17
-
18
- describe "#publish" do
19
- it "should publish message change" do
20
- em do
21
- hiredis = EM::Hiredis.connect.pubsub
22
- hiredis.subscribe "firehose:channel_updates"
23
- hiredis.on(:message) {|_, msg|
24
- msg.should == "#{channel_key}\n1\n#{message}"
25
- em.next_tick { em.stop }
26
- }
27
- Firehose::Server::Publisher.new.publish channel_key, message
28
- end
29
- end
30
-
31
- "\"'\r\t\n!@\#$%^&*()[]\v\f\a\b\e{}/=?+\\|".each_char do |char|
32
- it "should publish messages with the '#{char.inspect}' character" do
33
- msg = [char, message, char].join
34
- em 1 do
35
- Firehose::Server::Publisher.new.publish(channel_key, msg).callback { em.stop }
36
- end
37
- redis_exec('lpop', "firehose:#{channel_key}:list").should == msg
38
- end
39
- end
40
-
41
- it "should add message to list" do
42
- em do
43
- Firehose::Server::Publisher.new.publish(channel_key, message).callback { em.stop }
44
- end
45
- redis_exec('lpop', "firehose:#{channel_key}:list").should == message
46
- end
47
-
48
- it "should limit list to MAX_MESSAGES messages" do
49
- em do
50
- Firehose::Server::Publisher::MAX_MESSAGES.times do |n|
51
- publisher.publish(channel_key, message)
52
- end
53
- publisher.publish(channel_key, message).callback { em.stop }
54
- end
55
- redis_exec('llen', "firehose:#{channel_key}:list").should == Firehose::Server::Publisher::MAX_MESSAGES
56
- end
57
-
58
- it "should increment sequence" do
59
- sequence_key = "firehose:#{channel_key}:sequence"
60
-
61
- @done_counter = 0
62
- redis_exec('get', sequence_key).should be_nil
63
- em do
64
- publisher.publish(channel_key, message).callback { @done_counter += 1; em.next_tick { em.stop } if @done_counter > 1 }
65
- publisher.publish(channel_key, message).callback { @done_counter += 1; em.next_tick { em.stop } if @done_counter > 1 }
66
- end
67
- redis_exec('get', sequence_key).to_i.should == 2
68
- end
69
-
70
- it "should set expirery on sequence and list keys" do
71
- ttl = 78 # Why 78? Why not!
72
-
73
- em do
74
- publisher.publish(channel_key, message, :ttl => 78).callback do
75
- # Allow for 1 second of slippage/delay
76
- redis_exec('TTL', "firehose:#{channel_key}:sequence").should > (ttl- 1)
77
- redis_exec('TTL', "firehose:#{channel_key}:list").should > (ttl - 1)
78
- em.stop
79
- end
80
- end
81
- end
82
-
83
- end
84
- end
@@ -1,69 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Firehose::Server::Subscriber do
4
- include EM::TestHelper
5
-
6
- let(:channel_key) { '/bears/are/mean' }
7
- let(:subscriber) { Firehose::Server::Subscriber.new(EM::Hiredis.connect) }
8
- let(:dummy_subscriber){ Firehose::Server::Subscriber.new(double('redis', :pubsub => double('pubsub', :subscribe => EM::DefaultDeferrable.new, :on => nil))) }
9
- let(:message) { 'Raaaarrrrrr!!!!' }
10
- let(:publisher) { Firehose::Server::Publisher.new }
11
-
12
- describe "#subscribe" do
13
- it "should add the deferrable to the subscriptions hash" do
14
- deferrable = EM::DefaultDeferrable.new
15
- dummy_subscriber.subscribe(channel_key, deferrable)
16
- dummy_subscriber.send(:subscriptions)[channel_key].should == [deferrable]
17
- end
18
-
19
- it "should call succeed on the deferrable when a message is published" do
20
- deferrable = EM::DefaultDeferrable.new
21
- deferrable.callback do |msg, sequence|
22
- msg.should == message
23
- sequence.should == 1 # The publisher is fresh, so the sequence ID will be 1.
24
- em.next_tick { em.stop }
25
- end
26
-
27
- em do
28
- subscriber.subscribe(channel_key, deferrable)
29
- publisher.publish(channel_key, message)
30
- end
31
- end
32
-
33
- it "shouldn't call succeed on the deferrable when a 2nd message is published" do
34
- deferrable = EM::DefaultDeferrable.new
35
- deferrable.should_receive(:succeed).with(message, 1) # The publisher is fresh, so the sequence ID will be 1.
36
- deferrable.should_not_receive(:succeed).with('2nd message', 2)
37
- em do
38
- subscriber.subscribe(channel_key, deferrable)
39
- publisher.publish(channel_key, message).callback do
40
- publisher.publish(channel_key, '2nd message').callback do
41
- em.stop
42
- end
43
- end
44
- end
45
-
46
- end
47
- end
48
-
49
- describe "#unsubscribe" do
50
- it "should remove the deferrable from the subscriptions hash" do
51
- deferrable = EM::DefaultDeferrable.new
52
- dummy_subscriber.subscribe(channel_key, deferrable)
53
- dummy_subscriber.unsubscribe(channel_key, deferrable)
54
- dummy_subscriber.send(:subscriptions).has_key?(channel_key).should be_false
55
- end
56
-
57
- it "shouldn't call succeed on the deferrable when a message is published" do
58
- deferrable = EM::DefaultDeferrable.new
59
- deferrable.should_not_receive(:succeed).with(message, 1) # The publisher is fresh, so the sequence ID will be 1.
60
- em do
61
- subscriber.subscribe(channel_key, deferrable)
62
- subscriber.unsubscribe(channel_key, deferrable)
63
- publisher.publish(channel_key, message).callback do
64
- em.stop
65
- end
66
- end
67
- end
68
- end
69
- end
data/spec/spec_helper.rb DELETED
@@ -1,77 +0,0 @@
1
- ENV['RACK_ENV'] ||= 'test'
2
-
3
- require 'logger'
4
- require 'em-http'
5
- require 'faye/websocket'
6
- require 'hiredis'
7
- require 'firehose'
8
-
9
- # We use both EM::Http and Net::Http in this test lib. When EM:Http is fired up
10
- # we're usually hitting Rainbows! for integrations, and when Net::Http we want
11
- # to mock that up.
12
- require 'webmock/rspec'
13
- WebMock.allow_net_connect!
14
-
15
- module EM::TestHelper
16
- # Run test inside of reactor.
17
- def em(ttl=30, &block)
18
- if block
19
- # Run the block inside of a reactor
20
- EM.run do
21
- EM.add_timer(ttl) do
22
- EM.stop
23
- raise "Test timed-out"
24
- end
25
- block.call(EM)
26
- end
27
- else # or just grab em and go nuts.
28
- EM
29
- end
30
- end
31
- end
32
-
33
- module Hiredis::TestHelper
34
- def redis
35
- @conn ||= begin
36
- conn = Hiredis::Connection.new
37
- conn.connect("127.0.0.1", 6379)
38
- conn
39
- end
40
- end
41
-
42
- def reset_redis
43
- redis_exec 'flushdb'
44
- end
45
-
46
- def redis_exec(*tokens)
47
- redis.write tokens
48
- redis.read
49
- end
50
- end
51
-
52
- # Configure RSpec runner. See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
53
- RSpec.configure do |config|
54
- config.treat_symbols_as_metadata_keys_with_true_values = true
55
- config.run_all_when_everything_filtered = true
56
- config.filter_run :focus
57
- config.include Hiredis::TestHelper
58
- config.before(:each) do
59
- reset_redis
60
- end
61
- end
62
-
63
- # Allow async responses to get through rack/lint
64
- require 'rack/lint'
65
- class Rack::Lint
66
- def check_status_with_async(status)
67
- check_status_without_async(status) unless status == -1
68
- end
69
- alias_method :check_status_without_async, :check_status
70
- alias_method :check_status, :check_status_with_async
71
-
72
- def check_content_type_with_async(status, headers)
73
- check_content_type_without_async(status, headers) unless status == -1
74
- end
75
- alias_method :check_content_type_without_async, :check_content_type
76
- alias_method :check_content_type, :check_content_type_with_async
77
- end