funl 0.4 → 0.5
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/lib/funl/client-sequencer.rb +4 -3
- data/lib/funl/message-sequencer.rb +17 -6
- data/lib/funl/message.rb +7 -1
- data/lib/funl/version.rb +1 -1
- data/test/test-reflect.rb +72 -0
- data/test/test-subscribe.rb +26 -0
- metadata +19 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f896217f8f6185a6894823174f381b98be0af3d
|
4
|
+
data.tar.gz: 497d37bb1d3180d02e12eeebcbd47d643ed836cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dded12ff33c1585f69b04305b1942850734bd49017c01d277785907278f2fff0ea09cc664792df414187c86a75fbf96b84784ecd2abd157b469ecfd3687a707d
|
7
|
+
data.tar.gz: aa9fb5d8155ee50e9366327e2457e88bdfd0da12b92de899b8597855bbc9626f82bd69035858fb3999d0c84c143685d70e215519f245d1d97a0da6a7a537864e
|
@@ -52,13 +52,14 @@ module Funl
|
|
52
52
|
|
53
53
|
def handle_conn conn
|
54
54
|
stream = ObjectStream.new(conn, type: stream_type)
|
55
|
-
|
55
|
+
client_id = next_id
|
56
56
|
@next_id += 1
|
57
|
+
msg = {"client_id" => client_id}
|
57
58
|
stream << msg
|
58
59
|
rescue IOError, SystemCallError => ex
|
59
|
-
log.error "write error for client #{
|
60
|
+
log.error "write error for client #{client_id}: #{ex}"
|
60
61
|
else
|
61
|
-
log.info "recognized client #{
|
62
|
+
log.info "recognized client #{client_id}"
|
62
63
|
ensure
|
63
64
|
stream.close if stream and not stream.closed?
|
64
65
|
end
|
@@ -108,7 +108,7 @@ module Funl
|
|
108
108
|
if msg.control?
|
109
109
|
handle_control readable, *msg.control_op
|
110
110
|
else
|
111
|
-
handle_message msg
|
111
|
+
handle_message msg, readable
|
112
112
|
end
|
113
113
|
end
|
114
114
|
end
|
@@ -120,17 +120,17 @@ module Funl
|
|
120
120
|
end
|
121
121
|
|
122
122
|
def handle_control stream, op_type, tags = nil
|
123
|
-
log.debug {"#{stream} #{op_type} #{tags}"}
|
123
|
+
log.debug {"#{stream.peer_name} #{op_type} #{tags}"}
|
124
124
|
|
125
125
|
case op_type
|
126
126
|
when SUBSCRIBE_ALL
|
127
|
-
@subscribers_to_all
|
127
|
+
@subscribers_to_all |= [stream]
|
128
128
|
|
129
129
|
when SUBSCRIBE
|
130
130
|
tags.each do |tag|
|
131
|
-
@subscribers[tag]
|
131
|
+
@subscribers[tag] |= [stream]
|
132
132
|
end
|
133
|
-
@tags[stream]
|
133
|
+
@tags[stream] |= tags
|
134
134
|
|
135
135
|
when UNSUBSCRIBE_ALL
|
136
136
|
@subscribers_to_all.delete stream
|
@@ -151,7 +151,7 @@ module Funl
|
|
151
151
|
write_succeeds?(ack, stream)
|
152
152
|
end
|
153
153
|
|
154
|
-
def handle_message msg
|
154
|
+
def handle_message msg, origin_conn
|
155
155
|
log.debug {"handling message #{msg.inspect}"}
|
156
156
|
|
157
157
|
@tick += 1
|
@@ -159,13 +159,24 @@ module Funl
|
|
159
159
|
msg.delta = nil
|
160
160
|
|
161
161
|
tags = msg.tags
|
162
|
+
reflect = false
|
162
163
|
dest_streams =
|
163
164
|
if !tags or (tags.empty? rescue true)
|
164
165
|
@subscribers_to_all.dup
|
165
166
|
else
|
167
|
+
reflect = tags.delete(true)
|
166
168
|
tags.inject(@subscribers_to_all) {|a,tag| a + @subscribers[tag]}
|
167
169
|
end
|
168
170
|
|
171
|
+
if reflect
|
172
|
+
log.debug {"reflecting message"}
|
173
|
+
reflect_msg = Message[
|
174
|
+
client: msg.client_id,
|
175
|
+
local: msg.local_tick,
|
176
|
+
global: msg.global_tick]
|
177
|
+
write_succeeds? reflect_msg, origin_conn
|
178
|
+
end
|
179
|
+
|
169
180
|
dest_streams.each do |stream|
|
170
181
|
write_succeeds? msg, stream
|
171
182
|
end
|
data/lib/funl/message.rb
CHANGED
@@ -15,7 +15,13 @@ module Funl
|
|
15
15
|
# messages are pipelined, delta > 1.
|
16
16
|
attr_accessor :delta
|
17
17
|
|
18
|
-
# Application-defined metadata. May be used for filtering etc.
|
18
|
+
# Application-defined metadata. May be used for filtering etc. Must be an
|
19
|
+
# array or nil. If mseq detects +true+ among the tags, then mseq _reflects_
|
20
|
+
# the message: it sends the message back to the sender (minus tags and blob,
|
21
|
+
# and with updated global_tick). This is so that a client can send mseq a
|
22
|
+
# message with tags it does not subscribe to and know when it has arrived.
|
23
|
+
# The +true+ is removed from the tag list before mseq sends it to
|
24
|
+
# subscribers.
|
19
25
|
attr_accessor :tags
|
20
26
|
|
21
27
|
# Application-defined payload data. See blobber.rb.
|
data/lib/funl/version.rb
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'funl/message-sequencer'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
include Funl
|
5
|
+
|
6
|
+
require 'minitest/autorun'
|
7
|
+
|
8
|
+
class TestReflect < Minitest::Test
|
9
|
+
attr_reader :log, :mseq
|
10
|
+
|
11
|
+
def setup
|
12
|
+
@log = Logger.new($stderr)
|
13
|
+
log.level = Logger::WARN
|
14
|
+
|
15
|
+
client_socks = []
|
16
|
+
server_socks = []
|
17
|
+
2.times do
|
18
|
+
cl, sv = UNIXSocket.pair
|
19
|
+
client_socks << cl
|
20
|
+
server_socks << sv
|
21
|
+
end
|
22
|
+
|
23
|
+
dummy, _ = UNIXSocket.pair
|
24
|
+
|
25
|
+
@mseq = MessageSequencer.new dummy, *server_socks, log: log
|
26
|
+
mseq.start
|
27
|
+
|
28
|
+
@streams = client_socks.each_with_index.map do |s,i|
|
29
|
+
stream = ObjectStreamWrapper.new(s, type: mseq.stream_type)
|
30
|
+
stream.write_to_outbox({"client_id" => "client #{i}"})
|
31
|
+
global_tick = stream.read["tick"]
|
32
|
+
stream.expect Message
|
33
|
+
stream
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def teardown
|
38
|
+
mseq.stop rescue nil
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_reflect
|
42
|
+
snd, rcv = @streams
|
43
|
+
rcv << Message.control(SUBSCRIBE, ["foo"])
|
44
|
+
ack = rcv.read
|
45
|
+
assert ack.control?
|
46
|
+
assert_equal 0, ack.global_tick
|
47
|
+
reflect = true
|
48
|
+
|
49
|
+
snd << Message[
|
50
|
+
client: 0, local: 1, global: 0, delta: 1,
|
51
|
+
tags: [reflect, "bar"], blob: ""]
|
52
|
+
snd << Message[
|
53
|
+
client: 0, local: 2, global: 0, delta: 2,
|
54
|
+
tags: [reflect, "foo"], blob: ""]
|
55
|
+
|
56
|
+
m = rcv.read
|
57
|
+
assert_equal 2, m.global_tick
|
58
|
+
assert_equal ["foo"], m.tags
|
59
|
+
|
60
|
+
m = snd.read
|
61
|
+
assert_equal 1, m.global_tick
|
62
|
+
assert_equal 1, m.local_tick
|
63
|
+
assert_equal nil, m.tags
|
64
|
+
assert_equal nil, m.blob
|
65
|
+
|
66
|
+
m = snd.read
|
67
|
+
assert_equal 2, m.global_tick
|
68
|
+
assert_equal 2, m.local_tick
|
69
|
+
assert_equal nil, m.tags
|
70
|
+
assert_equal nil, m.blob
|
71
|
+
end
|
72
|
+
end
|
data/test/test-subscribe.rb
CHANGED
@@ -184,4 +184,30 @@ class TestSubscribe < Minitest::Test
|
|
184
184
|
assert_equal 3, m.global_tick
|
185
185
|
assert_equal ["foo"], m.tags
|
186
186
|
end
|
187
|
+
|
188
|
+
def test_redundant_subscribe
|
189
|
+
snd, rcv = @streams
|
190
|
+
2.times do
|
191
|
+
rcv << Message.control(SUBSCRIBE, ["foo"])
|
192
|
+
ack = rcv.read
|
193
|
+
assert ack.control?
|
194
|
+
end
|
195
|
+
|
196
|
+
snd << Message[
|
197
|
+
client: 0, local: 0, global: 0, delta: 1,
|
198
|
+
tags: ["foo"], blob: "1"]
|
199
|
+
snd << Message[
|
200
|
+
client: 0, local: 0, global: 0, delta: 2,
|
201
|
+
tags: ["foo"], blob: "2"]
|
202
|
+
|
203
|
+
m = rcv.read
|
204
|
+
assert_equal 1, m.global_tick
|
205
|
+
assert_equal ["foo"], m.tags
|
206
|
+
assert_equal "1", m.blob
|
207
|
+
|
208
|
+
m = rcv.read
|
209
|
+
assert_equal 2, m.global_tick
|
210
|
+
assert_equal ["foo"], m.tags
|
211
|
+
assert_equal "2", m.blob
|
212
|
+
end
|
187
213
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: funl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.5'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel VanderWerf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: object-stream
|
@@ -35,22 +35,23 @@ files:
|
|
35
35
|
- README.md
|
36
36
|
- COPYING
|
37
37
|
- Rakefile
|
38
|
-
- lib/funl/
|
39
|
-
- lib/funl/
|
40
|
-
- lib/funl/subscription-tracker.rb
|
41
|
-
- lib/funl/history-client.rb
|
38
|
+
- lib/funl/client-sequencer.rb
|
39
|
+
- lib/funl/message-sequencer.rb
|
42
40
|
- lib/funl/history-worker.rb
|
41
|
+
- lib/funl/stream.rb
|
43
42
|
- lib/funl/client.rb
|
44
|
-
- lib/funl/
|
45
|
-
- lib/funl/
|
43
|
+
- lib/funl/history-client.rb
|
44
|
+
- lib/funl/subscription-tracker.rb
|
46
45
|
- lib/funl/message.rb
|
46
|
+
- lib/funl/blobber.rb
|
47
47
|
- lib/funl/version.rb
|
48
|
-
- test/test-message-sequencer.rb
|
49
|
-
- test/test-client-sequencer.rb
|
50
|
-
- test/test-message.rb
|
51
48
|
- test/test-stream.rb
|
52
|
-
- test/test-
|
49
|
+
- test/test-message.rb
|
53
50
|
- test/test-client.rb
|
51
|
+
- test/test-client-sequencer.rb
|
52
|
+
- test/test-subscribe.rb
|
53
|
+
- test/test-reflect.rb
|
54
|
+
- test/test-message-sequencer.rb
|
54
55
|
homepage: https://github.com/vjoel/funl
|
55
56
|
licenses:
|
56
57
|
- BSD
|
@@ -78,15 +79,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
78
79
|
version: '0'
|
79
80
|
requirements: []
|
80
81
|
rubyforge_project:
|
81
|
-
rubygems_version: 2.1.
|
82
|
+
rubygems_version: 2.1.10
|
82
83
|
signing_key:
|
83
84
|
specification_version: 4
|
84
85
|
summary: Sequences messages
|
85
86
|
test_files:
|
86
|
-
- test/test-message-sequencer.rb
|
87
|
-
- test/test-client-sequencer.rb
|
88
|
-
- test/test-message.rb
|
89
87
|
- test/test-stream.rb
|
90
|
-
- test/test-
|
88
|
+
- test/test-message.rb
|
91
89
|
- test/test-client.rb
|
90
|
+
- test/test-client-sequencer.rb
|
91
|
+
- test/test-subscribe.rb
|
92
|
+
- test/test-reflect.rb
|
93
|
+
- test/test-message-sequencer.rb
|
92
94
|
has_rdoc:
|