funl 0.2 → 0.3
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/Rakefile +44 -10
- data/lib/funl/client.rb +18 -0
- data/lib/funl/message-sequencer.rb +74 -8
- data/lib/funl/message.rb +14 -0
- data/lib/funl/stream.rb +5 -0
- data/lib/funl/version.rb +1 -1
- data/test/test-message-sequencer.rb +15 -3
- data/test/test-subscribe.rb +175 -0
- metadata +14 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbb42a88d076acb7f545c98acbeeae62d94accae
|
4
|
+
data.tar.gz: f78b9b4f60684598d01b387fb56d57e4320d3c1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6735b03e0e9a8833dcfbad3ef8ad1ad139b06b12483d3d525b50fd24df4c0ec42f5f8c198eaf19e0f16d3a4bdba1958a72a1bae3279717bebcad68ecd2bfe085
|
7
|
+
data.tar.gz: 71d767408b0eaa9e1d1f818cf45271d23e8a44ab262bd0f70a413de35cbb17cf229b4d480abb3d6c9996cfae3b9a3cb76bfa08a09aa0c8673fc4aa843a37656f
|
data/Rakefile
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
require 'rake'
|
2
2
|
require 'rake/testtask'
|
3
3
|
|
4
|
+
PRJ = "funl"
|
5
|
+
|
4
6
|
def version
|
5
|
-
|
6
|
-
|
7
|
+
@version ||= begin
|
8
|
+
require 'funl/version'
|
9
|
+
warn "Funl::VERSION not a string" unless Funl::VERSION.kind_of? String
|
10
|
+
Funl::VERSION
|
11
|
+
end
|
7
12
|
end
|
8
13
|
|
9
|
-
|
14
|
+
def tag
|
15
|
+
@tag ||= "#{PRJ}-#{version}"
|
16
|
+
end
|
10
17
|
|
11
18
|
desc "Run tests"
|
12
19
|
Rake::TestTask.new :test do |t|
|
@@ -15,16 +22,43 @@ Rake::TestTask.new :test do |t|
|
|
15
22
|
t.test_files = FileList["test/**/*.rb"]
|
16
23
|
end
|
17
24
|
|
18
|
-
desc "
|
19
|
-
task :release do
|
20
|
-
|
25
|
+
desc "Commit, tag, and push repo; build and push gem"
|
26
|
+
task :release => "release:is_new_version" do
|
27
|
+
require 'tempfile'
|
28
|
+
|
29
|
+
sh "gem build #{PRJ}.gemspec"
|
21
30
|
|
22
|
-
|
31
|
+
file = Tempfile.new "template"
|
32
|
+
begin
|
33
|
+
file.puts "release #{version}"
|
34
|
+
file.close
|
35
|
+
sh "git commit --allow-empty -a -v -t #{file.path}"
|
36
|
+
ensure
|
37
|
+
file.close unless file.closed?
|
38
|
+
file.unlink
|
39
|
+
end
|
23
40
|
|
24
|
-
sh "git
|
25
|
-
sh "git tag #{prj}-#{version}"
|
41
|
+
sh "git tag #{tag}"
|
26
42
|
sh "git push"
|
27
43
|
sh "git push --tags"
|
28
44
|
|
29
|
-
sh "gem push #{
|
45
|
+
sh "gem push #{tag}.gem"
|
46
|
+
end
|
47
|
+
|
48
|
+
namespace :release do
|
49
|
+
desc "Diff to latest release"
|
50
|
+
task :diff do
|
51
|
+
latest = `git describe --abbrev=0 --tags --match '#{PRJ}-*'`.chomp
|
52
|
+
sh "git diff #{latest}"
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Log to latest release"
|
56
|
+
task :log do
|
57
|
+
latest = `git describe --abbrev=0 --tags --match '#{PRJ}-*'`.chomp
|
58
|
+
sh "git log #{latest}.."
|
59
|
+
end
|
60
|
+
|
61
|
+
task :is_new_version do
|
62
|
+
abort "#{tag} exists; update version!" unless `git tag -l #{tag}`.empty?
|
63
|
+
end
|
30
64
|
end
|
data/lib/funl/client.rb
CHANGED
@@ -44,6 +44,24 @@ module Funl
|
|
44
44
|
seq_read_greeting
|
45
45
|
end
|
46
46
|
|
47
|
+
def subscribe tags
|
48
|
+
seq << Message.control(SUBSCRIBE, tags)
|
49
|
+
## wait for ack which has tick, ask arc for older messages
|
50
|
+
end
|
51
|
+
|
52
|
+
def subscribe_all
|
53
|
+
seq << Message.control(SUBSCRIBE_ALL)
|
54
|
+
## wait for ack which has tick, ask arc for older messages
|
55
|
+
end
|
56
|
+
|
57
|
+
def unsubscribe tags
|
58
|
+
seq << Message.control(UNSUBSCRIBE, tags)
|
59
|
+
end
|
60
|
+
|
61
|
+
def unsubscribe_all
|
62
|
+
seq << Message.control(UNSUBSCRIBE_ALL)
|
63
|
+
end
|
64
|
+
|
47
65
|
def cseq_read_client_id
|
48
66
|
log.debug "getting client_id from cseq"
|
49
67
|
@client_id = cseq.read["client_id"]
|
@@ -18,6 +18,7 @@ module Funl
|
|
18
18
|
attr_reader :message_class
|
19
19
|
attr_reader :blob_type
|
20
20
|
attr_reader :greeting
|
21
|
+
attr_reader :subscribers
|
21
22
|
|
22
23
|
def initialize server, *conns, log: Logger.new($stderr),
|
23
24
|
stream_type: ObjectStream::MSGPACK_TYPE,
|
@@ -37,6 +38,10 @@ module Funl
|
|
37
38
|
conns.each do |conn|
|
38
39
|
try_conn conn
|
39
40
|
end
|
41
|
+
|
42
|
+
@subscribers_to_all = [] # [conn, ...]
|
43
|
+
@subscribers = Hash.new {|h, tag| h[tag] = []} # tag => [conn, ...]
|
44
|
+
@tags = Hash.new {|h, conn| h[conn] = []} # conn => [tag, ...]
|
40
45
|
end
|
41
46
|
|
42
47
|
def default_greeting
|
@@ -49,8 +54,8 @@ module Funl
|
|
49
54
|
stream = message_server_stream_for(conn)
|
50
55
|
current_greeting = greeting.merge({"tick" => tick})
|
51
56
|
if write_succeeds?(current_greeting, stream)
|
52
|
-
log.debug "connected #{stream.inspect}"
|
53
|
-
|
57
|
+
log.debug {"connected #{stream.inspect}"}
|
58
|
+
streams << stream
|
54
59
|
end
|
55
60
|
end
|
56
61
|
private :try_conn
|
@@ -78,7 +83,7 @@ module Funl
|
|
78
83
|
when server
|
79
84
|
begin
|
80
85
|
conn, addr = readable.accept_nonblock
|
81
|
-
log.debug "accepted #{conn.inspect} from #{addr.inspect}"
|
86
|
+
log.debug {"accepted #{conn.inspect} from #{addr.inspect}"}
|
82
87
|
try_conn conn
|
83
88
|
rescue IO::WaitReadable
|
84
89
|
next
|
@@ -93,15 +98,18 @@ module Funl
|
|
93
98
|
end
|
94
99
|
rescue IOError, SystemCallError => ex
|
95
100
|
log.debug {"closing #{readable}: #{ex}"}
|
96
|
-
|
97
|
-
readable.close unless readable.closed?
|
101
|
+
reject_stream readable
|
98
102
|
else
|
99
103
|
log.debug {
|
100
104
|
"read #{msgs.size} messages from #{readable.peer_name}"}
|
101
105
|
end
|
102
106
|
|
103
107
|
msgs.each do |msg|
|
104
|
-
|
108
|
+
if msg.control?
|
109
|
+
handle_control readable, *msg.control_op
|
110
|
+
else
|
111
|
+
handle_message msg
|
112
|
+
end
|
105
113
|
end
|
106
114
|
end
|
107
115
|
end
|
@@ -111,12 +119,56 @@ module Funl
|
|
111
119
|
raise
|
112
120
|
end
|
113
121
|
|
122
|
+
def handle_control stream, op_type, tags = nil
|
123
|
+
log.debug {"#{stream} #{op_type} #{tags}"}
|
124
|
+
|
125
|
+
case op_type
|
126
|
+
when SUBSCRIBE_ALL
|
127
|
+
@subscribers_to_all += [stream]
|
128
|
+
ack = Message.control(op_type)
|
129
|
+
ack.global_tick = tick
|
130
|
+
write_succeeds?(ack, stream)
|
131
|
+
|
132
|
+
when SUBSCRIBE
|
133
|
+
tags.each do |tag|
|
134
|
+
@subscribers[tag] += [stream]
|
135
|
+
end
|
136
|
+
@tags[stream] += tags
|
137
|
+
ack = Message.control(op_type, tags)
|
138
|
+
ack.global_tick = tick
|
139
|
+
write_succeeds?(ack, stream)
|
140
|
+
|
141
|
+
when UNSUBSCRIBE_ALL
|
142
|
+
@subscribers_to_all.delete stream
|
143
|
+
|
144
|
+
when UNSUBSCRIBE
|
145
|
+
tags.each do |tag|
|
146
|
+
@subscribers[tag].delete stream
|
147
|
+
end
|
148
|
+
@tags[stream] -= tags
|
149
|
+
|
150
|
+
else
|
151
|
+
log.error "bad operation: #{op_type.inspect}"
|
152
|
+
return
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
114
156
|
def handle_message msg
|
115
157
|
log.debug {"handling message #{msg.inspect}"}
|
158
|
+
|
116
159
|
@tick += 1
|
117
160
|
msg.global_tick = tick
|
118
161
|
msg.delta = nil
|
119
|
-
|
162
|
+
|
163
|
+
tags = msg.tags
|
164
|
+
dest_streams =
|
165
|
+
if !tags or (tags.empty? rescue true)
|
166
|
+
@subscribers_to_all.dup
|
167
|
+
else
|
168
|
+
tags.inject(@subscribers_to_all) {|a,tag| a + @subscribers[tag]}
|
169
|
+
end
|
170
|
+
|
171
|
+
dest_streams.each do |stream|
|
120
172
|
write_succeeds? msg, stream
|
121
173
|
end
|
122
174
|
end
|
@@ -127,9 +179,23 @@ module Funl
|
|
127
179
|
true
|
128
180
|
rescue IOError, SystemCallError => ex
|
129
181
|
log.debug {"closing #{stream}: #{ex}"}
|
130
|
-
|
182
|
+
reject_stream stream
|
131
183
|
false
|
132
184
|
end
|
133
185
|
private :write_succeeds?
|
134
186
|
end
|
187
|
+
|
188
|
+
def reject_stream stream
|
189
|
+
stream.close unless stream.closed?
|
190
|
+
if streams.include? stream
|
191
|
+
streams.delete stream
|
192
|
+
@subscribers_to_all.delete stream
|
193
|
+
tags = @tags.delete stream
|
194
|
+
if tags
|
195
|
+
tags.each do |tag|
|
196
|
+
@subscribers[tag].delete stream
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
135
201
|
end
|
data/lib/funl/message.rb
CHANGED
@@ -29,6 +29,20 @@ module Funl
|
|
29
29
|
client: nil, local: nil, global: nil, delta: nil, tags: nil, blob: nil)
|
30
30
|
new client, local, global, delta, tags, blob
|
31
31
|
end
|
32
|
+
|
33
|
+
def self.control op_type, *args
|
34
|
+
Message.new.tap {|m| m.client_id = [op_type, *args]}
|
35
|
+
end
|
36
|
+
|
37
|
+
# Is this a control packet rather than a data packet?
|
38
|
+
def control?
|
39
|
+
@client_id.kind_of? Array
|
40
|
+
end
|
41
|
+
|
42
|
+
# Array of [op_type, *args] for the control operation.
|
43
|
+
def control_op
|
44
|
+
@client_id
|
45
|
+
end
|
32
46
|
|
33
47
|
def inspect
|
34
48
|
d = delta ? "+#{delta}" : nil
|
data/lib/funl/stream.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'object-stream-wrapper'
|
2
2
|
|
3
3
|
module Funl
|
4
|
+
SUBSCRIBE = "subscribe".freeze
|
5
|
+
UNSUBSCRIBE = "unsubscribe".freeze
|
6
|
+
SUBSCRIBE_ALL = "subscribe_all".freeze
|
7
|
+
UNSUBSCRIBE_ALL = "unsubscribe_all".freeze
|
8
|
+
|
4
9
|
# Mixin depends on stream_type, log, client_id, message_class.
|
5
10
|
module Stream
|
6
11
|
def client_stream_for io, type: stream_type
|
data/lib/funl/version.rb
CHANGED
@@ -47,9 +47,16 @@ class TestMessageSequencer < Minitest::Test
|
|
47
47
|
streams = (0...@n_clients).map do
|
48
48
|
conn = UNIXSocket.new(@path)
|
49
49
|
stream = ObjectStreamWrapper.new(conn, type: stream_type)
|
50
|
-
stream.write_to_outbox{
|
50
|
+
stream.write_to_outbox({"client_id" => "test_later_conns"})
|
51
|
+
stream.write(Message.control(SUBSCRIBE_ALL))
|
51
52
|
global_tick = stream.read["tick"]
|
52
53
|
assert_equal 0, global_tick
|
54
|
+
|
55
|
+
stream.expect Message
|
56
|
+
ack = stream.read
|
57
|
+
assert ack.control?
|
58
|
+
assert_equal 0, ack.global_tick
|
59
|
+
|
53
60
|
stream
|
54
61
|
end
|
55
62
|
|
@@ -73,7 +80,6 @@ class TestMessageSequencer < Minitest::Test
|
|
73
80
|
src << message
|
74
81
|
|
75
82
|
replies = dst.map do |stream|
|
76
|
-
stream.expect Message
|
77
83
|
stream.read
|
78
84
|
end
|
79
85
|
|
@@ -103,10 +109,16 @@ class TestMessageSequencer < Minitest::Test
|
|
103
109
|
|
104
110
|
conn = UNIXSocket.new(path)
|
105
111
|
stream = ObjectStreamWrapper.new(conn, type: mseq.stream_type)
|
106
|
-
stream.write_to_outbox{
|
112
|
+
stream.write_to_outbox({"client_id" => "test_persist"}) # not needed
|
113
|
+
stream.write(Message.control(SUBSCRIBE_ALL))
|
107
114
|
tick = stream.read["tick"]
|
108
115
|
assert_equal n_write, tick
|
109
116
|
|
117
|
+
stream.expect Message
|
118
|
+
ack = stream.read
|
119
|
+
assert ack.control?
|
120
|
+
assert_equal n_write, ack.global_tick
|
121
|
+
|
110
122
|
stream.write Message.new
|
111
123
|
stream.read
|
112
124
|
n_write += 1
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require 'funl/message-sequencer'
|
2
|
+
require 'socket'
|
3
|
+
|
4
|
+
include Funl
|
5
|
+
|
6
|
+
require 'minitest/autorun'
|
7
|
+
|
8
|
+
class TestSubscribe < 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_single_tag
|
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
|
+
|
48
|
+
snd << Message[
|
49
|
+
client: 0, local: 0, global: 0, delta: 1,
|
50
|
+
tags: ["bar"], blob: ""]
|
51
|
+
snd << Message[
|
52
|
+
client: 0, local: 0, global: 0, delta: 2,
|
53
|
+
tags: ["foo"], blob: ""]
|
54
|
+
|
55
|
+
m = rcv.read
|
56
|
+
assert_equal 2, m.global_tick
|
57
|
+
assert_equal ["foo"], m.tags
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_multiple_tag
|
61
|
+
snd, rcv = @streams
|
62
|
+
rcv << Message.control(SUBSCRIBE, ["foo", "bar"])
|
63
|
+
ack = rcv.read
|
64
|
+
assert ack.control?
|
65
|
+
assert_equal 0, ack.global_tick
|
66
|
+
|
67
|
+
snd << Message[
|
68
|
+
client: 0, local: 0, global: 0, delta: 1,
|
69
|
+
tags: ["bar"], blob: ""]
|
70
|
+
snd << Message[
|
71
|
+
client: 0, local: 0, global: 0, delta: 2,
|
72
|
+
tags: ["foo"], blob: ""]
|
73
|
+
|
74
|
+
m = rcv.read
|
75
|
+
assert_equal 1, m.global_tick
|
76
|
+
assert_equal ["bar"], m.tags
|
77
|
+
m = rcv.read
|
78
|
+
assert_equal 2, m.global_tick
|
79
|
+
assert_equal ["foo"], m.tags
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_multiple_receiver
|
83
|
+
snd, rcv = @streams
|
84
|
+
@streams.each do |stream|
|
85
|
+
stream << Message.control(SUBSCRIBE, ["foo"])
|
86
|
+
ack = stream.read
|
87
|
+
assert ack.control?
|
88
|
+
assert_equal 0, ack.global_tick
|
89
|
+
end
|
90
|
+
|
91
|
+
snd << Message[
|
92
|
+
client: 0, local: 0, global: 0, delta: 1,
|
93
|
+
tags: ["foo"], blob: ""]
|
94
|
+
|
95
|
+
@streams.each do |stream|
|
96
|
+
m = stream.read
|
97
|
+
assert_equal 1, m.global_tick
|
98
|
+
assert_equal ["foo"], m.tags
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_unsubscribe
|
103
|
+
snd, rcv = @streams
|
104
|
+
rcv << Message.control(SUBSCRIBE, ["foo"])
|
105
|
+
ack = rcv.read
|
106
|
+
assert ack.control?
|
107
|
+
assert_equal 0, ack.global_tick
|
108
|
+
|
109
|
+
snd << Message[
|
110
|
+
client: 0, local: 0, global: 0, delta: 1,
|
111
|
+
tags: ["foo"], blob: ""]
|
112
|
+
|
113
|
+
m = rcv.read
|
114
|
+
assert_equal 1, m.global_tick
|
115
|
+
assert_equal ["foo"], m.tags
|
116
|
+
|
117
|
+
rcv << Message.control(UNSUBSCRIBE, ["foo"])
|
118
|
+
|
119
|
+
snd << Message[
|
120
|
+
client: 0, local: 0, global: 0, delta: 1,
|
121
|
+
tags: ["foo"], blob: ""]
|
122
|
+
|
123
|
+
sleep 0.2
|
124
|
+
|
125
|
+
rcv << Message.control(SUBSCRIBE, ["foo"])
|
126
|
+
ack = rcv.read
|
127
|
+
assert ack.control?
|
128
|
+
assert_equal 2, ack.global_tick
|
129
|
+
|
130
|
+
snd << Message[
|
131
|
+
client: 0, local: 0, global: 0, delta: 1,
|
132
|
+
tags: ["foo"], blob: ""]
|
133
|
+
|
134
|
+
m = rcv.read
|
135
|
+
assert_equal 3, m.global_tick
|
136
|
+
assert_equal ["foo"], m.tags
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_subscribe_all
|
140
|
+
snd, rcv = @streams
|
141
|
+
rcv << Message.control(SUBSCRIBE_ALL)
|
142
|
+
ack = rcv.read
|
143
|
+
assert ack.control?
|
144
|
+
assert_equal 0, ack.global_tick
|
145
|
+
|
146
|
+
snd << Message[
|
147
|
+
client: 0, local: 0, global: 0, delta: 1,
|
148
|
+
tags: ["foo"], blob: ""]
|
149
|
+
|
150
|
+
m = rcv.read
|
151
|
+
assert_equal 1, m.global_tick
|
152
|
+
assert_equal ["foo"], m.tags
|
153
|
+
|
154
|
+
rcv << Message.control(UNSUBSCRIBE_ALL)
|
155
|
+
|
156
|
+
snd << Message[
|
157
|
+
client: 0, local: 0, global: 0, delta: 1,
|
158
|
+
tags: ["foo"], blob: ""]
|
159
|
+
|
160
|
+
sleep 0.2
|
161
|
+
|
162
|
+
rcv << Message.control(SUBSCRIBE_ALL)
|
163
|
+
ack = rcv.read
|
164
|
+
assert ack.control?
|
165
|
+
assert_equal 2, ack.global_tick
|
166
|
+
|
167
|
+
snd << Message[
|
168
|
+
client: 0, local: 0, global: 0, delta: 1,
|
169
|
+
tags: ["foo"], blob: ""]
|
170
|
+
|
171
|
+
m = rcv.read
|
172
|
+
assert_equal 3, m.global_tick
|
173
|
+
assert_equal ["foo"], m.tags
|
174
|
+
end
|
175
|
+
end
|
metadata
CHANGED
@@ -1,27 +1,27 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: funl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.3'
|
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-09-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: object-stream
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
description: Sequences messages.
|
@@ -48,6 +48,7 @@ files:
|
|
48
48
|
- test/test-client-sequencer.rb
|
49
49
|
- test/test-message.rb
|
50
50
|
- test/test-stream.rb
|
51
|
+
- test/test-subscribe.rb
|
51
52
|
- test/test-client.rb
|
52
53
|
homepage: https://github.com/vjoel/funl
|
53
54
|
licenses:
|
@@ -55,28 +56,28 @@ licenses:
|
|
55
56
|
metadata: {}
|
56
57
|
post_install_message:
|
57
58
|
rdoc_options:
|
58
|
-
- --quiet
|
59
|
-
- --line-numbers
|
60
|
-
- --inline-source
|
61
|
-
- --title
|
59
|
+
- "--quiet"
|
60
|
+
- "--line-numbers"
|
61
|
+
- "--inline-source"
|
62
|
+
- "--title"
|
62
63
|
- funl
|
63
|
-
- --main
|
64
|
+
- "--main"
|
64
65
|
- README.md
|
65
66
|
require_paths:
|
66
67
|
- lib
|
67
68
|
required_ruby_version: !ruby/object:Gem::Requirement
|
68
69
|
requirements:
|
69
|
-
- -
|
70
|
+
- - ">="
|
70
71
|
- !ruby/object:Gem::Version
|
71
72
|
version: '0'
|
72
73
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
74
|
requirements:
|
74
|
-
- -
|
75
|
+
- - ">="
|
75
76
|
- !ruby/object:Gem::Version
|
76
77
|
version: '0'
|
77
78
|
requirements: []
|
78
79
|
rubyforge_project:
|
79
|
-
rubygems_version: 2.
|
80
|
+
rubygems_version: 2.1.4
|
80
81
|
signing_key:
|
81
82
|
specification_version: 4
|
82
83
|
summary: Sequences messages
|
@@ -85,5 +86,6 @@ test_files:
|
|
85
86
|
- test/test-client-sequencer.rb
|
86
87
|
- test/test-message.rb
|
87
88
|
- test/test-stream.rb
|
89
|
+
- test/test-subscribe.rb
|
88
90
|
- test/test-client.rb
|
89
91
|
has_rdoc:
|