cztop 1.0.0 → 1.1.0.pre1

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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/coverage.yml +20 -0
  3. data/.github/workflows/draft_api.yml +27 -0
  4. data/.github/workflows/{main.yml → stable_api.yml} +6 -6
  5. data/.rubocop.yml +175 -0
  6. data/CHANGES.md +8 -1
  7. data/Gemfile +5 -0
  8. data/README.md +3 -1
  9. data/ci/install-libczmq +22 -0
  10. data/ci/install-libzmq +22 -0
  11. data/cztop.gemspec +3 -2
  12. data/lib/cztop/actor.rb +55 -26
  13. data/lib/cztop/authenticator.rb +18 -9
  14. data/lib/cztop/beacon.rb +22 -10
  15. data/lib/cztop/cert_store.rb +8 -2
  16. data/lib/cztop/certificate.rb +47 -18
  17. data/lib/cztop/config/comments.rb +14 -3
  18. data/lib/cztop/config/serialization.rb +25 -5
  19. data/lib/cztop/config/traversing.rb +44 -13
  20. data/lib/cztop/config.rb +23 -9
  21. data/lib/cztop/frame.rb +23 -10
  22. data/lib/cztop/has_ffi_delegate.rb +11 -1
  23. data/lib/cztop/message/frames.rb +16 -2
  24. data/lib/cztop/message.rb +36 -22
  25. data/lib/cztop/metadata.rb +35 -24
  26. data/lib/cztop/monitor.rb +14 -5
  27. data/lib/cztop/poller/aggregated.rb +31 -15
  28. data/lib/cztop/poller/zmq.rb +25 -22
  29. data/lib/cztop/poller/zpoller.rb +18 -6
  30. data/lib/cztop/poller.rb +43 -18
  31. data/lib/cztop/polymorphic_zsock_methods.rb +6 -1
  32. data/lib/cztop/proxy.rb +34 -19
  33. data/lib/cztop/send_receive_methods.rb +5 -1
  34. data/lib/cztop/socket/types.rb +128 -22
  35. data/lib/cztop/socket.rb +23 -18
  36. data/lib/cztop/version.rb +5 -1
  37. data/lib/cztop/z85/padded.rb +12 -3
  38. data/lib/cztop/z85/pipe.rb +40 -17
  39. data/lib/cztop/z85.rb +17 -6
  40. data/lib/cztop/zap.rb +57 -32
  41. data/lib/cztop/zsock_options.rb +155 -122
  42. data/lib/cztop.rb +2 -1
  43. metadata +28 -10
  44. data/.ruby-version +0 -1
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  # This is the trivial poller based on zpoller. It only supports polling
3
5
  # for readability, but it also supports doing that on CLIENT/SERVER sockets,
@@ -5,6 +7,7 @@ module CZTop
5
7
  #
6
8
  # @see http://api.zeromq.org/czmq3-0:zpoller
7
9
  class Poller::ZPoller
10
+
8
11
  include HasFFIDelegate
9
12
  extend CZTop::HasFFIDelegate::ClassMethods
10
13
  include ::CZMQ::FFI
@@ -14,24 +17,26 @@ module CZTop
14
17
  # @param readers [Socket, Actor] any additional sockets to poll for input
15
18
  def initialize(reader, *readers)
16
19
  @sockets = {} # to keep references and return same instances
17
- ptr = Zpoller.new(reader,
18
- *readers.flat_map {|r| [ :pointer, r ] },
19
- :pointer, nil)
20
+ ptr = Zpoller.new(reader,
21
+ *readers.flat_map { |r| [:pointer, r] },
22
+ :pointer, nil)
20
23
  attach_ffi_delegate(ptr)
21
24
  remember_socket(reader)
22
25
  readers.each { |r| remember_socket(r) }
23
26
  end
24
27
 
28
+
25
29
  # Adds another reader socket to the poller.
26
30
  # @param reader [Socket, Actor] socket to poll for input
27
31
  # @return [void]
28
32
  # @raise [SystemCallError] if this fails
29
33
  def add(reader)
30
34
  rc = ffi_delegate.add(reader)
31
- raise_zmq_err("unable to add socket %p" % reader) if rc == -1
35
+ raise_zmq_err(format('unable to add socket %p', reader)) if rc == -1
32
36
  remember_socket(reader)
33
37
  end
34
38
 
39
+
35
40
  # Removes a reader socket from the poller.
36
41
  # @param reader [Socket, Actor] socket to remove
37
42
  # @return [void]
@@ -40,10 +45,11 @@ module CZTop
40
45
  # @raise [SystemCallError] if this fails for another reason
41
46
  def remove(reader)
42
47
  rc = ffi_delegate.remove(reader)
43
- raise_zmq_err("unable to remove socket %p" % reader) if rc == -1
48
+ raise_zmq_err(format('unable to remove socket %p', reader)) if rc == -1
44
49
  forget_socket(reader)
45
50
  end
46
51
 
52
+
47
53
  # Waits and returns the first socket that becomes readable.
48
54
  # @param timeout [Integer] how long to wait in ms, or 0 to avoid
49
55
  # blocking, or -1 to wait indefinitely
@@ -54,11 +60,13 @@ module CZTop
54
60
  ptr = ffi_delegate.wait(timeout)
55
61
  if ptr.null?
56
62
  raise Interrupt if ffi_delegate.terminated
63
+
57
64
  return nil
58
65
  end
59
- return socket_by_ptr(ptr)
66
+ socket_by_ptr(ptr)
60
67
  end
61
68
 
69
+
62
70
  # Tells the zpoller to ignore interrupts. By default, {#wait} will return
63
71
  # immediately if it detects an interrupt (when +zsys_interrupted+ is set
64
72
  # to something other than zero). Calling this method will supress this
@@ -68,6 +76,7 @@ module CZTop
68
76
  ffi_delegate.ignore_interrupts
69
77
  end
70
78
 
79
+
71
80
  # By default the poller stops if the process receives a SIGINT or SIGTERM
72
81
  # signal. This makes it impossible to shut-down message based architectures
73
82
  # like zactors. This method lets you switch off break handling. The default
@@ -91,6 +100,7 @@ module CZTop
91
100
  @sockets[socket.to_ptr.to_i] = socket
92
101
  end
93
102
 
103
+
94
104
  # Forgets the socket because it has been removed from the poller.
95
105
  # @param socket [Socket, Actor] the socket instance to forget
96
106
  # @return [void]
@@ -98,6 +108,7 @@ module CZTop
98
108
  @sockets.delete(socket.to_ptr.to_i)
99
109
  end
100
110
 
111
+
101
112
  # Gets the previously remembered socket associated to the given pointer.
102
113
  # @param ptr [FFI::Pointer] the pointer to a socket
103
114
  # @return [Socket, Actor] the socket associated to the given pointer
@@ -109,5 +120,6 @@ module CZTop
109
120
  # it ever returns a wrong pointer.
110
121
  raise_zmq_err("no socket known for pointer #{ptr.inspect}")
111
122
  end
123
+
112
124
  end
113
125
  end
data/lib/cztop/poller.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  # A non-trivial socket poller.
3
5
  #
@@ -9,23 +11,25 @@ module CZTop
9
11
  # * +zpoller+ can only poll for readability
10
12
  #
11
13
  class Poller
14
+
12
15
  include ::CZMQ::FFI
13
16
 
14
17
  # @param readers [Socket, Actor] sockets to poll for input
15
18
  def initialize(*readers)
16
- @sockets = {} # needed to return the same socket objects
17
- @events = {} # event masks for each socket
19
+ @sockets = {} # needed to return the same socket objects
20
+ @events = {} # event masks for each socket
18
21
  @poller_ptr = ZMQ.poller_new
19
22
  ObjectSpace.define_finalizer(@poller_ptr,
20
- Proc.new do
21
- ptr_ptr = ::FFI::MemoryPointer.new :pointer
22
- ptr_ptr.write_pointer(@poller_ptr)
23
- ZMQ.poller_destroy(ptr_ptr)
24
- end)
23
+ proc do
24
+ ptr_ptr = ::FFI::MemoryPointer.new :pointer
25
+ ptr_ptr.write_pointer(@poller_ptr)
26
+ ZMQ.poller_destroy(ptr_ptr)
27
+ end)
25
28
  @event_ptr = FFI::MemoryPointer.new(ZMQ::PollerEvent)
26
29
  readers.each { |r| add_reader(r) }
27
30
  end
28
31
 
32
+
29
33
  # Adds a socket to be polled for readability.
30
34
  # @param socket [Socket, Actor] the socket
31
35
  # @param events [Integer] bitwise-OR'd events you're interested in (see
@@ -34,11 +38,12 @@ module CZTop
34
38
  # @raise [ArgumentError] if it's not a socket
35
39
  def add(socket, events)
36
40
  ptr = ptr_for_socket(socket)
37
- rc = ZMQ.poller_add(@poller_ptr, ptr, nil, events)
41
+ rc = ZMQ.poller_add(@poller_ptr, ptr, nil, events)
38
42
  HasFFIDelegate.raise_zmq_err if rc == -1
39
43
  remember_socket(socket, events)
40
44
  end
41
45
 
46
+
42
47
  # Convenience method to register a socket for readability. See {#add}.
43
48
  # @param socket [Socket, Actor] the socket
44
49
  # @return [void]
@@ -46,6 +51,7 @@ module CZTop
46
51
  add(socket, ZMQ::POLLIN)
47
52
  end
48
53
 
54
+
49
55
  # Convenience method to register a socket for writability. See {#add}.
50
56
  # @param socket [Socket, Actor] the socket
51
57
  # @return [void]
@@ -53,6 +59,7 @@ module CZTop
53
59
  add(socket, ZMQ::POLLOUT)
54
60
  end
55
61
 
62
+
56
63
  # Modifies the events of interest for the given socket.
57
64
  # @param socket [Socket, Actor] the socket
58
65
  # @param events [Integer] events you're interested in (see constants in
@@ -61,11 +68,12 @@ module CZTop
61
68
  # @raise [ArgumentError] if it's not a socket
62
69
  def modify(socket, events)
63
70
  ptr = ptr_for_socket(socket)
64
- rc = ZMQ.poller_modify(@poller_ptr, ptr, events)
71
+ rc = ZMQ.poller_modify(@poller_ptr, ptr, events)
65
72
  HasFFIDelegate.raise_zmq_err if rc == -1
66
73
  remember_socket(socket, events)
67
74
  end
68
75
 
76
+
69
77
  # Removes a previously registered socket. Won't raise if you're
70
78
  # trying to remove a socket that's not registered.
71
79
  # @param socket [Socket, Actor] the socket
@@ -73,11 +81,12 @@ module CZTop
73
81
  # @raise [ArgumentError] if it's not a socket
74
82
  def remove(socket)
75
83
  ptr = ptr_for_socket(socket)
76
- rc = ZMQ.poller_remove(@poller_ptr, ptr)
84
+ rc = ZMQ.poller_remove(@poller_ptr, ptr)
77
85
  HasFFIDelegate.raise_zmq_err if rc == -1
78
86
  forget_socket(socket)
79
87
  end
80
88
 
89
+
81
90
  # Removes a reader socket that was registered for readability only.
82
91
  #
83
92
  # @param socket [Socket, Actor] the socket
@@ -88,9 +97,10 @@ module CZTop
88
97
  remove(socket)
89
98
  return
90
99
  end
91
- raise ArgumentError, "not registered for readability only: %p" % socket
100
+ raise ArgumentError, format('not registered for readability only: %p', socket)
92
101
  end
93
102
 
103
+
94
104
  # Removes a reader socket that was registered for writability only.
95
105
  #
96
106
  # @param socket [Socket, Actor] the socket
@@ -101,9 +111,10 @@ module CZTop
101
111
  remove(socket)
102
112
  return
103
113
  end
104
- raise ArgumentError, "not registered for writability only: %p" % socket
114
+ raise ArgumentError, format('not registered for writability only: %p', socket)
105
115
  end
106
116
 
117
+
107
118
  # Waits for registered sockets to become readable or writable, depending
108
119
  # on what you're interested in.
109
120
  #
@@ -116,7 +127,7 @@ module CZTop
116
127
  rc = ZMQ.poller_wait(@poller_ptr, @event_ptr, timeout)
117
128
  if rc == -1
118
129
  case CZMQ::FFI::Errors.errno
119
- # NOTE: ETIMEDOUT for backwards compatibility, although this API is
130
+ # NOTE: ETIMEDOUT for backwards compatibility, although this API is
120
131
  # still DRAFT.
121
132
  when Errno::EAGAIN::Errno, Errno::ETIMEDOUT::Errno
122
133
  return nil
@@ -124,9 +135,10 @@ module CZTop
124
135
  HasFFIDelegate.raise_zmq_err
125
136
  end
126
137
  end
127
- return Event.new(self, @event_ptr)
138
+ Event.new(self, @event_ptr)
128
139
  end
129
140
 
141
+
130
142
  # Simpler version of {#wait}, which just returns the first socket of
131
143
  # interest, if any. This is useful if you either have only reader sockets,
132
144
  # or only have writer sockets.
@@ -140,27 +152,30 @@ module CZTop
140
152
  return event.socket if event
141
153
  end
142
154
 
155
+
143
156
  # @param ptr [FFI::Pointer] pointer to the socket
144
157
  # @return [Socket, Actor] socket corresponding to given pointer
145
158
  # @raise [ArgumentError] if pointer is not known
146
159
  def socket_for_ptr(ptr)
147
160
  @sockets[ptr.to_i] or
148
- raise ArgumentError, "no socket known for pointer %p" % ptr
161
+ raise ArgumentError, format('no socket known for pointer %p', ptr)
149
162
  end
150
163
 
164
+
151
165
  # @return [Array<CZTop::Socket>] all sockets registered with this poller
152
166
  # @note The actual events registered for each sockets don't matter.
153
167
  def sockets
154
168
  @sockets.values
155
169
  end
156
170
 
171
+
157
172
  # Returns the event mask for the given, registered socket.
158
173
  # @param socket [Socket, Actor] which socket's events to return
159
174
  # @return [Integer] event mask for the given socket
160
175
  # @raise [ArgumentError] if socket is not registered
161
176
  def event_mask_for_socket(socket)
162
177
  @events[socket] or
163
- raise ArgumentError, "no event mask known for socket %p" % socket
178
+ raise ArgumentError, format('no event mask known for socket %p', socket)
164
179
  end
165
180
 
166
181
  private
@@ -170,17 +185,20 @@ module CZTop
170
185
  # @raise [ArgumentError] if argument is not a socket
171
186
  def ptr_for_socket(socket)
172
187
  raise ArgumentError unless socket.is_a?(Socket) || socket.is_a?(Actor)
188
+
173
189
  Zsock.resolve(socket)
174
190
  end
175
191
 
192
+
176
193
  # Keeps a reference to the given socket, and remembers its event mask.
177
194
  # @param socket [Socket, Actor] the socket
178
195
  # @param events [Integer] the event mask
179
196
  def remember_socket(socket, events)
180
197
  @sockets[ptr_for_socket(socket).to_i] = socket
181
- @events[socket] = events
198
+ @events[socket] = events
182
199
  end
183
200
 
201
+
184
202
  # Discards the referencel to the given socket, and forgets its event mask.
185
203
  # @param socket [Socket, Actor] the socket
186
204
  def forget_socket(socket)
@@ -188,33 +206,40 @@ module CZTop
188
206
  @events.delete(socket)
189
207
  end
190
208
 
209
+
191
210
  # Represents an event returned by {CZTop::Poller#wait}. This is useful to
192
211
  # find out whether the associated socket is now readable or writable, in
193
212
  # case you're interested in both. For a simpler variant, check out
194
213
  # {CZTop::Poller#simple_wait}.
195
214
  class Event
215
+
196
216
  # @param poller [CZTop::Poller] the poller instance
197
217
  # @param event_ptr [FFI::Pointer] pointer to the memory allocated for
198
218
  # the event's data (a +zmq_poller_event_t+)
199
219
  def initialize(poller, event_ptr)
200
- @poller = poller
220
+ @poller = poller
201
221
  @poller_event = ZMQ::PollerEvent.new(event_ptr)
202
222
  end
203
223
 
224
+
204
225
  # @return [Socket, Actor] the associated socket
205
226
  def socket
206
227
  @socket ||= @poller.socket_for_ptr(@poller_event[:socket])
207
228
  end
208
229
 
230
+
209
231
  # @return [Boolean] whether it's readable
210
232
  def readable?
211
233
  @poller_event.readable?
212
234
  end
213
235
 
236
+
214
237
  # @return [Boolean] whether it's writable
215
238
  def writable?
216
239
  @poller_event.writable?
217
240
  end
241
+
218
242
  end
243
+
219
244
  end
220
245
  end
@@ -1,24 +1,29 @@
1
- module CZTop
1
+ # frozen_string_literal: true
2
2
 
3
+ module CZTop
3
4
  # These are methods that can be used on a {Socket} as well as an {Actor}.
4
5
  # @see http://api.zeromq.org/czmq3-0:zsock
5
6
  module PolymorphicZsockMethods
7
+
6
8
  # Sends a signal.
7
9
  # @param status [Integer] signal (0-255)
8
10
  def signal(status = 0)
9
11
  ::CZMQ::FFI::Zsock.signal(ffi_delegate, status)
10
12
  end
11
13
 
14
+
12
15
  # Waits for a signal.
13
16
  # @return [Integer] the received signal
14
17
  def wait
15
18
  ::CZMQ::FFI::Zsock.wait(ffi_delegate)
16
19
  end
17
20
 
21
+
18
22
  # Set socket to use unbounded pipes (HWM=0); use this in cases when you are
19
23
  # totally certain the message volume can fit in memory.
20
24
  def set_unbounded
21
25
  ::CZMQ::FFI::Zsock.set_unbounded(ffi_delegate)
22
26
  end
27
+
23
28
  end
24
29
  end
data/lib/cztop/proxy.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module CZTop
2
4
  # Steerable proxy which switches messages between a frontend and a backend
3
5
  # socket.
@@ -6,11 +8,12 @@ module CZTop
6
8
  #
7
9
  # @see http://api.zeromq.org/czmq3-0:zproxy
8
10
  class Proxy
11
+
9
12
  include ::CZMQ::FFI
10
13
 
11
14
  # function pointer to the +zmonitor()+ function
12
15
  ZPROXY_FPTR = ::CZMQ::FFI.ffi_libraries.each do |dl|
13
- fptr = dl.find_function("zproxy")
16
+ fptr = dl.find_function('zproxy')
14
17
  break fptr if fptr
15
18
  end
16
19
  raise LoadError, "couldn't find zproxy()" if ZPROXY_FPTR.nil?
@@ -28,13 +31,15 @@ module CZTop
28
31
  @actor.terminate
29
32
  end
30
33
 
34
+
31
35
  # Enable verbose logging of commands and activity.
32
36
  # @return [void]
33
37
  def verbose!
34
- @actor << "VERBOSE"
38
+ @actor << 'VERBOSE'
35
39
  @actor.wait
36
40
  end
37
41
 
42
+
38
43
  # Returns a configurator object which you can use to configure the
39
44
  # frontend socket.
40
45
  # @return [Configurator] (memoized) frontend configurator
@@ -42,6 +47,7 @@ module CZTop
42
47
  @frontend ||= Configurator.new(self, :frontend)
43
48
  end
44
49
 
50
+
45
51
  # Returns a configurator object which you can use to configure the backend
46
52
  # socket.
47
53
  # @return [Configurator] (memoized) backend configurator
@@ -49,54 +55,59 @@ module CZTop
49
55
  @backend ||= Configurator.new(self, :backend)
50
56
  end
51
57
 
58
+
52
59
  # Captures all proxied messages and delivers them to a PULL socket bound
53
60
  # to the specified endpoint.
54
61
  # @note The PULL socket has to be bound before calling this method.
55
62
  # @param endpoint [String] the endpoint to which the PULL socket is bound to
56
63
  # @return [void]
57
64
  def capture(endpoint)
58
- @actor << ["CAPTURE", endpoint]
65
+ @actor << ['CAPTURE', endpoint]
59
66
  @actor.wait
60
67
  end
61
68
 
69
+
62
70
  # Pauses proxying of any messages.
63
71
  # @note This causes any messages to be queued up and potentialy hit the
64
72
  # high-water mark on the frontend or backend socket, causing messages to
65
73
  # be dropped or writing applications to block.
66
74
  # @return [void]
67
75
  def pause
68
- @actor << "PAUSE"
76
+ @actor << 'PAUSE'
69
77
  @actor.wait
70
78
  end
71
79
 
80
+
72
81
  # Resume proxying of messages.
73
82
  # @note This is only needed after a call to {#pause}, not to start the
74
83
  # proxy. Proxying starts as soon as the frontend and backend sockets are
75
84
  # properly attached.
76
85
  # @return [void]
77
86
  def resume
78
- @actor << "RESUME"
87
+ @actor << 'RESUME'
79
88
  @actor.wait
80
89
  end
81
90
 
91
+
82
92
  # Used to configure the socket on one side of a {Proxy}.
83
93
  class Configurator
94
+
84
95
  # @return [Array<Symbol>] supported socket types
85
96
  SOCKET_TYPES = %i[
86
97
  PAIR PUB SUB REQ REP
87
98
  DEALER ROUTER PULL PUSH
88
99
  XPUB XSUB
89
- ]
100
+ ].freeze
90
101
 
91
102
  # @param proxy [Proxy] the proxy instance
92
103
  # @param side [Symbol] :frontend or :backend
93
104
  def initialize(proxy, side)
94
105
  @proxy = proxy
95
- @side = case side
96
- when :frontend then "FRONTEND"
97
- when :backend then "BACKEND"
98
- else raise ArgumentError, "invalid side: #{side.inspect}"
99
- end
106
+ @side = case side
107
+ when :frontend then 'FRONTEND'
108
+ when :backend then 'BACKEND'
109
+ else raise ArgumentError, "invalid side: #{side.inspect}"
110
+ end
100
111
  end
101
112
 
102
113
  # @return [Proxy] the proxy this {Configurator} works on
@@ -111,27 +122,29 @@ module CZTop
111
122
  # @raise [ArgumentError] if the given socket type is invalid
112
123
  # @return [void]
113
124
  def bind(socket_type, endpoint)
114
- unless SOCKET_TYPES.include?(socket_type)
115
- raise ArgumentError, "invalid socket type: #{socket_type}"
116
- end
117
- @proxy.actor << [ @side, socket_type.to_s, endpoint ]
125
+ raise ArgumentError, "invalid socket type: #{socket_type}" unless SOCKET_TYPES.include?(socket_type)
126
+
127
+ @proxy.actor << [@side, socket_type.to_s, endpoint]
118
128
  @proxy.actor.wait
119
129
  end
120
130
 
131
+
121
132
  # Set ZAP domain for authentication.
122
133
  # @param domain [String] the ZAP domain
123
134
  def domain=(domain)
124
- @proxy.actor << [ "DOMAIN", @side, domain ]
135
+ @proxy.actor << ['DOMAIN', @side, domain]
125
136
  @proxy.actor.wait
126
137
  end
127
138
 
139
+
128
140
  # Configure PLAIN authentication on this socket.
129
141
  # @note You'll have to use a {CZTop::Authenticator}.
130
142
  def PLAIN_server!
131
- @proxy.actor << [ "PLAIN", @side ]
143
+ @proxy.actor << ['PLAIN', @side]
132
144
  @proxy.actor.wait
133
145
  end
134
146
 
147
+
135
148
  # Configure CURVE authentication on this socket.
136
149
  # @note You'll have to use a {CZTop::Authenticator}.
137
150
  # @param cert [Certificate] this server's certificate,
@@ -139,11 +152,13 @@ module CZTop
139
152
  def CURVE_server!(cert)
140
153
  public_key = cert.public_key
141
154
  secret_key = cert.secret_key or
142
- raise ArgumentError, "no secret key in certificate"
155
+ raise ArgumentError, 'no secret key in certificate'
143
156
 
144
- @proxy.actor << [ "CURVE", @side, public_key, secret_key ]
157
+ @proxy.actor << ['CURVE', @side, public_key, secret_key]
145
158
  @proxy.actor.wait
146
159
  end
160
+
147
161
  end
162
+
148
163
  end
149
164
  end
@@ -1,10 +1,12 @@
1
- module CZTop
1
+ # frozen_string_literal: true
2
2
 
3
+ module CZTop
3
4
  # These are methods that can be used on a {Socket} as well as an {Actor},
4
5
  # but actually just pass through to methods of {Message} (which take
5
6
  # a polymorphic reference, in Ruby as well as in C).
6
7
  # @see http://api.zeromq.org/czmq3-0:zmsg
7
8
  module SendReceiveMethods
9
+
8
10
  # Sends a message.
9
11
  #
10
12
  # @param message [Message, String, Array<parts>] the message to send
@@ -20,6 +22,7 @@ module CZTop
20
22
  self
21
23
  end
22
24
 
25
+
23
26
  # Receives a message.
24
27
  #
25
28
  # @return [Message]
@@ -31,5 +34,6 @@ module CZTop
31
34
  def receive
32
35
  Message.receive_from(self)
33
36
  end
37
+
34
38
  end
35
39
  end