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 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: