pubsubstub 0.0.15 → 0.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,73 +0,0 @@
1
- module Pubsubstub
2
- class RedisPubSub
3
- EVENT_SCORE_THRESHOLD = 1000
4
- EXPIRE_THRESHOLD = 24 * 60 * 60
5
-
6
- def initialize(channel_name)
7
- @channel_name = channel_name
8
- end
9
-
10
- def subscribe(callback)
11
- self.class.sub.subscribe(key('pubsub'), callback)
12
- end
13
-
14
- def unsubscribe(callback)
15
- self.class.sub.unsubscribe_proc(key('pubsub'), callback)
16
- end
17
-
18
- def publish(event)
19
- self.class.publish(@channel_name, event)
20
- end
21
-
22
- def scrollback(since_event_id)
23
- redis_scrollback(since_event_id) do |json|
24
- yield Pubsubstub::Event.from_json(json)
25
- end
26
- end
27
-
28
- private
29
-
30
- def redis_scrollback(since_event_id, &block)
31
- args = [key('scrollback'), "(#{since_event_id.to_i}", '+inf']
32
- if EventMachine.reactor_running?
33
- self.class.nonblocking_redis.zrangebyscore(*args) do |events|
34
- events.each(&block)
35
- end
36
- else
37
- self.class.blocking_redis.zrangebyscore(*args).each(&block)
38
- end
39
- end
40
-
41
- def key(purpose)
42
- [@channel_name, purpose].join(".")
43
- end
44
-
45
- class << self
46
- def publish(channel_name, event)
47
- scrollback = "#{channel_name}.scrollback"
48
- blocking_redis.pipelined do
49
- blocking_redis.publish("#{channel_name}.pubsub", event.to_json)
50
- blocking_redis.zadd(scrollback, event.id, event.to_json)
51
- blocking_redis.zremrangebyrank(scrollback, 0, -EVENT_SCORE_THRESHOLD)
52
- blocking_redis.expire(scrollback, EXPIRE_THRESHOLD)
53
- end
54
- end
55
-
56
- def sub
57
- @sub ||= nonblocking_redis.pubsub
58
- end
59
-
60
- def blocking_redis
61
- @blocking_redis ||= Redis.new(url: redis_url)
62
- end
63
-
64
- def nonblocking_redis
65
- @nonblocking_redis ||= EM::Hiredis.connect(redis_url)
66
- end
67
-
68
- def redis_url
69
- Pubsubstub.redis_url || ENV['REDIS_URL'] || "redis://localhost:6379/0"
70
- end
71
- end
72
- end
73
- end
@@ -1,121 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Pubsubstub::RedisPubSub do
4
-
5
- context "class singleton methods" do
6
- subject { Pubsubstub::RedisPubSub }
7
-
8
- describe "#publish" do
9
- let(:redis) { double('redis') }
10
- let(:event) { double('Event', to_json: "event_data", id: 1234) }
11
- before {
12
- allow(redis).to receive(:pipelined).and_yield
13
- }
14
-
15
- it "publishes the event to a redis channel and adds it to the scrollback" do
16
- allow(subject).to receive(:blocking_redis) { redis }
17
- expect(redis).to receive(:publish).with("test.pubsub", event.to_json)
18
- expect(redis).to receive(:zadd).with("test.scrollback", event.id, event.to_json)
19
- expect(redis).to receive(:zremrangebyrank).with("test.scrollback", 0, -1000)
20
- expect(redis).to receive(:expire).with("test.scrollback", Pubsubstub::RedisPubSub::EXPIRE_THRESHOLD)
21
- subject.publish("test", event)
22
- end
23
-
24
- it "truncates the scrollback" do
25
- count = Pubsubstub::RedisPubSub::EVENT_SCORE_THRESHOLD
26
- (1...count).each do |id|
27
- event = double(to_json: "event_data #{id}", id: id)
28
- subject.publish('test', event)
29
- end
30
- expect(subject.blocking_redis.zcard("test.scrollback")).to eq(count - 1)
31
-
32
- event = double(to_json: "event_data N", id: count)
33
- subject.publish('test', event)
34
- expect(subject.blocking_redis.zcard("test.scrollback")).to eq(count - 1)
35
- end
36
- end
37
-
38
- describe "#redis_url" do
39
- it "uses the fallback url fallback chain" do
40
- Pubsubstub.redis_url = "redis://localhost:6379/1"
41
- expect(Pubsubstub::RedisPubSub.redis_url).to eq("redis://localhost:6379/1")
42
-
43
- Pubsubstub.redis_url = nil
44
- ENV['REDIS_URL'] = "redis://localhost:6379/2"
45
- expect(Pubsubstub::RedisPubSub.redis_url).to eq("redis://localhost:6379/2")
46
-
47
- Pubsubstub::RedisPubSub.instance_variable_set(:@blocking_redis, nil)
48
- ENV['REDIS_URL'] = nil
49
- expect(Pubsubstub::RedisPubSub.redis_url).to eq("redis://localhost:6379/0")
50
- end
51
- end
52
- end
53
-
54
- context "pubsub" do
55
- subject { Pubsubstub::RedisPubSub.new("test") }
56
- let(:pubsub) { double('redis pubsub') }
57
- let(:callback) { ->{} }
58
-
59
- describe "#subscribe" do
60
- before {
61
- allow(subject.class).to receive(:sub) { pubsub }
62
- }
63
-
64
- it "creates a redis sub with the callback" do
65
- expect(pubsub).to receive(:subscribe).with("test.pubsub", callback)
66
- subject.subscribe(callback)
67
- end
68
- end
69
-
70
- describe "#unsubscribe" do
71
- before {
72
- allow(subject.class).to receive(:sub) { pubsub }
73
- }
74
-
75
- it "creates a redis sub with the callback" do
76
- expect(pubsub).to receive(:unsubscribe_proc).with("test.pubsub", callback)
77
- subject.unsubscribe(callback)
78
- end
79
- end
80
-
81
- describe "#publish" do
82
- let(:event) { Pubsubstub::Event.new("toto") }
83
- it "delegates to RedisPubSub.publish" do
84
- expect(Pubsubstub::RedisPubSub).to receive(:publish).with("test", event)
85
- subject.publish(event)
86
- end
87
- end
88
- end
89
-
90
- describe "#scrollback" do
91
- subject { Pubsubstub::RedisPubSub.new("test") }
92
-
93
- let(:event1) { Pubsubstub::Event.new("toto", id: 1235) }
94
- let(:event2) { Pubsubstub::Event.new("toto", id: 1236) }
95
-
96
- describe "without EventMachine" do
97
- it "yields the events in the scrollback" do
98
- redis = double('redis')
99
- expect(redis).to receive(:zrangebyscore)
100
- .with('test.scrollback', '(1234', '+inf')
101
- .and_return([event1.to_json, event2.to_json])
102
-
103
- expect(Pubsubstub::RedisPubSub).to receive(:blocking_redis).and_return(redis)
104
- expect { |block| subject.scrollback(1234, &block) }.to yield_successive_args(event1, event2)
105
- end
106
- end
107
-
108
- describe "with EventMachine" do
109
- it "yields the events in the scrollback" do
110
- allow(EventMachine).to receive(:reactor_running?).and_return(true)
111
- redis = double('redis')
112
- expect(redis).to receive(:zrangebyscore)
113
- .with('test.scrollback', '(1234', '+inf')
114
- .and_yield([event1.to_json, event2.to_json])
115
-
116
- expect(Pubsubstub::RedisPubSub).to receive(:nonblocking_redis).and_return(redis)
117
- expect { |block| subject.scrollback(1234, &block) }.to yield_successive_args(event1, event2)
118
- end
119
- end
120
- end
121
- end