ionian 0.7.0 → 0.8.0
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/doc/Ionian.html +1 -1
- data/doc/Ionian/Extension.html +1 -1
- data/doc/Ionian/Extension/IO.html +78 -142
- data/doc/Ionian/Extension/Socket.html +39 -24
- data/doc/Ionian/ManagedSocket.html +244 -173
- data/doc/Ionian/Server.html +1 -1
- data/doc/Ionian/Socket.html +225 -91
- data/doc/_index.html +1 -1
- data/doc/file.README.html +1 -1
- data/doc/file.license.html +1 -1
- data/doc/index.html +1 -1
- data/doc/method_list.html +87 -87
- data/doc/top-level-namespace.html +1 -1
- data/lib/ionian/extension/io.rb +8 -16
- data/lib/ionian/extension/socket.rb +1 -0
- data/lib/ionian/managed_socket.rb +84 -39
- data/lib/ionian/socket.rb +10 -2
- metadata +14 -14
@@ -103,7 +103,7 @@
|
|
103
103
|
</div>
|
104
104
|
|
105
105
|
<div id="footer">
|
106
|
-
Generated on Wed
|
106
|
+
Generated on Wed Feb 11 16:57:30 2015 by
|
107
107
|
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
108
108
|
0.8.7.6 (ruby-2.1.5).
|
109
109
|
</div>
|
data/lib/ionian/extension/io.rb
CHANGED
@@ -39,7 +39,7 @@ module Ionian
|
|
39
39
|
::IO.select([self], nil, nil, timeout) ? true : false
|
40
40
|
end
|
41
41
|
|
42
|
-
# @return [Regexp]
|
42
|
+
# @return [Regexp] the regular expression used for {#read_match}.
|
43
43
|
def expression
|
44
44
|
@ionian_expression
|
45
45
|
end
|
@@ -50,6 +50,7 @@ module Ionian
|
|
50
50
|
# sequence. It is possible to use named captures in a
|
51
51
|
# regex, which allows for convienient accessors like
|
52
52
|
# match[:parameter].
|
53
|
+
# @param exp [Regexp, String] Match expression.
|
53
54
|
def expression= exp
|
54
55
|
@ionian_expression = exp
|
55
56
|
@ionian_expression = Regexp.new "(.*?)#{expression}" if exp.is_a? String
|
@@ -84,8 +85,8 @@ module Ionian
|
|
84
85
|
# @yieldparam match [MatchData] If there are multiple matches, the block
|
85
86
|
# is called multiple times.
|
86
87
|
#
|
87
|
-
# @return [Array<MatchData
|
88
|
-
#
|
88
|
+
# @return [Array<MatchData>] matches.
|
89
|
+
# Empty array if no data was received within the timeout period.
|
89
90
|
#
|
90
91
|
#
|
91
92
|
# @option kwargs [Numeric] :timeout (nil) Timeout in seconds IO::select
|
@@ -114,7 +115,7 @@ module Ionian
|
|
114
115
|
exp = Regexp.new "(.*?)#{exp}" if exp.is_a? String
|
115
116
|
|
116
117
|
unless skip_select
|
117
|
-
return
|
118
|
+
return [] unless self.has_data? timeout: timeout
|
118
119
|
end
|
119
120
|
|
120
121
|
@matches = []
|
@@ -165,8 +166,7 @@ module Ionian
|
|
165
166
|
Thread.current.thread_variable_set :match_thread_running, true
|
166
167
|
begin
|
167
168
|
while not closed? do
|
168
|
-
|
169
|
-
matches.each { |match| notify_match_handlers match } if matches
|
169
|
+
read_match(**kwargs).each { |match| notify_match_handlers match }
|
170
170
|
end
|
171
171
|
rescue Exception => e
|
172
172
|
notify_error_handlers e
|
@@ -176,14 +176,6 @@ module Ionian
|
|
176
176
|
end
|
177
177
|
end
|
178
178
|
|
179
|
-
def run_match_is_running?
|
180
|
-
return true if \
|
181
|
-
@run_match_thread and
|
182
|
-
@run_match_thread.thread_variable_get(:match_thread_running)
|
183
|
-
|
184
|
-
false
|
185
|
-
end
|
186
|
-
|
187
179
|
# Erase the data in the IO and Ionian buffers.
|
188
180
|
# This is typically handled automatically.
|
189
181
|
def purge
|
@@ -211,7 +203,7 @@ module Ionian
|
|
211
203
|
|
212
204
|
# @deprecated Use {#register_match_handler} instead.
|
213
205
|
def register_observer &block
|
214
|
-
STDOUT.puts "
|
206
|
+
STDOUT.puts "WARNING: Call to deprecated method: #{__method__}"
|
215
207
|
register_match_handler &block
|
216
208
|
end
|
217
209
|
|
@@ -223,7 +215,7 @@ module Ionian
|
|
223
215
|
|
224
216
|
# @deprecated Use {#unregister_match_handler} instead.
|
225
217
|
def unregister_observer &block
|
226
|
-
STDOUT.puts "
|
218
|
+
STDOUT.puts "WARNING: Call to deprecated method: #{__method__}"
|
227
219
|
unregister_match_handler &block
|
228
220
|
end
|
229
221
|
|
@@ -1,9 +1,10 @@
|
|
1
1
|
require 'ionian/socket'
|
2
2
|
|
3
|
+
Thread.abort_on_exception = true
|
4
|
+
|
3
5
|
module Ionian
|
4
6
|
|
5
|
-
# A socket manager that
|
6
|
-
# like heartbeating and auto-reconnect.
|
7
|
+
# A socket manager that performs functions like heartbeating and auto-reconnect.
|
7
8
|
class ManagedSocket
|
8
9
|
|
9
10
|
# When true, automatically reconnect if the socket closes.
|
@@ -16,25 +17,69 @@ module Ionian
|
|
16
17
|
# @see Ionian::Socket#initialize More optional parameters.
|
17
18
|
def initialize **kwargs
|
18
19
|
@auto_reconnect = kwargs.delete(:auto_reconnect) || false
|
20
|
+
raise NotImplementedError, ':auto_reconnect must be set true.' unless @auto_reconnect
|
19
21
|
@kwargs = kwargs
|
20
22
|
|
21
|
-
@match_handlers
|
22
|
-
@
|
23
|
+
@match_handlers = []
|
24
|
+
@status_handlers = []
|
23
25
|
|
24
|
-
|
26
|
+
@write_queue = Queue.new
|
27
|
+
@write_pipe_rx, @write_pipe_tx = IO.pipe
|
28
|
+
@write_pipe_rx.extend Ionian::Extension::IO
|
25
29
|
end
|
26
30
|
|
27
31
|
# Close the socket.
|
28
32
|
# Disables :auto_reconnect.
|
29
33
|
def close
|
30
|
-
@
|
31
|
-
|
34
|
+
unless @closed == true
|
35
|
+
@auto_reconnect = false
|
36
|
+
@socket.close if @socket and not @socket.closed?
|
37
|
+
@write_pipe_tx.close rescue IOError
|
38
|
+
@write_pipe_rx.close rescue IOError
|
39
|
+
@write_queue = nil
|
40
|
+
|
41
|
+
@closed = true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Start the event loop.
|
46
|
+
# Should be called after the handlers are registered.
|
47
|
+
def run
|
48
|
+
@run_thread ||= Thread.new do
|
49
|
+
while not @write_pipe_rx.closed?
|
50
|
+
begin
|
51
|
+
create_socket if (not @socket or @socket.closed?) and not @write_pipe_rx.closed?
|
52
|
+
io = ::IO.select([@write_pipe_rx, @socket.fd], nil, nil, nil).first.first
|
53
|
+
|
54
|
+
case io
|
55
|
+
|
56
|
+
when @write_pipe_rx
|
57
|
+
@write_pipe_rx.read_all
|
58
|
+
while @socket and not @write_queue.empty?
|
59
|
+
@socket.write @write_queue.shift
|
60
|
+
end
|
61
|
+
|
62
|
+
when @socket.fd
|
63
|
+
@socket.read_match
|
64
|
+
|
65
|
+
end
|
66
|
+
rescue IOError # Far-end socket closed.
|
67
|
+
@socket.close if @socket and not @socket.closed?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Write data to the socket.
|
74
|
+
def write data
|
75
|
+
@write_queue << data
|
76
|
+
@write_pipe_tx.write "\n"
|
32
77
|
end
|
33
78
|
|
34
79
|
# Register a block to be called when {Ionian::Extension::IO#run_match}
|
35
80
|
# receives matched data.
|
36
81
|
# Method callbacks can be registered with &object.method(:method).
|
37
|
-
# @return [Block]
|
82
|
+
# @return [Block] the given block.
|
38
83
|
# @yield [MatchData, self]
|
39
84
|
def register_match_handler &block
|
40
85
|
@match_handlers << block unless @match_handlers.include? block
|
@@ -51,35 +96,19 @@ module Ionian
|
|
51
96
|
block
|
52
97
|
end
|
53
98
|
|
54
|
-
# Register a block to be called when
|
55
|
-
# raises an error.
|
99
|
+
# Register a block to be called when there is a change in socket status.
|
56
100
|
# Method callbacks can be registered with &object.method(:method).
|
57
101
|
# @return [Block] a reference to the given block.
|
58
|
-
# @yield [
|
59
|
-
def
|
60
|
-
|
61
|
-
@socket.register_error_handler &block if @socket
|
62
|
-
block
|
63
|
-
end
|
64
|
-
|
65
|
-
alias_method :on_error, :register_error_handler
|
66
|
-
|
67
|
-
# Unregister a block from being called when a {Ionian::IO#run_match} error
|
68
|
-
# is raised.
|
69
|
-
def unregister_error_handler &block
|
70
|
-
@error_handlers.delete_if { |o| o == block }
|
71
|
-
@socket.unregister_error_handler &block if @socket
|
72
|
-
block
|
102
|
+
# @yield [status, self]
|
103
|
+
def register_status_handler &block
|
104
|
+
raise NotImplementedError
|
73
105
|
end
|
74
106
|
|
75
|
-
|
76
|
-
# @see Ionian::Socket
|
77
|
-
def method_missing meth, *args, &block
|
78
|
-
@socket.__send__ meth, *args, &block
|
79
|
-
end
|
107
|
+
alias_method :on_status_change, :register_status_handler
|
80
108
|
|
81
|
-
|
82
|
-
|
109
|
+
# Unregister a block from being called when there is a change in socket status.
|
110
|
+
def unregister_status_handler &block
|
111
|
+
raise NotImplementedError
|
83
112
|
end
|
84
113
|
|
85
114
|
|
@@ -87,23 +116,39 @@ module Ionian
|
|
87
116
|
|
88
117
|
# Initialize or reinitialize @socket.
|
89
118
|
def create_socket
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
119
|
+
begin
|
120
|
+
@socket = Ionian::Socket.new **@kwargs
|
121
|
+
|
122
|
+
@socket.on_error &method(:socket_error_handler)
|
123
|
+
@match_handlers.each { |h| @socket.register_match_handler &h }
|
124
|
+
# @error_handlers.each { |h| @socket.register_error_handler &h }
|
125
|
+
rescue Errno::ECONNREFUSED, SystemCallError => e
|
126
|
+
if auto_reconnect
|
127
|
+
sleep @kwargs.fetch :connect_timeout, 10
|
128
|
+
retry
|
129
|
+
else
|
130
|
+
raise e
|
131
|
+
end
|
132
|
+
end
|
96
133
|
end
|
97
134
|
|
98
135
|
# {Ionian::Socket#on_error} handler for @socket.
|
99
136
|
def socket_error_handler e, socket
|
100
137
|
if auto_reconnect
|
101
|
-
@socket.close
|
138
|
+
@socket.close if @socket and not @socket.closed?
|
102
139
|
create_socket
|
103
140
|
else
|
104
141
|
raise e unless e.is_a? EOFError or e.is_a? IOError
|
105
142
|
end
|
106
143
|
end
|
107
144
|
|
145
|
+
def notify_match_handlers match
|
146
|
+
@match_handlers.each { |h| h.call match, self }
|
147
|
+
end
|
148
|
+
|
149
|
+
def notify_error_handlers exception
|
150
|
+
@error_handlers.each { |h| h.call exception, self }
|
151
|
+
end
|
152
|
+
|
108
153
|
end
|
109
154
|
end
|
data/lib/ionian/socket.rb
CHANGED
@@ -167,19 +167,27 @@ module Ionian
|
|
167
167
|
end
|
168
168
|
end
|
169
169
|
end
|
170
|
+
|
171
|
+
# @return [IO] the file descriptor for this socket.
|
172
|
+
# For use with methods like IO.select.
|
173
|
+
def fd
|
174
|
+
@socket
|
175
|
+
end
|
170
176
|
|
171
|
-
#
|
177
|
+
# @return [Regexp] the regular expression used to match incoming data.
|
172
178
|
def expression
|
173
179
|
@expression || @socket.expression
|
174
180
|
end
|
175
181
|
|
176
182
|
# Set the regular expression used to match incoming data.
|
183
|
+
# @param exp [Regexp, String] Match expression.
|
184
|
+
# @see Ionian::Extension::IO#expression=
|
177
185
|
def expression= exp
|
178
186
|
@expression = exp
|
179
187
|
@socket.expression = exp if @socket
|
180
188
|
end
|
181
189
|
|
182
|
-
#
|
190
|
+
# @return [Boolean] True if the socket remains open after writing data.
|
183
191
|
def persistent?
|
184
192
|
@persistent == false || @persistent == nil ? false : true
|
185
193
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ionian
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex McLain
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '10.4'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '10.4'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: yard
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,42 +72,42 @@ dependencies:
|
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 3.1
|
75
|
+
version: '3.1'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 3.1
|
82
|
+
version: '3.1'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: rspec-its
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: 1.0
|
89
|
+
version: '1.0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: 1.0
|
96
|
+
version: '1.0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: fivemat
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
103
|
+
version: '1.3'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
110
|
+
version: '1.3'
|
111
111
|
description: A library to simplify interaction with IO streams. This includes network
|
112
112
|
sockets, file sockets, and serial streams like the console and RS232. Features regular
|
113
113
|
expression matching and notification of received data.
|