backrub 1.0.0 → 2.0.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 +4 -4
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -1
- data/backrub.gemspec +1 -1
- data/lib/backrub.rb +13 -55
- data/lib/backrub/store/base.rb +17 -0
- data/lib/backrub/store/redis.rb +46 -0
- data/lib/backrub/version.rb +3 -0
- data/test/backrub/store/redis_test.rb +50 -0
- data/test/backrub_test.rb +21 -34
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d42c9e5402d9150f81a77e3d2359c563db3de03
|
4
|
+
data.tar.gz: dee8d063247b1a74db02a20807a814f24ced01c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 77cc4d20ba3e9b1ff5c1dfadef7c25e601d56aa95badd7390573f8708f5b868f4222cc2d81ee78e24365430a8df07817246ca40a58ee554abf813d75ed798db3
|
7
|
+
data.tar.gz: 2b55a4e20b6e55dad15a7898ac0d5e0075201a4e5dc673793c02de112547c812166df3e4acac6ec97153f782ac1b516d04c1ac4bbc6a500e32373f146281cd5c
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
data/backrub.gemspec
CHANGED
data/lib/backrub.rb
CHANGED
@@ -1,68 +1,26 @@
|
|
1
|
-
require '
|
1
|
+
require 'backrub/store/base'
|
2
|
+
require 'backrub/store/redis'
|
3
|
+
require 'backrub/version'
|
2
4
|
|
3
5
|
module Backrub
|
4
|
-
VERSION = "1.0.0"
|
5
|
-
|
6
|
-
DEFAULT_BACKLOG_SIZE = 100
|
7
|
-
|
8
6
|
extend self
|
9
7
|
|
10
|
-
attr_writer :
|
11
|
-
|
12
|
-
|
13
|
-
@redis_config ||= {}
|
14
|
-
end
|
15
|
-
|
16
|
-
def redis
|
17
|
-
@redis ||= new_redis
|
8
|
+
attr_writer :store
|
9
|
+
def store
|
10
|
+
@store ||= Backrub::Store::Redis.new
|
18
11
|
end
|
19
12
|
|
20
|
-
def subscribe(
|
21
|
-
|
22
|
-
|
23
|
-
if channels.count == 1 && channels.first.is_a?(Hash)
|
24
|
-
hash = channels.first
|
25
|
-
|
26
|
-
hash.each do |channel, offset|
|
27
|
-
if offset > 0
|
28
|
-
backlog = redis.lrange(channel, 0, offset - 1)
|
29
|
-
|
30
|
-
backlog.reverse_each do |message|
|
31
|
-
yield channel.to_s, message
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
channels = hash.keys
|
37
|
-
end
|
38
|
-
|
39
|
-
begin
|
40
|
-
# Open a new connection because the connection blocks, causing other threads to be unable to use it
|
41
|
-
local_redis = new_redis
|
42
|
-
local_redis.subscribe(*channels) do |on|
|
43
|
-
on.message do |channel, message|
|
44
|
-
yield channel, message
|
45
|
-
end
|
46
|
-
end
|
47
|
-
ensure
|
48
|
-
local_redis.quit
|
13
|
+
def subscribe(channels_with_backlog, &block)
|
14
|
+
channels_with_backlog.each do |channel, count|
|
15
|
+
store.backlog(channel.to_s, count.to_i, &block) unless count.zero?
|
49
16
|
end
|
50
|
-
end
|
51
17
|
|
52
|
-
|
53
|
-
redis.multi do
|
54
|
-
redis.publish(channel, message)
|
55
|
-
redis.lpush(channel, message)
|
56
|
-
redis.ltrim(channel, 0, backlog_size - 1)
|
57
|
-
end
|
58
|
-
end
|
18
|
+
channels = channels_with_backlog.keys.map(&:to_s)
|
59
19
|
|
60
|
-
|
61
|
-
@backlog_size || DEFAULT_BACKLOG_SIZE
|
20
|
+
store.subscribe(*channels, &block)
|
62
21
|
end
|
63
22
|
|
64
|
-
|
65
|
-
|
66
|
-
Redis.new(redis_config)
|
23
|
+
def publish(channel, message)
|
24
|
+
store.publish(channel, message)
|
67
25
|
end
|
68
26
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Backrub
|
2
|
+
module Store
|
3
|
+
class Base
|
4
|
+
def backlog(channel, count)
|
5
|
+
raise NotImplementedError
|
6
|
+
end
|
7
|
+
|
8
|
+
def publish(channel, message)
|
9
|
+
raise NotImplementedError
|
10
|
+
end
|
11
|
+
|
12
|
+
def subscribe(*channel)
|
13
|
+
raise NotImplementedError
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'redis'
|
2
|
+
|
3
|
+
module Backrub
|
4
|
+
module Store
|
5
|
+
class Redis < Base
|
6
|
+
attr_reader :config, :backlog_size
|
7
|
+
|
8
|
+
def initialize(config={}, backlog_size=100)
|
9
|
+
@config = config
|
10
|
+
@backlog_size = backlog_size
|
11
|
+
end
|
12
|
+
|
13
|
+
def redis
|
14
|
+
@redis ||= ::Redis.new(config)
|
15
|
+
end
|
16
|
+
|
17
|
+
def backlog(channel, count)
|
18
|
+
backlog = redis.lrange(channel, 0, count - 1)
|
19
|
+
|
20
|
+
backlog.reverse_each do |message|
|
21
|
+
yield channel, message
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def publish(channel, message)
|
26
|
+
redis.multi do
|
27
|
+
redis.publish(channel, message)
|
28
|
+
redis.lpush(channel, message)
|
29
|
+
redis.ltrim(channel, 0, backlog_size - 1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def subscribe(*channels)
|
34
|
+
# Open a new connection because the connection blocks, causing other threads to be unable to use it
|
35
|
+
local_redis = ::Redis.new(config)
|
36
|
+
local_redis.subscribe(*channels) do |on|
|
37
|
+
on.message do |channel, message|
|
38
|
+
yield channel, message
|
39
|
+
end
|
40
|
+
end
|
41
|
+
ensure
|
42
|
+
local_redis.quit
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BackrubRedisTest < MiniTest::Unit::TestCase
|
4
|
+
def setup
|
5
|
+
@backlog = 20
|
6
|
+
@config = {}
|
7
|
+
@store = Backrub::Store::Redis.new(@config, @backlog)
|
8
|
+
@redis = @store.redis
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_backlog
|
12
|
+
backlog = 20.times.map {|n| "a" * (n+1)}
|
13
|
+
channel = "test"
|
14
|
+
count = 5
|
15
|
+
@redis.expects(:lrange).with(channel, 0, count - 1).returns(backlog[0...count])
|
16
|
+
|
17
|
+
received_backlog = []
|
18
|
+
|
19
|
+
@store.backlog(channel, count) do |channel, message|
|
20
|
+
received_backlog << message
|
21
|
+
end
|
22
|
+
|
23
|
+
assert_equal backlog[0...count].reverse, received_backlog
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_publishing
|
27
|
+
channel = "test"
|
28
|
+
message = "data"
|
29
|
+
@redis.expects(:publish).with(channel, message)
|
30
|
+
@redis.expects(:lpush).with(channel, message)
|
31
|
+
@redis.expects(:ltrim).with(channel, 0, @backlog - 1)
|
32
|
+
|
33
|
+
@store.publish(channel, message)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_subscribing
|
37
|
+
test_messages = [["test", "data"], ["test2", "data2"]]
|
38
|
+
|
39
|
+
mock_redis = mock()
|
40
|
+
mock_message_handler = mock()
|
41
|
+
mock_message_handler.expects(:message).multiple_yields(*test_messages)
|
42
|
+
mock_redis.expects(:subscribe).with("test", "test2").yields(mock_message_handler)
|
43
|
+
mock_redis.expects(:quit)
|
44
|
+
::Redis.expects(:new).returns(mock_redis)
|
45
|
+
|
46
|
+
@store.subscribe("test", "test2") do |channel, message|
|
47
|
+
assert_equal test_messages.shift, [channel, message]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/test/backrub_test.rb
CHANGED
@@ -1,52 +1,39 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class BackrubTest < MiniTest::Unit::TestCase
|
4
|
-
|
5
|
-
channel = "test"
|
6
|
-
message = "data"
|
7
|
-
Backrub.redis.expects(:publish).with(channel, message)
|
8
|
-
Backrub.redis.expects(:lpush).with(channel, message)
|
9
|
-
Backrub.redis.expects(:ltrim).with(channel, 0, Backrub::DEFAULT_BACKLOG_SIZE - 1)
|
10
|
-
|
11
|
-
Backrub.publish(channel, message)
|
12
|
-
end
|
13
|
-
|
14
|
-
def test_subscribing
|
15
|
-
fake_redis = mock()
|
16
|
-
subscribe_object = mock()
|
17
|
-
subscribe_object.expects(:message).yields(["test", "data"])
|
18
|
-
fake_redis.expects(:subscribe).with("test").yields(subscribe_object)
|
19
|
-
fake_redis.expects(:quit)
|
4
|
+
class MockStore < Backrub::Store::Base
|
20
5
|
|
21
|
-
|
6
|
+
end
|
22
7
|
|
23
|
-
|
24
|
-
|
25
|
-
assert_equal "data", message
|
26
|
-
end
|
8
|
+
def setup
|
9
|
+
Backrub.store = MockStore.new
|
27
10
|
end
|
28
11
|
|
29
|
-
def
|
12
|
+
def test_subscribing
|
30
13
|
channels = {
|
31
14
|
first_channel: 0,
|
32
15
|
second_channel: 2
|
33
16
|
}
|
34
|
-
|
35
|
-
Backrub.redis.expects(:lrange).with(:second_channel, 0, 1).returns(second_channel_data.dup)
|
36
|
-
second_channel_data.unshift("third_bit")
|
37
|
-
|
38
|
-
fake_redis = mock()
|
39
|
-
subscribe_object = mock()
|
40
|
-
subscribe_object.expects(:message).yields(["second_channel", "third_bit"])
|
17
|
+
Backrub.store.expects(:backlog).with("second_channel", 2).multiple_yields(["second_channel", "first_bit"], ["second_channel", "second_bit"])
|
41
18
|
|
42
|
-
|
43
|
-
|
19
|
+
expected_data = [
|
20
|
+
["second_channel", "first_bit"],
|
21
|
+
["second_channel", "second_bit"],
|
22
|
+
["first_channel", "third_bit"],
|
23
|
+
]
|
44
24
|
|
45
|
-
Backrub.expects(:
|
25
|
+
Backrub.store.expects(:subscribe).with("first_channel", "second_channel").yields(["first_channel", "third_bit"])
|
46
26
|
|
27
|
+
data = []
|
47
28
|
Backrub.subscribe(channels) do |channel, message|
|
48
|
-
|
49
|
-
assert_equal second_channel_data.pop, message
|
29
|
+
data << [channel, message]
|
50
30
|
end
|
31
|
+
|
32
|
+
assert_equal expected_data, data
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_publishing
|
36
|
+
Backrub.store.expects(:publish).with("test", "data")
|
37
|
+
Backrub.publish("test", "data")
|
51
38
|
end
|
52
39
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: backrub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bouke van der Bijl
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-02-
|
11
|
+
date: 2014-02-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -95,6 +95,10 @@ files:
|
|
95
95
|
- Rakefile
|
96
96
|
- backrub.gemspec
|
97
97
|
- lib/backrub.rb
|
98
|
+
- lib/backrub/store/base.rb
|
99
|
+
- lib/backrub/store/redis.rb
|
100
|
+
- lib/backrub/version.rb
|
101
|
+
- test/backrub/store/redis_test.rb
|
98
102
|
- test/backrub_test.rb
|
99
103
|
- test/test_helper.rb
|
100
104
|
homepage: ''
|
@@ -122,6 +126,7 @@ signing_key:
|
|
122
126
|
specification_version: 4
|
123
127
|
summary: Redis-based pubsub system with a backlog
|
124
128
|
test_files:
|
129
|
+
- test/backrub/store/redis_test.rb
|
125
130
|
- test/backrub_test.rb
|
126
131
|
- test/test_helper.rb
|
127
132
|
has_rdoc:
|