zmqmachine 0.6.0 → 0.7.1
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.
- data/.gitignore +15 -0
- data/AUTHORS.txt +3 -0
- data/History.txt +19 -0
- data/examples/fake_ftp.rb +9 -1
- data/examples/one_handed_ping_pong.rb +2 -1
- data/examples/ping_pong.rb +2 -2
- data/examples/pub_sub.rb +10 -4
- data/examples/pubsub_forwarder.rb +8 -3
- data/examples/throttled_ping_pong.rb +2 -2
- data/lib/zm/configuration.rb +129 -0
- data/lib/zm/device.rb +4 -0
- data/lib/zm/device/configuration.rb +24 -0
- data/lib/zm/{devices → device}/forwarder.rb +48 -46
- data/lib/zm/{devices → device}/queue.rb +63 -44
- data/lib/zm/log_client.rb +2 -2
- data/lib/zm/log_server.rb +68 -0
- data/lib/zm/reactor.rb +42 -29
- data/lib/zm/server.rb +4 -0
- data/lib/zm/server/base.rb +139 -0
- data/lib/zm/server/configuration.rb +53 -0
- data/lib/zm/server/pair.rb +23 -0
- data/lib/zm/server/pub.rb +23 -0
- data/lib/zm/server/pull.rb +24 -0
- data/lib/zm/server/push.rb +23 -0
- data/lib/zm/server/rep.rb +42 -0
- data/lib/zm/server/req.rb +41 -0
- data/lib/zm/server/routing_envelope.rb +26 -0
- data/lib/zm/server/sub.rb +40 -0
- data/lib/zm/sockets.rb +1 -1
- data/lib/zm/sockets/base.rb +3 -12
- data/lib/zm/sockets/envelope_help.rb +49 -0
- data/lib/zm/sockets/pair.rb +0 -1
- data/lib/zm/sockets/pub.rb +0 -1
- data/lib/zm/sockets/rep.rb +45 -0
- data/lib/zm/sockets/req.rb +46 -1
- data/lib/zm/sockets/sub.rb +0 -1
- data/lib/zm/timers.rb +26 -13
- data/lib/zmqmachine.rb +1 -1
- data/version.txt +1 -1
- data/zmqmachine.gemspec +6 -6
- metadata +90 -91
- data/lib/zm/devices.rb +0 -4
- data/lib/zm/sockets/xrep.rb +0 -86
- data/lib/zm/sockets/xreq.rb +0 -86
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
module Server
|
4
|
+
ZMQMachine::ConfigClassMaker.create_class('Configuration',
|
5
|
+
%w( on_read bind connect endpoint topic hwm linger extra reactor ),
|
6
|
+
ZMQMachine::Configuration,
|
7
|
+
ZMQMachine::Server)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
#module ZMQMachine
|
12
|
+
#
|
13
|
+
# module Server
|
14
|
+
#
|
15
|
+
# class Configuration
|
16
|
+
# Fields = %w( on_read bind connect endpoint topic hwm linger extra reactor name context log_endpoint exception_handler )
|
17
|
+
#
|
18
|
+
# # Creates a Configuration object from another object that conforms
|
19
|
+
# # to the Configuration protocol.
|
20
|
+
# #
|
21
|
+
# def self.create_from(other_config)
|
22
|
+
# config = new
|
23
|
+
# Fields.each do |name|
|
24
|
+
# config.send("#{name}", other_config.send(name.to_sym)) if config.respond_to?(name.to_sym)
|
25
|
+
# end
|
26
|
+
# config
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# def initialize(&blk)
|
30
|
+
# instance_eval(&blk) if block_given?
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# Fields.each do |name|
|
34
|
+
# code = <<-code
|
35
|
+
# def #{ name } (value = nil)
|
36
|
+
# if value
|
37
|
+
# @#{name} = value
|
38
|
+
# else
|
39
|
+
# @#{name}
|
40
|
+
# end
|
41
|
+
# end
|
42
|
+
#
|
43
|
+
# def #{ name }=(value)
|
44
|
+
# @#{name} = value
|
45
|
+
# end
|
46
|
+
# code
|
47
|
+
#
|
48
|
+
# class_eval code
|
49
|
+
# end
|
50
|
+
# end # class Configuration
|
51
|
+
#
|
52
|
+
# end # Server
|
53
|
+
#end # ZMQMachine
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module Pair
|
7
|
+
include Base
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def allocate_socket
|
12
|
+
@socket = @reactor.pair_socket(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def register_for_events socket
|
16
|
+
@reactor.register_readable socket
|
17
|
+
@reactor.register_writable socket
|
18
|
+
end
|
19
|
+
|
20
|
+
end # module Pair
|
21
|
+
|
22
|
+
end # module Server
|
23
|
+
end # ZMQMachine
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module PUB
|
7
|
+
include Base
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def allocate_socket
|
12
|
+
@socket = @reactor.pub_socket(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def register_for_events socket
|
16
|
+
@reactor.deregister_readable socket
|
17
|
+
@reactor.deregister_writable socket
|
18
|
+
end
|
19
|
+
|
20
|
+
end # module PUB
|
21
|
+
|
22
|
+
end # module Server
|
23
|
+
end # ZMQMachine
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module PULL
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def write messages
|
10
|
+
# no op
|
11
|
+
close messages
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def allocate_socket
|
18
|
+
@socket = @reactor.pull_socket(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
end # module PULL
|
22
|
+
|
23
|
+
end # module Server
|
24
|
+
end # ZMQMachine
|
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module PUSH
|
7
|
+
include Base
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def allocate_socket
|
12
|
+
@socket = @reactor.push_socket(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def register_for_events socket
|
16
|
+
@reactor.deregister_readable socket
|
17
|
+
@reactor.deregister_writable socket
|
18
|
+
end
|
19
|
+
|
20
|
+
end # module PUSH
|
21
|
+
|
22
|
+
end # module Servers
|
23
|
+
end # ZMQMachine
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module REP
|
7
|
+
include Base
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def allocate_socket
|
12
|
+
@socket = @reactor.rep_socket(self)
|
13
|
+
end
|
14
|
+
end # module REP
|
15
|
+
|
16
|
+
|
17
|
+
module XREP
|
18
|
+
include Base
|
19
|
+
include RoutingEnvelope
|
20
|
+
|
21
|
+
def on_readable socket, messages, envelope
|
22
|
+
@routing = save_routing envelope
|
23
|
+
|
24
|
+
@on_read.call socket, messages, envelope
|
25
|
+
close_messages(envelope + messages)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def allocate_socket
|
32
|
+
@socket = @reactor.xrep_socket(self)
|
33
|
+
end
|
34
|
+
end # module XREP
|
35
|
+
|
36
|
+
|
37
|
+
module ROUTER
|
38
|
+
include XREP
|
39
|
+
end # module ROUTER
|
40
|
+
|
41
|
+
end # module Server
|
42
|
+
end # ZMQMachine
|
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module REQ
|
7
|
+
include Base
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
def allocate_socket
|
12
|
+
@socket = @reactor.req_socket(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
end # module REQ
|
16
|
+
|
17
|
+
module XREQ
|
18
|
+
include Base
|
19
|
+
include RoutingEnvelope
|
20
|
+
|
21
|
+
def on_readable socket, messages, envelope
|
22
|
+
@routing = save_routing envelope
|
23
|
+
|
24
|
+
@on_read.call socket, messages, envelope
|
25
|
+
close_messages(envelope + messages)
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def allocate_socket
|
31
|
+
@socket = @reactor.xreq_socket(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
end # module XREQ
|
35
|
+
|
36
|
+
module DEALER
|
37
|
+
include XREQ
|
38
|
+
end # module DEALER
|
39
|
+
|
40
|
+
end # module Server
|
41
|
+
end # ZMQMachine
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module RoutingEnvelope
|
7
|
+
# Saves the return routing information for XREP sockets
|
8
|
+
def save_routing messages
|
9
|
+
@routing_messages = []
|
10
|
+
@routing_strings = []
|
11
|
+
messages.each do |message|
|
12
|
+
string = message.copy_out_string
|
13
|
+
@routing_strings << string
|
14
|
+
@routing_messages << ZMQ::Message.new(string)
|
15
|
+
end
|
16
|
+
|
17
|
+
@routing_messages
|
18
|
+
end
|
19
|
+
|
20
|
+
def routing_strings
|
21
|
+
@routing_strings.dup
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Server
|
5
|
+
|
6
|
+
module SUB
|
7
|
+
include Base
|
8
|
+
|
9
|
+
def initialize configuration
|
10
|
+
@topic = configuration.topic || ''
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def write messages
|
15
|
+
# no op
|
16
|
+
close messages
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def allocate_socket
|
23
|
+
@socket = @reactor.sub_socket(self)
|
24
|
+
end
|
25
|
+
|
26
|
+
def register_for_events socket
|
27
|
+
subscribe socket, @topic
|
28
|
+
|
29
|
+
super
|
30
|
+
end
|
31
|
+
|
32
|
+
def subscribe socket, topic
|
33
|
+
rc = socket.subscribe topic
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end # module SUB
|
38
|
+
|
39
|
+
end # module Server
|
40
|
+
end # ZMQMachine
|
data/lib/zm/sockets.rb
CHANGED
data/lib/zm/sockets/base.rb
CHANGED
@@ -129,7 +129,7 @@ module ZMQMachine
|
|
129
129
|
@raw_socket.sendmsgs messages
|
130
130
|
end
|
131
131
|
|
132
|
-
if LibZMQ.version2? || LibZMQ.version3?
|
132
|
+
if ZMQ::LibZMQ.version2? || ZMQ::LibZMQ.version3?
|
133
133
|
|
134
134
|
# Retrieve the IDENTITY value assigned to this socket.
|
135
135
|
#
|
@@ -153,13 +153,13 @@ module ZMQMachine
|
|
153
153
|
rc = @raw_socket.recvmsgs parts, ZMQ::Util.nonblocking_flag
|
154
154
|
|
155
155
|
if ZMQ::Util.resultcode_ok?(rc)
|
156
|
-
|
156
|
+
@handler.on_readable self, parts
|
157
157
|
else
|
158
158
|
# verify errno corresponds to EAGAIN
|
159
159
|
if eagain?
|
160
160
|
more = false
|
161
161
|
elsif valid_socket_error?
|
162
|
-
|
162
|
+
@handler.on_readable_error self, rc
|
163
163
|
end
|
164
164
|
end
|
165
165
|
end
|
@@ -178,15 +178,6 @@ module ZMQMachine
|
|
178
178
|
|
179
179
|
private
|
180
180
|
|
181
|
-
def deliver parts, rc
|
182
|
-
if ZMQ::Util.resultcode_ok?(rc)
|
183
|
-
@handler.on_readable self, parts
|
184
|
-
else
|
185
|
-
# this branch is never called
|
186
|
-
@handler.on_readable_error self, rc
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
181
|
def eagain?
|
191
182
|
ZMQ::EAGAIN == ZMQ::Util.errno
|
192
183
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
|
2
|
+
module ZMQMachine
|
3
|
+
|
4
|
+
module Socket
|
5
|
+
|
6
|
+
# Two socket types (XREQ/XREP also called DEALER/ROUTER) have message
|
7
|
+
# parts for routing the message to the appropriate destination. This
|
8
|
+
# extra routing data is commonly called the routing envelope.
|
9
|
+
#
|
10
|
+
# The module provides logic for separating the routing envelope from
|
11
|
+
# the message body. The envelope is passed separately to the user's
|
12
|
+
# #on_readable method.
|
13
|
+
#
|
14
|
+
module EnvelopeHelp
|
15
|
+
|
16
|
+
# Convenience method for sending a multi-part message. The
|
17
|
+
# +messages+ and +envelope+ arguments must implement Enumerable.
|
18
|
+
#
|
19
|
+
def send_messages messages, envelope = nil
|
20
|
+
envelope ? @raw_socket.sendmsgs(envelope + messages) : @raw_socket.sendmsgs(messages)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Used by the reactor. Never called by user code.
|
24
|
+
#
|
25
|
+
def resume_read
|
26
|
+
rc = 0
|
27
|
+
more = true
|
28
|
+
|
29
|
+
while ZMQ::Util.resultcode_ok?(rc) && more
|
30
|
+
parts, envelope = [], []
|
31
|
+
rc = @raw_socket.recv_multipart parts, envelope, ZMQ::Util.nonblocking_flag
|
32
|
+
|
33
|
+
if ZMQ::Util.resultcode_ok?(rc)
|
34
|
+
@handler.on_readable self, parts, envelope
|
35
|
+
else
|
36
|
+
# verify errno corresponds to EAGAIN
|
37
|
+
if eagain?
|
38
|
+
more = false
|
39
|
+
elsif valid_socket_error?
|
40
|
+
@handler.on_readable_error self, rc
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end # module EnvelopeSeparation
|
47
|
+
|
48
|
+
end # Socket
|
49
|
+
end # ZMQMachine
|
data/lib/zm/sockets/pair.rb
CHANGED
data/lib/zm/sockets/pub.rb
CHANGED
data/lib/zm/sockets/rep.rb
CHANGED
@@ -74,6 +74,51 @@ module ZMQMachine
|
|
74
74
|
end
|
75
75
|
end # class Rep
|
76
76
|
|
77
|
+
class XRep
|
78
|
+
include ZMQMachine::Socket::Base
|
79
|
+
include ZMQMachine::Socket::EnvelopeHelp
|
80
|
+
|
81
|
+
def initialize context, handler
|
82
|
+
@poll_options = ZMQ::POLLIN
|
83
|
+
@kind = :xreply
|
84
|
+
|
85
|
+
super
|
86
|
+
end
|
87
|
+
|
88
|
+
# Attach a handler to the XREP socket.
|
89
|
+
#
|
90
|
+
# A XREP socket has no restrictions on the number of sends and
|
91
|
+
# recieves. Each send will silently prepend a message part to
|
92
|
+
# your outgoing data which the REQ/XREQ socket on the other end
|
93
|
+
# will use for matching up the transaction.
|
94
|
+
#
|
95
|
+
# This socket expects its +handler+ to
|
96
|
+
# implement at least the #on_readable method. This method
|
97
|
+
# will be called whenever a reply arrives. The #on_writable method
|
98
|
+
# will be called continually until the socket HWM is breached.
|
99
|
+
#
|
100
|
+
# For error handling purposes, the handler must also
|
101
|
+
# implement #on_readable_error.
|
102
|
+
#
|
103
|
+
def on_attach handler
|
104
|
+
raise ArgumentError, "Handler must implement an #on_readable method" unless handler.respond_to? :on_readable
|
105
|
+
raise ArgumentError, "Handler must implement an #on_readable_error method" unless handler.respond_to? :on_readable_error
|
106
|
+
raise ArgumentError, "Handler must implement an #on_writable method" unless handler.respond_to? :on_writable
|
107
|
+
raise ArgumentError, "Handler must implement an #on_writable_error method" unless handler.respond_to? :on_writable_error
|
108
|
+
super
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def allocate_socket context
|
115
|
+
sock = ZMQ::Socket.new context.pointer, ZMQ::XREP
|
116
|
+
sock
|
117
|
+
end
|
118
|
+
end # class XRep
|
119
|
+
|
120
|
+
Router = XRep # same thing, different name
|
121
|
+
|
77
122
|
end # module Socket
|
78
123
|
|
79
124
|
end # module ZMQMachine
|