pubsubstub 0.0.15 → 0.1.0.beta1

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.
@@ -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