omq 0.10.0 → 0.12.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/CHANGELOG.md +157 -0
- data/README.md +31 -4
- data/lib/omq/drop_queue.rb +54 -0
- data/lib/omq/engine.rb +103 -61
- data/lib/omq/monitor_event.rb +16 -0
- data/lib/omq/options.rb +6 -2
- data/lib/omq/pair.rb +2 -2
- data/lib/omq/pub_sub.rb +13 -12
- data/lib/omq/push_pull.rb +4 -4
- data/lib/omq/queue_interface.rb +73 -0
- data/lib/omq/readable.rb +2 -0
- data/lib/omq/req_rep.rb +4 -4
- data/lib/omq/router_dealer.rb +4 -4
- data/lib/omq/routing/dealer.rb +1 -1
- data/lib/omq/routing/fan_out.rb +26 -5
- data/lib/omq/routing/pair.rb +2 -2
- data/lib/omq/routing/pull.rb +1 -1
- data/lib/omq/routing/push.rb +2 -0
- data/lib/omq/routing/rep.rb +2 -2
- data/lib/omq/routing/req.rb +8 -3
- data/lib/omq/routing/round_robin.rb +4 -12
- data/lib/omq/routing/router.rb +2 -2
- data/lib/omq/routing/sub.rb +1 -2
- data/lib/omq/routing/xpub.rb +1 -1
- data/lib/omq/routing/xsub.rb +2 -2
- data/lib/omq/routing.rb +41 -11
- data/lib/omq/socket.rb +49 -2
- data/lib/omq/transport/inproc.rb +25 -7
- data/lib/omq/transport/ipc.rb +16 -4
- data/lib/omq/transport/tcp.rb +31 -8
- data/lib/omq/version.rb +1 -1
- data/lib/omq/writable.rb +1 -0
- data/lib/omq.rb +6 -16
- metadata +4 -15
- data/lib/omq/channel.rb +0 -14
- data/lib/omq/client_server.rb +0 -37
- data/lib/omq/peer.rb +0 -26
- data/lib/omq/radio_dish.rb +0 -74
- data/lib/omq/routing/channel.rb +0 -83
- data/lib/omq/routing/client.rb +0 -56
- data/lib/omq/routing/dish.rb +0 -78
- data/lib/omq/routing/gather.rb +0 -46
- data/lib/omq/routing/peer.rb +0 -101
- data/lib/omq/routing/radio.rb +0 -140
- data/lib/omq/routing/scatter.rb +0 -82
- data/lib/omq/routing/server.rb +0 -101
- data/lib/omq/scatter_gather.rb +0 -23
- data/lib/omq/single_frame.rb +0 -18
data/lib/omq/transport/inproc.rb
CHANGED
|
@@ -118,11 +118,12 @@ module OMQ
|
|
|
118
118
|
"incompatible socket types: #{client_type} cannot connect to #{server_type}"
|
|
119
119
|
end
|
|
120
120
|
|
|
121
|
-
#
|
|
122
|
-
# over inproc.
|
|
123
|
-
# bypass for data, so no internal queues are needed.
|
|
121
|
+
# PUB/SUB-family types exchange commands (SUBSCRIBE/CANCEL)
|
|
122
|
+
# over inproc. QoS >= 1 needs command queues for ACK/NACK.
|
|
124
123
|
needs_commands = COMMAND_TYPES.include?(client_type) ||
|
|
125
|
-
COMMAND_TYPES.include?(server_type)
|
|
124
|
+
COMMAND_TYPES.include?(server_type) ||
|
|
125
|
+
client_engine.options.qos >= 1 ||
|
|
126
|
+
server_engine.options.qos >= 1
|
|
126
127
|
|
|
127
128
|
if needs_commands
|
|
128
129
|
a_to_b = Async::Queue.new
|
|
@@ -301,13 +302,30 @@ module OMQ
|
|
|
301
302
|
|
|
302
303
|
# Receives a multi-frame message.
|
|
303
304
|
#
|
|
305
|
+
# When a block is given, command items ([:command, cmd]) are
|
|
306
|
+
# yielded as command frames — matching the Protocol::ZMTP::Connection
|
|
307
|
+
# interface. Without a block, commands are silently skipped if
|
|
308
|
+
# the pipe has command queues.
|
|
309
|
+
#
|
|
304
310
|
# @return [Array<String>]
|
|
305
311
|
# @raise [EOFError] if closed
|
|
306
312
|
#
|
|
307
313
|
def receive_message
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
314
|
+
loop do
|
|
315
|
+
item = @receive_queue.dequeue
|
|
316
|
+
raise EOFError, "connection closed" if item.nil?
|
|
317
|
+
|
|
318
|
+
if item.is_a?(Array) && item.first == :command
|
|
319
|
+
if block_given?
|
|
320
|
+
cmd = item[1]
|
|
321
|
+
frame = Protocol::ZMTP::Codec::Frame.new(cmd.to_body, command: true)
|
|
322
|
+
yield frame
|
|
323
|
+
end
|
|
324
|
+
next
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
return item
|
|
328
|
+
end
|
|
311
329
|
end
|
|
312
330
|
|
|
313
331
|
|
data/lib/omq/transport/ipc.rb
CHANGED
|
@@ -92,12 +92,24 @@ module OMQ
|
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
|
|
95
|
-
#
|
|
95
|
+
# Spawns an accept loop task under +parent_task+.
|
|
96
|
+
# Yields an IO::Stream-wrapped client socket for each accepted connection.
|
|
96
97
|
#
|
|
97
|
-
# @param
|
|
98
|
+
# @param parent_task [Async::Task]
|
|
99
|
+
# @yieldparam io [IO::Stream::Buffered]
|
|
98
100
|
#
|
|
99
|
-
def
|
|
100
|
-
@task =
|
|
101
|
+
def start_accept_loops(parent_task, &on_accepted)
|
|
102
|
+
@task = parent_task.async(transient: true, annotation: "ipc accept #{@endpoint}") do
|
|
103
|
+
loop do
|
|
104
|
+
client = @server.accept
|
|
105
|
+
Async::Task.current.defer_stop { on_accepted.call(IO::Stream::Buffered.wrap(client)) }
|
|
106
|
+
end
|
|
107
|
+
rescue Async::Stop
|
|
108
|
+
rescue IOError
|
|
109
|
+
# server closed
|
|
110
|
+
ensure
|
|
111
|
+
@server.close rescue nil
|
|
112
|
+
end
|
|
101
113
|
end
|
|
102
114
|
|
|
103
115
|
|
data/lib/omq/transport/tcp.rb
CHANGED
|
@@ -17,7 +17,7 @@ module OMQ
|
|
|
17
17
|
# @return [Listener]
|
|
18
18
|
#
|
|
19
19
|
def bind(endpoint, engine)
|
|
20
|
-
host, port = parse_endpoint(endpoint)
|
|
20
|
+
host, port = self.parse_endpoint(endpoint)
|
|
21
21
|
host = "0.0.0.0" if host == "*"
|
|
22
22
|
|
|
23
23
|
addrs = Addrinfo.getaddrinfo(host, port, nil, :STREAM, nil, ::Socket::AI_PASSIVE)
|
|
@@ -43,14 +43,23 @@ module OMQ
|
|
|
43
43
|
# @param engine [Engine]
|
|
44
44
|
# @return [void]
|
|
45
45
|
#
|
|
46
|
+
# Validates that the endpoint's host can be resolved.
|
|
47
|
+
#
|
|
48
|
+
# @param endpoint [String]
|
|
49
|
+
# @return [void]
|
|
50
|
+
#
|
|
51
|
+
def validate_endpoint!(endpoint)
|
|
52
|
+
host, _port = parse_endpoint(endpoint)
|
|
53
|
+
Addrinfo.getaddrinfo(host, nil, nil, :STREAM) if host
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
|
|
46
57
|
def connect(endpoint, engine)
|
|
47
|
-
host, port = parse_endpoint(endpoint)
|
|
58
|
+
host, port = self.parse_endpoint(endpoint)
|
|
48
59
|
sock = TCPSocket.new(host, port)
|
|
49
60
|
engine.handle_connected(IO::Stream::Buffered.wrap(sock), endpoint: endpoint)
|
|
50
61
|
end
|
|
51
62
|
|
|
52
|
-
private
|
|
53
|
-
|
|
54
63
|
# Parses a TCP endpoint URI into host and port.
|
|
55
64
|
#
|
|
56
65
|
# @param endpoint [String]
|
|
@@ -90,12 +99,26 @@ module OMQ
|
|
|
90
99
|
end
|
|
91
100
|
|
|
92
101
|
|
|
93
|
-
#
|
|
102
|
+
# Spawns accept loop tasks under +parent_task+.
|
|
103
|
+
# Yields an IO::Stream-wrapped client socket for each accepted connection.
|
|
94
104
|
#
|
|
95
|
-
# @param
|
|
105
|
+
# @param parent_task [Async::Task]
|
|
106
|
+
# @yieldparam io [IO::Stream::Buffered]
|
|
96
107
|
#
|
|
97
|
-
def
|
|
98
|
-
@tasks =
|
|
108
|
+
def start_accept_loops(parent_task, &on_accepted)
|
|
109
|
+
@tasks = @servers.map do |server|
|
|
110
|
+
parent_task.async(transient: true, annotation: "tcp accept #{@endpoint}") do
|
|
111
|
+
loop do
|
|
112
|
+
client = server.accept
|
|
113
|
+
Async::Task.current.defer_stop { on_accepted.call(IO::Stream::Buffered.wrap(client)) }
|
|
114
|
+
end
|
|
115
|
+
rescue Async::Stop
|
|
116
|
+
rescue IOError
|
|
117
|
+
# server closed
|
|
118
|
+
ensure
|
|
119
|
+
server.close rescue nil
|
|
120
|
+
end
|
|
121
|
+
end
|
|
99
122
|
end
|
|
100
123
|
|
|
101
124
|
|
data/lib/omq/version.rb
CHANGED
data/lib/omq/writable.rb
CHANGED
data/lib/omq.rb
CHANGED
|
@@ -10,6 +10,7 @@ require "protocol/zmtp"
|
|
|
10
10
|
require "io/stream"
|
|
11
11
|
|
|
12
12
|
require_relative "omq/version"
|
|
13
|
+
require_relative "omq/monitor_event"
|
|
13
14
|
|
|
14
15
|
module OMQ
|
|
15
16
|
# Raised when an internal pump task crashes unexpectedly.
|
|
@@ -18,6 +19,8 @@ module OMQ
|
|
|
18
19
|
class SocketDeadError < RuntimeError; end
|
|
19
20
|
|
|
20
21
|
# Errors raised when a peer disconnects or resets the connection.
|
|
22
|
+
# Not frozen at load time — transport plugins append to this before
|
|
23
|
+
# the first bind/connect, which freezes both arrays.
|
|
21
24
|
CONNECTION_LOST = [
|
|
22
25
|
EOFError,
|
|
23
26
|
IOError,
|
|
@@ -26,7 +29,7 @@ module OMQ
|
|
|
26
29
|
Errno::ECONNABORTED,
|
|
27
30
|
Errno::ENOTCONN,
|
|
28
31
|
IO::Stream::ConnectionResetError,
|
|
29
|
-
]
|
|
32
|
+
]
|
|
30
33
|
|
|
31
34
|
# Errors raised when a peer cannot be reached.
|
|
32
35
|
CONNECTION_FAILED = [
|
|
@@ -36,7 +39,7 @@ module OMQ
|
|
|
36
39
|
Errno::EHOSTUNREACH,
|
|
37
40
|
Errno::ENETUNREACH,
|
|
38
41
|
Socket::ResolutionError,
|
|
39
|
-
]
|
|
42
|
+
]
|
|
40
43
|
end
|
|
41
44
|
|
|
42
45
|
# Transport
|
|
@@ -61,16 +64,8 @@ require_relative "omq/routing/xpub"
|
|
|
61
64
|
require_relative "omq/routing/xsub"
|
|
62
65
|
require_relative "omq/routing/push"
|
|
63
66
|
require_relative "omq/routing/pull"
|
|
64
|
-
require_relative "omq/routing/scatter"
|
|
65
|
-
require_relative "omq/routing/gather"
|
|
66
|
-
require_relative "omq/routing/channel"
|
|
67
|
-
require_relative "omq/routing/client"
|
|
68
|
-
require_relative "omq/routing/server"
|
|
69
|
-
require_relative "omq/routing/radio"
|
|
70
|
-
require_relative "omq/routing/dish"
|
|
71
|
-
require_relative "omq/routing/peer"
|
|
72
|
-
require_relative "omq/single_frame"
|
|
73
67
|
require_relative "omq/engine"
|
|
68
|
+
require_relative "omq/queue_interface"
|
|
74
69
|
require_relative "omq/readable"
|
|
75
70
|
require_relative "omq/writable"
|
|
76
71
|
|
|
@@ -81,11 +76,6 @@ require_relative "omq/router_dealer"
|
|
|
81
76
|
require_relative "omq/pub_sub"
|
|
82
77
|
require_relative "omq/push_pull"
|
|
83
78
|
require_relative "omq/pair"
|
|
84
|
-
require_relative "omq/scatter_gather"
|
|
85
|
-
require_relative "omq/channel"
|
|
86
|
-
require_relative "omq/client_server"
|
|
87
|
-
require_relative "omq/radio_dish"
|
|
88
|
-
require_relative "omq/peer"
|
|
89
79
|
|
|
90
80
|
# For the purists.
|
|
91
81
|
ØMQ = OMQ
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omq
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.12.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -65,43 +65,32 @@ files:
|
|
|
65
65
|
- LICENSE
|
|
66
66
|
- README.md
|
|
67
67
|
- lib/omq.rb
|
|
68
|
-
- lib/omq/
|
|
69
|
-
- lib/omq/client_server.rb
|
|
68
|
+
- lib/omq/drop_queue.rb
|
|
70
69
|
- lib/omq/engine.rb
|
|
70
|
+
- lib/omq/monitor_event.rb
|
|
71
71
|
- lib/omq/options.rb
|
|
72
72
|
- lib/omq/pair.rb
|
|
73
|
-
- lib/omq/peer.rb
|
|
74
73
|
- lib/omq/pub_sub.rb
|
|
75
74
|
- lib/omq/push_pull.rb
|
|
76
|
-
- lib/omq/
|
|
75
|
+
- lib/omq/queue_interface.rb
|
|
77
76
|
- lib/omq/reactor.rb
|
|
78
77
|
- lib/omq/readable.rb
|
|
79
78
|
- lib/omq/req_rep.rb
|
|
80
79
|
- lib/omq/router_dealer.rb
|
|
81
80
|
- lib/omq/routing.rb
|
|
82
|
-
- lib/omq/routing/channel.rb
|
|
83
|
-
- lib/omq/routing/client.rb
|
|
84
81
|
- lib/omq/routing/dealer.rb
|
|
85
|
-
- lib/omq/routing/dish.rb
|
|
86
82
|
- lib/omq/routing/fan_out.rb
|
|
87
|
-
- lib/omq/routing/gather.rb
|
|
88
83
|
- lib/omq/routing/pair.rb
|
|
89
|
-
- lib/omq/routing/peer.rb
|
|
90
84
|
- lib/omq/routing/pub.rb
|
|
91
85
|
- lib/omq/routing/pull.rb
|
|
92
86
|
- lib/omq/routing/push.rb
|
|
93
|
-
- lib/omq/routing/radio.rb
|
|
94
87
|
- lib/omq/routing/rep.rb
|
|
95
88
|
- lib/omq/routing/req.rb
|
|
96
89
|
- lib/omq/routing/round_robin.rb
|
|
97
90
|
- lib/omq/routing/router.rb
|
|
98
|
-
- lib/omq/routing/scatter.rb
|
|
99
|
-
- lib/omq/routing/server.rb
|
|
100
91
|
- lib/omq/routing/sub.rb
|
|
101
92
|
- lib/omq/routing/xpub.rb
|
|
102
93
|
- lib/omq/routing/xsub.rb
|
|
103
|
-
- lib/omq/scatter_gather.rb
|
|
104
|
-
- lib/omq/single_frame.rb
|
|
105
94
|
- lib/omq/socket.rb
|
|
106
95
|
- lib/omq/transport/inproc.rb
|
|
107
96
|
- lib/omq/transport/ipc.rb
|
data/lib/omq/channel.rb
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class CHANNEL < Socket
|
|
5
|
-
include Readable
|
|
6
|
-
include Writable
|
|
7
|
-
include SingleFrame
|
|
8
|
-
|
|
9
|
-
def initialize(endpoints = nil, linger: 0)
|
|
10
|
-
_init_engine(:CHANNEL, linger: linger)
|
|
11
|
-
_attach(endpoints, default: :connect)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
data/lib/omq/client_server.rb
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class CLIENT < Socket
|
|
5
|
-
include Readable
|
|
6
|
-
include Writable
|
|
7
|
-
include SingleFrame
|
|
8
|
-
|
|
9
|
-
def initialize(endpoints = nil, linger: 0)
|
|
10
|
-
_init_engine(:CLIENT, linger: linger)
|
|
11
|
-
_attach(endpoints, default: :connect)
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
class SERVER < Socket
|
|
16
|
-
include Readable
|
|
17
|
-
include Writable
|
|
18
|
-
include SingleFrame
|
|
19
|
-
|
|
20
|
-
def initialize(endpoints = nil, linger: 0)
|
|
21
|
-
_init_engine(:SERVER, linger: linger)
|
|
22
|
-
_attach(endpoints, default: :bind)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Sends a message to a specific peer by routing ID.
|
|
26
|
-
#
|
|
27
|
-
# @param routing_id [String] 4-byte routing ID
|
|
28
|
-
# @param message [String] message body
|
|
29
|
-
# @return [self]
|
|
30
|
-
#
|
|
31
|
-
def send_to(routing_id, message)
|
|
32
|
-
parts = [routing_id.b.freeze, message.b.freeze]
|
|
33
|
-
with_timeout(@options.write_timeout) { @engine.enqueue_send(parts) }
|
|
34
|
-
self
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|
data/lib/omq/peer.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class PEER < Socket
|
|
5
|
-
include Readable
|
|
6
|
-
include Writable
|
|
7
|
-
include SingleFrame
|
|
8
|
-
|
|
9
|
-
def initialize(endpoints = nil, linger: 0)
|
|
10
|
-
_init_engine(:PEER, linger: linger)
|
|
11
|
-
_attach(endpoints, default: :connect)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
# Sends a message to a specific peer by routing ID.
|
|
15
|
-
#
|
|
16
|
-
# @param routing_id [String] 4-byte routing ID
|
|
17
|
-
# @param message [String] message body
|
|
18
|
-
# @return [self]
|
|
19
|
-
#
|
|
20
|
-
def send_to(routing_id, message)
|
|
21
|
-
parts = [routing_id.b.freeze, message.b.freeze]
|
|
22
|
-
with_timeout(@options.write_timeout) { @engine.enqueue_send(parts) }
|
|
23
|
-
self
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
data/lib/omq/radio_dish.rb
DELETED
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
class RADIO < Socket
|
|
5
|
-
include Writable
|
|
6
|
-
|
|
7
|
-
def initialize(endpoints = nil, linger: 0, conflate: false)
|
|
8
|
-
_init_engine(:RADIO, linger: linger, conflate: conflate)
|
|
9
|
-
_attach(endpoints, default: :bind)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
# Publishes a message to a group.
|
|
13
|
-
#
|
|
14
|
-
# @param group [String] group name
|
|
15
|
-
# @param body [String] message body
|
|
16
|
-
# @return [self]
|
|
17
|
-
#
|
|
18
|
-
def publish(group, body)
|
|
19
|
-
with_timeout(@options.write_timeout) do
|
|
20
|
-
@engine.enqueue_send([group.b.freeze, body.b.freeze])
|
|
21
|
-
end
|
|
22
|
-
self
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
# Sends a message to a group.
|
|
26
|
-
#
|
|
27
|
-
# @param message [String] message body (requires group: kwarg)
|
|
28
|
-
# @param group [String] group name
|
|
29
|
-
# @return [self]
|
|
30
|
-
#
|
|
31
|
-
def send(message, group: nil)
|
|
32
|
-
raise ArgumentError, "RADIO requires a group (use group: kwarg, publish, or << [group, body])" unless group
|
|
33
|
-
publish(group, message)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# Sends a message to a group via [group, body] array.
|
|
37
|
-
#
|
|
38
|
-
# @param message [Array<String>] [group, body]
|
|
39
|
-
# @return [self]
|
|
40
|
-
#
|
|
41
|
-
def <<(message)
|
|
42
|
-
raise ArgumentError, "RADIO requires [group, body] array" unless message.is_a?(Array) && message.size == 2
|
|
43
|
-
publish(message[0], message[1])
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
class DISH < Socket
|
|
48
|
-
include Readable
|
|
49
|
-
|
|
50
|
-
def initialize(endpoints = nil, linger: 0, group: nil)
|
|
51
|
-
_init_engine(:DISH, linger: linger)
|
|
52
|
-
_attach(endpoints, default: :connect)
|
|
53
|
-
join(group) if group
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
# Joins a group.
|
|
57
|
-
#
|
|
58
|
-
# @param group [String]
|
|
59
|
-
# @return [void]
|
|
60
|
-
#
|
|
61
|
-
def join(group)
|
|
62
|
-
@engine.routing.join(group)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
# Leaves a group.
|
|
66
|
-
#
|
|
67
|
-
# @param group [String]
|
|
68
|
-
# @return [void]
|
|
69
|
-
#
|
|
70
|
-
def leave(group)
|
|
71
|
-
@engine.routing.leave(group)
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
end
|
data/lib/omq/routing/channel.rb
DELETED
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
module Routing
|
|
5
|
-
# CHANNEL socket routing: exclusive 1-to-1 bidirectional.
|
|
6
|
-
#
|
|
7
|
-
class Channel
|
|
8
|
-
|
|
9
|
-
# @param engine [Engine]
|
|
10
|
-
#
|
|
11
|
-
def initialize(engine)
|
|
12
|
-
@engine = engine
|
|
13
|
-
@connection = nil
|
|
14
|
-
@recv_queue = Async::LimitedQueue.new(engine.options.recv_hwm)
|
|
15
|
-
@send_queue = Async::LimitedQueue.new(engine.options.send_hwm)
|
|
16
|
-
@tasks = []
|
|
17
|
-
@send_pump_idle = true
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
# @return [Async::LimitedQueue]
|
|
21
|
-
#
|
|
22
|
-
attr_reader :recv_queue, :send_queue
|
|
23
|
-
|
|
24
|
-
# @param connection [Connection]
|
|
25
|
-
# @raise [RuntimeError] if a connection already exists
|
|
26
|
-
#
|
|
27
|
-
def connection_added(connection)
|
|
28
|
-
raise "CHANNEL allows only one peer" if @connection
|
|
29
|
-
@connection = connection
|
|
30
|
-
task = @engine.start_recv_pump(connection, @recv_queue)
|
|
31
|
-
@tasks << task if task
|
|
32
|
-
start_send_pump(connection) unless connection.is_a?(Transport::Inproc::DirectPipe)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
# @param connection [Connection]
|
|
36
|
-
#
|
|
37
|
-
def connection_removed(connection)
|
|
38
|
-
if @connection == connection
|
|
39
|
-
@connection = nil
|
|
40
|
-
@send_pump&.stop
|
|
41
|
-
@send_pump = nil
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# @param parts [Array<String>]
|
|
46
|
-
#
|
|
47
|
-
def enqueue(parts)
|
|
48
|
-
conn = @connection
|
|
49
|
-
if conn.is_a?(Transport::Inproc::DirectPipe) && conn.direct_recv_queue
|
|
50
|
-
conn.send_message(parts)
|
|
51
|
-
else
|
|
52
|
-
@send_queue.enqueue(parts)
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
#
|
|
57
|
-
def stop
|
|
58
|
-
@tasks.each(&:stop)
|
|
59
|
-
@tasks.clear
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
def send_pump_idle? = @send_pump_idle
|
|
63
|
-
|
|
64
|
-
private
|
|
65
|
-
|
|
66
|
-
def start_send_pump(conn)
|
|
67
|
-
@send_pump = @engine.spawn_pump_task(annotation: "send pump") do
|
|
68
|
-
loop do
|
|
69
|
-
@send_pump_idle = true
|
|
70
|
-
batch = [@send_queue.dequeue]
|
|
71
|
-
@send_pump_idle = false
|
|
72
|
-
Routing.drain_send_queue(@send_queue, batch)
|
|
73
|
-
batch.each { |parts| conn.write_message(parts) }
|
|
74
|
-
conn.flush
|
|
75
|
-
end
|
|
76
|
-
rescue *CONNECTION_LOST
|
|
77
|
-
@engine.connection_lost(conn)
|
|
78
|
-
end
|
|
79
|
-
@tasks << @send_pump
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
data/lib/omq/routing/client.rb
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
module Routing
|
|
5
|
-
# CLIENT socket routing: round-robin send, fair-queue receive.
|
|
6
|
-
#
|
|
7
|
-
# Same as DEALER — no envelope manipulation.
|
|
8
|
-
#
|
|
9
|
-
class Client
|
|
10
|
-
include RoundRobin
|
|
11
|
-
|
|
12
|
-
# @param engine [Engine]
|
|
13
|
-
#
|
|
14
|
-
def initialize(engine)
|
|
15
|
-
@engine = engine
|
|
16
|
-
@recv_queue = Async::LimitedQueue.new(engine.options.recv_hwm)
|
|
17
|
-
@tasks = []
|
|
18
|
-
init_round_robin(engine)
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# @return [Async::LimitedQueue]
|
|
22
|
-
#
|
|
23
|
-
attr_reader :recv_queue, :send_queue
|
|
24
|
-
|
|
25
|
-
# @param connection [Connection]
|
|
26
|
-
#
|
|
27
|
-
def connection_added(connection)
|
|
28
|
-
@connections << connection
|
|
29
|
-
signal_connection_available
|
|
30
|
-
update_direct_pipe
|
|
31
|
-
task = @engine.start_recv_pump(connection, @recv_queue)
|
|
32
|
-
@tasks << task if task
|
|
33
|
-
start_send_pump unless @send_pump_started
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
# @param connection [Connection]
|
|
37
|
-
#
|
|
38
|
-
def connection_removed(connection)
|
|
39
|
-
@connections.delete(connection)
|
|
40
|
-
update_direct_pipe
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
# @param parts [Array<String>]
|
|
44
|
-
#
|
|
45
|
-
def enqueue(parts)
|
|
46
|
-
enqueue_round_robin(parts)
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
#
|
|
50
|
-
def stop
|
|
51
|
-
@tasks.each(&:stop)
|
|
52
|
-
@tasks.clear
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
data/lib/omq/routing/dish.rb
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module OMQ
|
|
4
|
-
module Routing
|
|
5
|
-
# DISH socket routing: group-based receive from RADIO peers.
|
|
6
|
-
#
|
|
7
|
-
# Sends JOIN/LEAVE commands to connected RADIO peers.
|
|
8
|
-
# Receives two-frame messages (group + body) from RADIO.
|
|
9
|
-
#
|
|
10
|
-
class Dish
|
|
11
|
-
|
|
12
|
-
# @param engine [Engine]
|
|
13
|
-
#
|
|
14
|
-
def initialize(engine)
|
|
15
|
-
@engine = engine
|
|
16
|
-
@connections = []
|
|
17
|
-
@recv_queue = Async::LimitedQueue.new(engine.options.recv_hwm)
|
|
18
|
-
@groups = Set.new
|
|
19
|
-
@tasks = []
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
# @return [Async::LimitedQueue]
|
|
23
|
-
#
|
|
24
|
-
attr_reader :recv_queue
|
|
25
|
-
|
|
26
|
-
# @param connection [Connection]
|
|
27
|
-
#
|
|
28
|
-
def connection_added(connection)
|
|
29
|
-
@connections << connection
|
|
30
|
-
# Send existing group memberships to new peer
|
|
31
|
-
@groups.each do |group|
|
|
32
|
-
connection.send_command(Protocol::ZMTP::Codec::Command.join(group))
|
|
33
|
-
end
|
|
34
|
-
task = @engine.start_recv_pump(connection, @recv_queue)
|
|
35
|
-
@tasks << task if task
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# @param connection [Connection]
|
|
39
|
-
#
|
|
40
|
-
def connection_removed(connection)
|
|
41
|
-
@connections.delete(connection)
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# DISH is read-only.
|
|
45
|
-
#
|
|
46
|
-
def enqueue(_parts)
|
|
47
|
-
raise "DISH sockets cannot send"
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
# Joins a group.
|
|
51
|
-
#
|
|
52
|
-
# @param group [String]
|
|
53
|
-
#
|
|
54
|
-
def join(group)
|
|
55
|
-
@groups << group
|
|
56
|
-
@connections.each do |conn|
|
|
57
|
-
conn.send_command(Protocol::ZMTP::Codec::Command.join(group))
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
# Leaves a group.
|
|
62
|
-
#
|
|
63
|
-
# @param group [String]
|
|
64
|
-
#
|
|
65
|
-
def leave(group)
|
|
66
|
-
@groups.delete(group)
|
|
67
|
-
@connections.each do |conn|
|
|
68
|
-
conn.send_command(Protocol::ZMTP::Codec::Command.leave(group))
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def stop
|
|
73
|
-
@tasks.each(&:stop)
|
|
74
|
-
@tasks.clear
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|