meerkat 0.4.5 → 0.6.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.
data/README.md CHANGED
@@ -6,36 +6,59 @@ Rack middleware for [Server-Sent Events (HTML5 SSE)](http://www.html5rocks.com/e
6
6
  Requires an [EventMachine](https://github.com/eventmachine/eventmachine#readme) backed server, like [Thin](http://code.macournoyer.com/thin/) or [Rainbows](http://rainbows.rubyforge.org/) (with the EventMachine backend only).
7
7
 
8
8
  Features:
9
- * Subscribe for single events
10
- * Subscribe for multiple events with patterns
11
- * Low memory and CPU usage
12
- * Works with all proxies (unlike WebSockets)
13
- * Allows publishing from server side as well as from the client side (with POST request)
9
+
10
+ * Realtime events
11
+ * Extremely efficent
12
+ * Broad browser support (both desktop and mobile browsers)
13
+ * Works with all proxies (unlike WebSockets)
14
+ * Subscribe to single events
15
+ * Subscribe to multiple events via patterns
16
+ * Publish messages from the server
17
+ * Publish messages from the client (via POST)
14
18
 
15
19
  Supported backends:
16
20
 
17
- * In memory, using [EventMachine Channels](http://eventmachine.rubyforge.org/EventMachine/Channel.html), good for single server usage.
18
- * Redis, using [em-hiredis](https://github.com/mloughran/em-hiredis#readme) and the [Pub/Sub API](http://redis.io/topics/pubsub).
19
- * Postgres, using the [Notify/Listen API](http://www.postgresql.org/docs/9.1/static/sql-notify.html).
20
- * When a message is published the topic and json payload is inserted into the 'meerkat_pubsub' table, and then a NOTIFY is issued.
21
- * Listening clients recivies the notification and reads the message from the table and writes it to the Event Stream of its clients.
22
- * On the next publish all messages older than 5 seconds are deleted.
23
- * No polling is ever done.
24
- * This works with PostgreSQL 8 and higher (tested with 8.3 and 9.1).
21
+ * In memory, using [EventMachine Channels](http://eventmachine.rubyforge.org/EventMachine/Channel.html), good for single server usage.
22
+ * RabbitMQ (AMQP), using the [AMQP gem](https://github.com/amqp/amqp-ruby) and the Pub/Sub pattern (Topic exchange + anonymous queues with pattern matching). AMQP is the most recommened alternative.
23
+ * Redis, using [em-hiredis](https://github.com/mloughran/em-hiredis#readme) and the [Pub/Sub API](http://redis.io/topics/pubsub).
24
+ * Postgres, using the [Notify/Listen API](http://www.postgresql.org/docs/9.1/static/sql-notify.html).
25
+ * When a message is published the topic and json payload is inserted into the 'meerkat_pubsub' table, and then a NOTIFY is issued.
26
+ * Listening clients recivies the notification and reads the message from the table and writes it to the Event Stream of its clients.
27
+ * On the next publish all messages older than 5 seconds are deleted.
28
+ * No polling is ever done.
29
+ * This works with PostgreSQL 8 and higher (tested with 8.3 and 9.1).
25
30
 
26
31
  Usage
27
32
  -----
28
33
 
34
+ Put meerkat and pg or em-hiredis in your Gemfile, depending on which backend you plan to use.
35
+ Gemfile:
36
+
37
+ ```ruby
38
+ gem 'meerkat'
39
+ gem 'amqp'
40
+ # or
41
+ gem 'pg'
42
+ # or
43
+ gem 'em-hiredis'
44
+ ```
45
+ Require meerkat and the backend you would like to use.
46
+
29
47
  config.ru:
30
48
 
31
49
  ```ruby
32
50
  require 'bundler/setup'
33
51
  require 'meerkat'
52
+ require 'meerkat/backend/amqp'
53
+ #require 'meerkat/backend/pg'
54
+ #require 'meerkat/backend/redis'
55
+ #require 'meerkat/backend/inmemory'
34
56
  require './app'
35
57
 
36
58
  #Meerkat.backend = Meerkat::Backend::InMemory.new
59
+ Meerkat.backend = Meerkat::Backend::AMQP.new 'amqp://guest:guest@localhost'
37
60
  #Meerkat.backend = Meerkat::Backend::Redis.new 'redis://localhost/0'
38
- Meerkat.backend = Meerkat::Backend::PG.new :dbname => 'postgres'
61
+ #Meerkat.backend = Meerkat::Backend::PG.new :dbname => 'postgres'
39
62
  map '/' do
40
63
  run App
41
64
  end
@@ -47,7 +70,7 @@ end
47
70
  On the client:
48
71
 
49
72
  ```javascript
50
- var source = new EventSource('/stream/mychannel');
73
+ var source = new EventSource('/stream/foo');
51
74
  var streamList = document.getElementById('stream');
52
75
  // Use #onmessage if you only listen to one topic
53
76
  source.onmessage = function(e) {
@@ -55,23 +78,24 @@ source.onmessage = function(e) {
55
78
  li.innerHTML = JSON.parse(e.data);
56
79
  streamList.appendChild(li);
57
80
  }
58
- var multiSource = new EventSource('/my/event/*');
81
+
82
+ var multiSource = new EventSource('/stream/foo.*');
59
83
  // You have to add custom event listerns when you
60
84
  // listen on multiple topics
61
- multiSource.addEventListener('/my/event/foo', function(e) {
85
+ multiSource.addEventListener('foo.bar', function(e) {
62
86
  // Do something
63
87
  }, false);
64
- multiSource.addEventListener('/my/event/bar', function(e) {
88
+ multiSource.addEventListener('foo.foo', function(e) {
65
89
  // Do something
66
90
  }, false);
67
91
  ```
68
92
 
69
- To push things from the client:
93
+ To push things from the server:
70
94
 
71
95
  ```ruby
72
- Meerkat.publish "/mychannel", {:any => hash}
73
- Meerkat.publish "/mychannel/2", 'any string'
74
- Meerkat.publish "/mychannel/3", any_object
96
+ Meerkat.publish "foo.bar", { :any => 'hash' } # the hash will automatically be json encoded
97
+ Meerkat.publish "foo.bar", 'any string'
98
+ Meerkat.publish "foo.foo", myobj.to_json, true # the third parameter indicates that the message already is json encoded
75
99
  ```
76
100
 
77
101
  The published objects will be JSON serialized before sent to the backend. You'll have to deserialize it in the client.
@@ -79,10 +103,13 @@ The published objects will be JSON serialized before sent to the backend. You'll
79
103
  From the client:
80
104
 
81
105
  ```javascript
82
- $.post('/stream/mychannel/2', { json: JSON.stringify(my_object) })
106
+ $.post('/stream', { topic: 'foo.bar', data: JSON.stringify(my_object) })
107
+ $.post('/stream/foo.bar', { data: JSON.stringify(my_object) })
83
108
  ```
84
109
 
85
- A simple POST request, with a parameter called 'json' containing a JSON string.
110
+ A simple POST request, with a parameter called 'data' (or 'json' or 'msg') containing a JSON string.
111
+
112
+ The topic can be specified other as a post parameter or in the path.
86
113
 
87
114
  Read more about Server-Sent Events and the EventSource API on [HTML5Rocks](http://www.html5rocks.com/en/tutorials/eventsource/basics/).
88
115
 
@@ -1,8 +1,5 @@
1
1
  require_relative 'meerkat/version'
2
2
  require_relative 'meerkat/rackadapter'
3
- require_relative 'meerkat/backend/inmemory'
4
- require_relative 'meerkat/backend/redis'
5
- require_relative 'meerkat/backend/pg'
6
3
  require 'multi_json'
7
4
 
8
5
  module Meerkat
@@ -12,13 +9,16 @@ module Meerkat
12
9
  @backend = backend
13
10
  end
14
11
 
15
- def publish(route, message, is_json = false)
12
+ def publish(topic, message, is_json = false)
13
+ raise "Topic is required" if topic.nil?
14
+ raise "Message is required" if message.nil?
16
15
  json = is_json ? message : MultiJson.encode(message)
17
- @backend.publish(route, json)
16
+ @backend.publish(topic, json)
18
17
  end
19
18
 
20
- def subscribe(route, &callback)
21
- @backend.subscribe(route, &callback)
19
+ def subscribe(topic, &callback)
20
+ raise "Topic is required" if topic.nil?
21
+ @backend.subscribe(topic, &callback)
22
22
  end
23
23
 
24
24
  def unsubscribe(sid)
@@ -0,0 +1,32 @@
1
+ require 'amqp'
2
+
3
+ module Meerkat
4
+ module Backend
5
+ class AMQP
6
+ def initialize(amqp_url = 'amqp://guest:guest@localhost')
7
+ @conn = ::AMQP.connect amqp_url
8
+ end
9
+
10
+ def publish(topic, json)
11
+ ::AMQP::Channel.new @conn do |ch|
12
+ ch.topic("meerkat").publish(json, :routing_key => topic)
13
+ end
14
+ end
15
+
16
+ def subscribe(topic, &callback)
17
+ ::AMQP::Channel.new @conn do |ch|
18
+ ch.queue('', :auto_delete => true) do |queue|
19
+ queue.bind(ch.topic("meerkat"), :routing_key => topic)
20
+ queue.subscribe do |headers, payload|
21
+ callback.call headers.routing_key, payload
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ def unsubscribe(channel)
28
+ channel.close
29
+ end
30
+ end
31
+ end
32
+ end
@@ -47,7 +47,11 @@ module Meerkat
47
47
  def create_table
48
48
  @pg.transaction do |conn|
49
49
  table = conn.exec "SELECT true FROM pg_tables WHERE tablename = $1", [TABLENAME]
50
- conn.exec "CREATE TABLE #{TABLENAME} (topic varchar(1024), json text, timestamp timestamp default now())" if table.count == 0
50
+ return unless table.count == 0
51
+ conn.exec "CREATE TABLE #{TABLENAME} (
52
+ topic varchar(1024),
53
+ json text,
54
+ timestamp timestamp default now())"
51
55
  end
52
56
  end
53
57
 
@@ -26,15 +26,14 @@ module Meerkat
26
26
 
27
27
  def post(env)
28
28
  req = Rack::Request.new env
29
+ topic = req.path_info[1..-1]
30
+ topic = req.params['topic'] if topic.empty?
29
31
  data = req.params['data'] || req.params['msg'] || req.params['json']
30
- if data
31
- Meerkat.publish(req.path_info, data, true)
32
- [204, {}, []]
33
- else
34
- [400,
35
- {'Content-Type' => 'text/plain'},
36
- ['Required POST parameter "data", "msg" or "json" is missing']]
37
- end
32
+
33
+ Meerkat.publish(topic, data, true)
34
+ [204, {}, []]
35
+ rescue Exception => e
36
+ [400, {'Content-Type' => 'text/plain'}, [e.message]]
38
37
  end
39
38
 
40
39
  def listen(env)
@@ -49,7 +48,7 @@ module Meerkat
49
48
  EM.add_periodic_timer(@keep_alive) { body << ":\n" }
50
49
  EM.add_timer(@timeout) { body.succeed } if @timeout
51
50
 
52
- path_info = Rack::Utils.unescape env["PATH_INFO"]
51
+ path_info = Rack::Utils.unescape(env["PATH_INFO"])[1..-1]
53
52
  sub = Meerkat.subscribe(path_info) do |topic, json|
54
53
  body << "event: #{topic}\n" unless path_info == topic
55
54
  body << "data: #{json}\n\n"
@@ -1,3 +1,3 @@
1
1
  module Meerkat
2
- VERSION = "0.4.5"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -18,14 +18,15 @@ Gem::Specification.new do |s|
18
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_development_dependency "minitest"
21
+ s.add_development_dependency "rspec"
22
22
  s.add_development_dependency "rack-test"
23
23
  s.add_development_dependency "thin_async"
24
24
  s.add_development_dependency "thin-async-test"
25
- s.add_development_dependency "em-minitest-spec"
25
+
26
+ s.add_development_dependency "pg"
27
+ s.add_development_dependency "amqp"
28
+ s.add_development_dependency "em-hiredis"
26
29
 
27
30
  s.add_runtime_dependency "multi_json"
28
31
  s.add_runtime_dependency "eventmachine"
29
- s.add_runtime_dependency "em-hiredis"
30
- s.add_runtime_dependency "pg"
31
32
  end
@@ -0,0 +1,34 @@
1
+ require './lib/meerkat/backend/amqp'
2
+ require 'eventmachine'
3
+
4
+ describe Meerkat::Backend::AMQP do
5
+ around do |spec|
6
+ EM.run { spec.call }
7
+ end
8
+
9
+ it 'can publish and subscribe' do
10
+ subject.subscribe 'route' do |topic, msg|
11
+ topic.should == 'route'
12
+ msg.should == 'foo'
13
+ EM.stop
14
+ end
15
+ EM.add_timer(0.1) { subject.publish 'route', 'foo' }
16
+ end
17
+
18
+ it 'can subscribe to wildcards' do
19
+ subject.subscribe 'foo.*' do |topic, msg|
20
+ topic.should == 'foo.bar'
21
+ msg.should == 'barfoo'
22
+ EM.stop
23
+ end
24
+ EM.add_timer(0.1) { subject.publish 'foo.bar', 'barfoo' }
25
+ end
26
+
27
+ it 'can unsubscribe' do
28
+ sid = subject.subscribe('route') { |topic, msg| }
29
+ EM.add_timer(0.1) do
30
+ subject.unsubscribe sid
31
+ EM.stop
32
+ end
33
+ end
34
+ end
@@ -1,34 +1,36 @@
1
- require 'minitest/autorun'
2
- require 'em/minitest/spec'
3
1
  require './lib/meerkat/backend/inmemory'
2
+ require 'eventmachine'
4
3
 
5
- describe 'The in memory backend' do
6
- include EM::MiniTest::Spec
7
-
8
- before do
9
- @im = Meerkat::Backend::InMemory.new
4
+ describe Meerkat::Backend::InMemory do
5
+ around do |spec|
6
+ EM.run { spec.call }
10
7
  end
11
8
 
12
9
  it 'can publish and subscribe' do
13
- @im.subscribe 'route' do |topic, msg|
14
- assert_equal 'route', topic
15
- assert_equal 'foo', msg
16
- done!
10
+ subject.subscribe 'route' do |topic, msg|
11
+ topic.should == 'route'
12
+ msg.should == 'foo'
13
+ EM.stop
14
+ end
15
+ EM.next_tick do
16
+ subject.publish 'route', 'foo'
17
17
  end
18
- @im.publish 'route', 'foo'
19
- wait!
20
18
  end
19
+
21
20
  it 'can subscribe to wildcards' do
22
- @im.subscribe '/foo/*' do |topic, msg|
23
- assert_equal '/foo/bar', topic
24
- assert_equal 'barfoo', msg
25
- done!
21
+ subject.subscribe '/foo/*' do |topic, msg|
22
+ topic.should == '/foo/bar'
23
+ msg.should == 'barfoo'
24
+ EM.stop
25
+ end
26
+ EM.next_tick do
27
+ subject.publish '/foo/bar', 'barfoo'
26
28
  end
27
- @im.publish '/foo/bar', 'barfoo'
28
- wait!
29
29
  end
30
+
30
31
  it 'can unbsubscribe' do
31
- sid = @im.subscribe 'route' do |topic, msg| end
32
- @im.unsubscribe sid
32
+ sid = subject.subscribe 'route' do |topic, msg| end
33
+ subject.unsubscribe sid
34
+ EM.stop
33
35
  end
34
36
  end
@@ -1,57 +1,63 @@
1
- require 'minitest/autorun'
2
- require 'em/minitest/spec'
1
+ require 'eventmachine'
3
2
  require './lib/meerkat/backend/pg'
4
3
 
5
4
  describe 'Postgres backend' do
6
- include EM::MiniTest::Spec
5
+ around do |spec|
6
+ EM.run { spec.call }
7
+ end
8
+
9
+ def done!
10
+ EM.stop
11
+ end
12
+
13
+ subject { Meerkat::Backend::PG.new :dbname => 'postgres' }
7
14
 
8
- before do
9
- @b = Meerkat::Backend::PG.new :dbname => 'postgres'
15
+ it 'create required table only once' do
16
+ subject.send :create_table
17
+ subject.send :create_table
18
+ done!
10
19
  end
11
20
 
12
21
  it 'can subscribe to partial wildcard' do
13
- @b.subscribe '/foo/*' do |topic, msg|
14
- assert_equal '/foo/bar', topic
15
- assert_equal 'messsage', msg
22
+ subject.subscribe '/foo/*' do |topic, msg|
23
+ topic.should == '/foo/bar'
24
+ msg.should == 'messsage'
16
25
  done!
17
26
  end
18
- @b.publish '/foo/bar', 'messsage'
19
- wait!
27
+ subject.publish '/foo/bar', 'messsage'
20
28
  end
21
29
 
22
30
  it 'can subscribe to wildcard' do
23
- @b.subscribe '*' do |topic, msg|
24
- assert_equal 'messsage', msg
31
+ subject.subscribe '*' do |topic, msg|
32
+ msg.should == 'messsage'
25
33
  done!
26
34
  end
27
- @b.publish '/', 'messsage'
28
- wait!
35
+ subject.publish '/', 'messsage'
29
36
  end
30
37
 
31
38
  it 'can publish and subscribe' do
32
- @b.subscribe '/' do |topic, msg|
33
- assert_equal 'messsage', msg
39
+ subject.subscribe '/' do |topic, msg|
40
+ msg.should == 'messsage'
34
41
  done!
35
42
  end
36
- @b.publish '/', 'messsage'
37
- wait!
43
+ subject.publish '/', 'messsage'
38
44
  end
39
45
 
40
46
  it 'can publish and subscribe multiple messages' do
41
47
  i = 5
42
48
  j = 0
43
- @b.subscribe '/' do |topic, msg|
49
+ subject.subscribe '/' do |topic, msg|
44
50
  j += 1
45
- assert_equal 'messsage', msg
51
+ msg.should == 'messsage'
46
52
  done! if j == i
47
53
  end
48
- i.times { @b.publish '/', 'messsage' }
49
- wait!
54
+ i.times { subject.publish '/', 'messsage' }
50
55
  end
51
56
 
52
57
  it 'can unsubscribe' do
53
- sid = @b.subscribe 'route' do |topic, msg| end
54
- @b.unsubscribe sid
58
+ sid = subject.subscribe 'route' do |topic, msg| end
59
+ subject.unsubscribe sid
60
+ done!
55
61
  end
56
62
  end
57
63
 
@@ -1,41 +1,36 @@
1
- require 'minitest/autorun'
2
- require 'em/minitest/spec'
3
1
  require './lib/meerkat/backend/redis'
2
+ require 'eventmachine'
4
3
 
5
- describe 'Redis backend' do
6
- include EM::MiniTest::Spec
4
+ describe Meerkat::Backend::Redis do
5
+ around do |spec|
6
+ EM.run { spec.call }
7
+ end
7
8
 
8
9
  it 'can publish and subscribe to wildcards' do
9
- b = Meerkat::Backend::Redis.new
10
- b.subscribe '/foo/*' do |topic, msg|
11
- assert_equal '/foo/bar', topic
12
- assert_equal 'messsage', msg
13
- done!
10
+ subject.subscribe '/foo/*' do |topic, msg|
11
+ topic.should == '/foo/bar'
12
+ msg.should == 'messsage'
13
+ EM.stop
14
14
  end
15
15
  EM.next_tick {
16
- b.publish '/foo/bar', 'messsage'
16
+ subject.publish '/foo/bar', 'messsage'
17
17
  }
18
- wait!
19
18
  end
20
19
 
21
20
  it 'can publish and subscribe' do
22
- b = Meerkat::Backend::Redis.new
23
- b.subscribe '/' do |topic, msg|
24
- assert_equal 'messsage', msg
25
- done!
21
+ subject.subscribe '/' do |topic, msg|
22
+ msg.should == 'messsage'
23
+ EM.stop
26
24
  end
27
25
  EM.next_tick {
28
- b.publish '/', 'messsage'
26
+ subject.publish '/', 'messsage'
29
27
  }
30
- wait!
31
28
  end
32
29
 
33
30
  it 'can unsubscribe' do
34
- b = Meerkat::Backend::Redis.new
35
- sid = b.subscribe 'route' do |msg|
36
- @recivied = msg
37
- end
38
- b.unsubscribe sid
31
+ sid = subject.subscribe('route')
32
+ subject.unsubscribe sid
33
+ EM.stop
39
34
  end
40
35
  end
41
36
 
@@ -1,10 +1,9 @@
1
- require 'bundler/setup'
2
- require 'minitest/autorun'
3
1
  require 'rack/test'
4
2
  require 'thin/async/test'
5
3
  require './lib/meerkat'
4
+ require './lib/meerkat/backend/inmemory'
6
5
 
7
- describe 'Meerkat' do
6
+ describe Meerkat do
8
7
  include Rack::Test::Methods
9
8
 
10
9
  before do
@@ -21,50 +20,57 @@ describe 'Meerkat' do
21
20
  }.to_app
22
21
  end
23
22
 
24
- it 'should return status 200 and content-type text/event-stream' do
23
+ it 'returns status 200 and content-type text/event-stream' do
25
24
  get '/'
26
- assert_equal 200, last_response.status
27
- assert_equal 'text/event-stream', last_response.headers['Content-Type']
25
+ last_response.status.should == 200
26
+ last_response.headers['Content-Type'].should == 'text/event-stream'
28
27
  end
29
28
 
30
- it 'first return a retry value' do
29
+ it 'start with a retry value' do
31
30
  get '/'
32
- assert_equal "retry: 3000\n", last_response.body.lines.first
31
+ last_response.body.lines.first.should == "retry: 3000\n"
33
32
  end
34
33
 
35
- it 'should periodically emit a comment to keep alive the connection' do
34
+ it 'periodically emits a comment to keep alive the connection' do
36
35
  get '/'
37
- assert_equal ":", last_response.body.split("\n")[1]
36
+ last_response.body.split("\n")[1].should == ":"
38
37
  end
39
-
40
- it 'should publish POST data and treat it like JSON' do
41
- mock = MiniTest::Mock.new
42
- mock.expect(:publish, nil, ['/foo', '"bar"'])
43
- Meerkat.backend = mock
38
+
39
+ it 'publishes POST data and treat it like JSON' do
40
+ backend = stub
41
+ backend.should_receive(:publish).with('foo', '"bar"')
42
+ Meerkat.backend = backend
44
43
  post '/foo', :json => '"bar"'
44
+ last_response.status.should == 204
45
+ end
46
+
47
+ it 'uses path info as topic' do
48
+ post '/foo.bar', msg: 'foobar'
49
+ last_response.status.should == 204
50
+ end
45
51
 
46
- assert_equal 204, last_response.status
47
- assert mock.verify
52
+ it 'can use topic post params as topic' do
53
+ post '/', topic: 'foo.bar', msg: 'foobar'
54
+ last_response.status.should == 204
48
55
  end
49
56
 
50
- it 'should return error 400 when there is no "json" POST parameters' do
57
+ it 'returns error 400 when there is no "json" POST parameters' do
51
58
  post '/', :foo => 'bar'
52
- assert_equal 400, last_response.status
59
+ last_response.status.should == 400
53
60
  end
54
61
 
55
62
  it 'should return error 400 when there is no POST data' do
56
63
  post '/foo'
57
- assert_equal 400, last_response.status
64
+ last_response.status.should == 400
58
65
  end
59
66
 
60
- it 'should return 404 for anything but GET and POST requests' do
61
- delete '/foo'
62
- assert_equal 404, last_response.status
63
- options '/foo'
64
- assert_equal 404, last_response.status
65
- head '/foo'
66
- assert_equal 404, last_response.status
67
- put '/foo'
68
- assert_equal 404, last_response.status
67
+ context 'return 404 for anything but GET and POST requests' do
68
+ after do
69
+ last_response.status.should == 404
70
+ end
71
+ it { delete '/foo' }
72
+ it { options '/foo' }
73
+ it { head '/foo' }
74
+ it { put '/foo' }
69
75
  end
70
76
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: meerkat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.6.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-11 00:00:00.000000000 Z
12
+ date: 2012-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: minitest
16
- requirement: &70099588426600 !ruby/object:Gem::Requirement
15
+ name: rspec
16
+ requirement: &70139880888460 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70099588426600
24
+ version_requirements: *70139880888460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rack-test
27
- requirement: &70099588426100 !ruby/object:Gem::Requirement
27
+ requirement: &70139880887760 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70099588426100
35
+ version_requirements: *70139880887760
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: thin_async
38
- requirement: &70099588425680 !ruby/object:Gem::Requirement
38
+ requirement: &70139880887100 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70099588425680
46
+ version_requirements: *70139880887100
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: thin-async-test
49
- requirement: &70099588425240 !ruby/object:Gem::Requirement
49
+ requirement: &70139880886400 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70099588425240
57
+ version_requirements: *70139880886400
58
58
  - !ruby/object:Gem::Dependency
59
- name: em-minitest-spec
60
- requirement: &70099588424820 !ruby/object:Gem::Requirement
59
+ name: pg
60
+ requirement: &70139880885580 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,32 +65,32 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70099588424820
68
+ version_requirements: *70139880885580
69
69
  - !ruby/object:Gem::Dependency
70
- name: multi_json
71
- requirement: &70099588424380 !ruby/object:Gem::Requirement
70
+ name: amqp
71
+ requirement: &70139880884760 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
75
75
  - !ruby/object:Gem::Version
76
76
  version: '0'
77
- type: :runtime
77
+ type: :development
78
78
  prerelease: false
79
- version_requirements: *70099588424380
79
+ version_requirements: *70139880884760
80
80
  - !ruby/object:Gem::Dependency
81
- name: eventmachine
82
- requirement: &70099588423940 !ruby/object:Gem::Requirement
81
+ name: em-hiredis
82
+ requirement: &70139880884020 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
86
86
  - !ruby/object:Gem::Version
87
87
  version: '0'
88
- type: :runtime
88
+ type: :development
89
89
  prerelease: false
90
- version_requirements: *70099588423940
90
+ version_requirements: *70139880884020
91
91
  - !ruby/object:Gem::Dependency
92
- name: em-hiredis
93
- requirement: &70099588423520 !ruby/object:Gem::Requirement
92
+ name: multi_json
93
+ requirement: &70139880883280 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *70099588423520
101
+ version_requirements: *70139880883280
102
102
  - !ruby/object:Gem::Dependency
103
- name: pg
104
- requirement: &70099588423100 !ruby/object:Gem::Requirement
103
+ name: eventmachine
104
+ requirement: &70139880882700 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :runtime
111
111
  prerelease: false
112
- version_requirements: *70099588423100
112
+ version_requirements: *70139880882700
113
113
  description: Requires an evented Ruby dispatcher, like Thin
114
114
  email:
115
115
  - carl.hoerberg@gmail.com
@@ -119,7 +119,6 @@ extra_rdoc_files: []
119
119
  files:
120
120
  - .gitignore
121
121
  - Gemfile
122
- - Gemfile.lock
123
122
  - README.md
124
123
  - Rakefile
125
124
  - examples/Gemfile
@@ -127,12 +126,14 @@ files:
127
126
  - examples/config.ru
128
127
  - examples/views/index.haml
129
128
  - lib/meerkat.rb
129
+ - lib/meerkat/backend/amqp.rb
130
130
  - lib/meerkat/backend/inmemory.rb
131
131
  - lib/meerkat/backend/pg.rb
132
132
  - lib/meerkat/backend/redis.rb
133
133
  - lib/meerkat/rackadapter.rb
134
134
  - lib/meerkat/version.rb
135
135
  - meerkat.gemspec
136
+ - spec/backend/amqp_spec.rb
136
137
  - spec/backend/inmemory_spec.rb
137
138
  - spec/backend/pg_spec.rb
138
139
  - spec/backend/redis_spec.rb
@@ -151,7 +152,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
151
152
  version: '0'
152
153
  segments:
153
154
  - 0
154
- hash: -2331619758487538772
155
+ hash: 3167433476364397664
155
156
  required_rubygems_version: !ruby/object:Gem::Requirement
156
157
  none: false
157
158
  requirements:
@@ -160,14 +161,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
161
  version: '0'
161
162
  segments:
162
163
  - 0
163
- hash: -2331619758487538772
164
+ hash: 3167433476364397664
164
165
  requirements: []
165
166
  rubyforge_project: meerkat
166
- rubygems_version: 1.8.10
167
+ rubygems_version: 1.8.17
167
168
  signing_key:
168
169
  specification_version: 3
169
170
  summary: Rack middleware for HTML5 Server-Sent Events, with swappable backends
170
171
  test_files:
172
+ - spec/backend/amqp_spec.rb
171
173
  - spec/backend/inmemory_spec.rb
172
174
  - spec/backend/pg_spec.rb
173
175
  - spec/backend/redis_spec.rb