funl 0.4 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ac4ecb6a3ca14c04c14cc5af85e34ba3d421123
4
- data.tar.gz: a9a6a618dfb48a4baed545c71767b5ac544cba98
3
+ metadata.gz: 7f896217f8f6185a6894823174f381b98be0af3d
4
+ data.tar.gz: 497d37bb1d3180d02e12eeebcbd47d643ed836cd
5
5
  SHA512:
6
- metadata.gz: 1794536193b70a6a965357d64c9d53b58f7c168d1e3c4a17a8b588d1b2e5550fae9b3bccbe5fb2393be397a1482e088b0784dd6aff5dfc4b5fd2ba00989864f0
7
- data.tar.gz: abadb9d061fba91923f6781b2132526468943ba848ddb01477008ae77cbc56a2af12cbfe709de9700ac3630177a2211e8e8bc7ad4577361a508dc96ad091cf3e
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
- msg = {"client_id" => next_id}
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 #{next_id}: #{ex}"
60
+ log.error "write error for client #{client_id}: #{ex}"
60
61
  else
61
- log.info "recognized client #{next_id}"
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 += [stream]
127
+ @subscribers_to_all |= [stream]
128
128
 
129
129
  when SUBSCRIBE
130
130
  tags.each do |tag|
131
- @subscribers[tag] += [stream]
131
+ @subscribers[tag] |= [stream]
132
132
  end
133
- @tags[stream] += tags
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
@@ -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.
@@ -1,3 +1,3 @@
1
1
  module Funl
2
- VERSION = "0.4"
2
+ VERSION = "0.5"
3
3
  end
@@ -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
@@ -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'
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-10-01 00:00:00.000000000 Z
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/stream.rb
39
- - lib/funl/blobber.rb
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/message-sequencer.rb
45
- - lib/funl/client-sequencer.rb
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-subscribe.rb
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.4
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-subscribe.rb
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: