funl 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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:
|