cztop 2.0.2 → 2.0.4
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/CHANGES.md +29 -0
- data/README.md +24 -19
- data/lib/cztop/curve/auth.rb +13 -6
- data/lib/cztop/curve.rb +1 -1
- data/lib/cztop/ffi.rb +37 -23
- data/lib/cztop/monitor.rb +5 -6
- data/lib/cztop/socket/dealer.rb +1 -1
- data/lib/cztop/socket/pair.rb +1 -1
- data/lib/cztop/socket/pub.rb +1 -1
- data/lib/cztop/socket/pull.rb +1 -1
- data/lib/cztop/socket/push.rb +1 -1
- data/lib/cztop/socket/readable.rb +6 -1
- data/lib/cztop/socket/rep.rb +1 -1
- data/lib/cztop/socket/req.rb +1 -1
- data/lib/cztop/socket/router.rb +1 -1
- data/lib/cztop/socket/stream.rb +1 -1
- data/lib/cztop/socket/sub.rb +1 -1
- data/lib/cztop/socket/writable.rb +7 -5
- data/lib/cztop/socket/xpub.rb +1 -1
- data/lib/cztop/socket/xsub.rb +1 -1
- data/lib/cztop/socket.rb +1 -1
- data/lib/cztop/version.rb +1 -1
- data/lib/cztop/zsock_options.rb +9 -1
- data/lib/cztop.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e3c85c43224c3d6b657fdc1178c3dc145bae175ab4febd29194717074509c3e0
|
|
4
|
+
data.tar.gz: 70b7dd7ed91196fa9c24bd911be6d30f5c5f9c3b5a55f70c8a78f4cfbbb8d74c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 34a251ab8bd12c5220dea4627f7cf3823d0aaf590da6875ba182d92107defd17a68100e638d8feca6b348608585d80f0002af77dfb8f34c68cc7d00fd5af2cb0
|
|
7
|
+
data.tar.gz: 70ee8e3f715ab38d820e48919e0c7e8608cdcd836383ed969ec712447b14db74b7706cc9b7e86d40f9c1b71ec2d2300a3287cdbc39edbb6270e1e00576e6d9b5
|
data/CHANGES.md
CHANGED
|
@@ -1,3 +1,32 @@
|
|
|
1
|
+
## [Unreleased]
|
|
2
|
+
|
|
3
|
+
2.0.4
|
|
4
|
+
-----
|
|
5
|
+
|
|
6
|
+
* Prevent socket double destruction by removing finalizers before native cleanup
|
|
7
|
+
and sharing their pointer holders with explicit destruction
|
|
8
|
+
* Prevent monitor double destruction with the same finalizer cleanup ordering
|
|
9
|
+
and shared pointer holder
|
|
10
|
+
* Keep parent messages alive while borrowed frames remain live, and reject frame
|
|
11
|
+
access after message ownership is transferred
|
|
12
|
+
|
|
13
|
+
2.0.3
|
|
14
|
+
-----
|
|
15
|
+
|
|
16
|
+
* Port specs to named `Minitest::Spec` subclasses with ordinary Ruby helpers
|
|
17
|
+
* Add regression coverage for native library loading and fallback
|
|
18
|
+
* Raise native send/receive errors immediately instead of waiting for readiness
|
|
19
|
+
* Raise `IO::EAGAINWaitReadable`/`IO::EAGAINWaitWritable` when nonblocking I/O
|
|
20
|
+
would block
|
|
21
|
+
* Convert all multipart message parts before sending the first frame
|
|
22
|
+
* Avoid an extra array allocation for scalar sends without modifying caller arrays
|
|
23
|
+
* Free native identity strings and messages retained after failed sends
|
|
24
|
+
* Reject endpoint and subscription operations on closed sockets, and receive
|
|
25
|
+
operations on closed monitors
|
|
26
|
+
* Close the CURVE authentication socket in its responder thread during shutdown
|
|
27
|
+
* Fix linger documentation to use seconds
|
|
28
|
+
* Clean up benchmark socket lifetimes and refresh measurements and README
|
|
29
|
+
|
|
1
30
|
2.0.2
|
|
2
31
|
-----
|
|
3
32
|
|
data/README.md
CHANGED
|
@@ -5,17 +5,17 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
[](https://www.ruby-lang.org)
|
|
7
7
|
|
|
8
|
-
Ruby FFI binding for [CZMQ](
|
|
8
|
+
Ruby FFI binding for [CZMQ](https://github.com/zeromq/czmq) and [ZeroMQ](https://zeromq.org/), with support for threads, Fiber Scheduler, and CURVE encryption.
|
|
9
9
|
|
|
10
|
-
> **
|
|
10
|
+
> **310k msg/s** inproc throughput (64 B) | **61 µs** Async roundtrip latency
|
|
11
11
|
|
|
12
12
|
---
|
|
13
13
|
|
|
14
14
|
## Highlights
|
|
15
15
|
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **Ruby
|
|
16
|
+
- **Socket types:** REQ/REP, PUB/SUB, PUSH/PULL, DEALER/ROUTER, XPUB/XSUB, PAIR, STREAM
|
|
17
|
+
- **Fibers and threads:** works with [async](https://github.com/socketry/async) and plain threads
|
|
18
|
+
- **Ruby API:** messages as `Array<String>`, errors as exceptions, timeouts as `IO::TimeoutError`
|
|
19
19
|
|
|
20
20
|
## Install
|
|
21
21
|
|
|
@@ -33,17 +33,21 @@ Then add the gem:
|
|
|
33
33
|
|
|
34
34
|
```sh
|
|
35
35
|
gem install cztop
|
|
36
|
-
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or add it to your Gemfile:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
37
41
|
gem 'cztop'
|
|
38
42
|
```
|
|
39
43
|
|
|
40
44
|
## Learning ZeroMQ
|
|
41
45
|
|
|
42
|
-
New to ZeroMQ? See [ZGUIDE_SUMMARY.md](ZGUIDE_SUMMARY.md)
|
|
46
|
+
New to ZeroMQ? See [ZGUIDE_SUMMARY.md](ZGUIDE_SUMMARY.md) for messaging patterns and working CZTop examples.
|
|
43
47
|
|
|
44
48
|
## Quick Start
|
|
45
49
|
|
|
46
|
-
###
|
|
50
|
+
### REQ / REP
|
|
47
51
|
|
|
48
52
|
```ruby
|
|
49
53
|
require 'cztop'
|
|
@@ -63,7 +67,7 @@ Async do |task|
|
|
|
63
67
|
end
|
|
64
68
|
```
|
|
65
69
|
|
|
66
|
-
###
|
|
70
|
+
### PUB / SUB
|
|
67
71
|
|
|
68
72
|
```ruby
|
|
69
73
|
Async do |task|
|
|
@@ -78,7 +82,7 @@ Async do |task|
|
|
|
78
82
|
end
|
|
79
83
|
```
|
|
80
84
|
|
|
81
|
-
###
|
|
85
|
+
### PUSH / PULL (Pipeline)
|
|
82
86
|
|
|
83
87
|
```ruby
|
|
84
88
|
Async do
|
|
@@ -95,7 +99,8 @@ end
|
|
|
95
99
|
| Pattern | Classes | Direction |
|
|
96
100
|
|---------|---------|-----------|
|
|
97
101
|
| Request/Reply | `REQ`, `REP` | bidirectional |
|
|
98
|
-
| Publish/Subscribe | `PUB`, `SUB
|
|
102
|
+
| Publish/Subscribe | `PUB`, `SUB` | unidirectional |
|
|
103
|
+
| Subscription forwarding | `XPUB`, `XSUB` | bidirectional |
|
|
99
104
|
| Pipeline | `PUSH`, `PULL` | unidirectional |
|
|
100
105
|
| Routing | `DEALER`, `ROUTER` | bidirectional |
|
|
101
106
|
| Exclusive pair | `PAIR` | bidirectional |
|
|
@@ -105,23 +110,23 @@ All classes live under `CZTop::Socket::`.
|
|
|
105
110
|
|
|
106
111
|
## Performance
|
|
107
112
|
|
|
108
|
-
Benchmarked with benchmark-ips on Linux x86_64 (CZMQ 4.2.1, ZMQ 4.3.5, Ruby 4.0.
|
|
113
|
+
Benchmarked with benchmark-ips on Linux x86_64 (CZMQ 4.2.1, ZMQ 4.3.5, Ruby 4.0.6 +YJIT):
|
|
109
114
|
|
|
110
|
-
#### Throughput (
|
|
115
|
+
#### Throughput (PUSH/PULL, 64 B messages)
|
|
111
116
|
|
|
112
117
|
| | inproc | ipc | tcp |
|
|
113
118
|
|---|--------|-----|-----|
|
|
114
|
-
| **Async** |
|
|
115
|
-
| **Threads** |
|
|
119
|
+
| **Async** | 278k/s | 18.3k/s | 15.8k/s |
|
|
120
|
+
| **Threads** | 310k/s | 18.3k/s | 16.2k/s |
|
|
116
121
|
|
|
117
|
-
#### Latency (
|
|
122
|
+
#### Latency (REQ/REP roundtrip)
|
|
118
123
|
|
|
119
124
|
| | inproc | ipc | tcp |
|
|
120
125
|
|---|--------|-----|-----|
|
|
121
|
-
| **Async** |
|
|
122
|
-
| **Threads** |
|
|
126
|
+
| **Async** | 60.7 µs | 112.6 µs | 127.8 µs |
|
|
127
|
+
| **Threads** | 74.9 µs | 109.2 µs | 119.6 µs |
|
|
123
128
|
|
|
124
|
-
|
|
129
|
+
See [bench/README.md](bench/README.md) for full results, measurement details, and scripts.
|
|
125
130
|
|
|
126
131
|
## API Reference
|
|
127
132
|
|
data/lib/cztop/curve/auth.rb
CHANGED
|
@@ -29,7 +29,9 @@ module CZTop
|
|
|
29
29
|
@allow_any = allow_any
|
|
30
30
|
@zap = CZTop::Socket::REP.new
|
|
31
31
|
@zap.linger = 0
|
|
32
|
+
@zap.recv_timeout = 0.1
|
|
32
33
|
@zap.bind('inproc://zeromq.zap.01')
|
|
34
|
+
@stopping = false
|
|
33
35
|
@thread = Thread.new { run }
|
|
34
36
|
ObjectSpace.define_finalizer(self, self.class._poststop(@thread))
|
|
35
37
|
end
|
|
@@ -60,8 +62,9 @@ module CZTop
|
|
|
60
62
|
#
|
|
61
63
|
def stop
|
|
62
64
|
ObjectSpace.undefine_finalizer(self)
|
|
63
|
-
@
|
|
64
|
-
@thread.join
|
|
65
|
+
@stopping = true
|
|
66
|
+
@thread.join
|
|
67
|
+
nil
|
|
65
68
|
end
|
|
66
69
|
|
|
67
70
|
# @api private
|
|
@@ -75,8 +78,12 @@ module CZTop
|
|
|
75
78
|
private
|
|
76
79
|
|
|
77
80
|
def run
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
until @stopping
|
|
82
|
+
begin
|
|
83
|
+
msg = @zap.receive
|
|
84
|
+
rescue IO::TimeoutError
|
|
85
|
+
next
|
|
86
|
+
end
|
|
80
87
|
# ZAP request: [version, request_id, domain, address, identity, mechanism, credential]
|
|
81
88
|
version = msg[0]
|
|
82
89
|
request_id = msg[1]
|
|
@@ -90,8 +97,8 @@ module CZTop
|
|
|
90
97
|
|
|
91
98
|
@zap.__send__(:send, [version, request_id, status, '', '', ''])
|
|
92
99
|
end
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
ensure
|
|
101
|
+
@zap.close
|
|
95
102
|
end
|
|
96
103
|
|
|
97
104
|
end
|
data/lib/cztop/curve.rb
CHANGED
|
@@ -6,7 +6,7 @@ module CZTop
|
|
|
6
6
|
#
|
|
7
7
|
# Provides keypair generation, key derivation, and Z85 encoding/decoding.
|
|
8
8
|
# CURVE options are applied to sockets via the +curve:+ keyword argument
|
|
9
|
-
# in socket constructors
|
|
9
|
+
# in socket constructors; there are no public CURVE methods on Socket.
|
|
10
10
|
#
|
|
11
11
|
module CURVE
|
|
12
12
|
|
data/lib/cztop/ffi.rb
CHANGED
|
@@ -6,6 +6,8 @@ module CZMQ
|
|
|
6
6
|
module FFI
|
|
7
7
|
extend ::FFI::Library
|
|
8
8
|
|
|
9
|
+
# Runtime packages may only include versioned sonames. Keep each library's
|
|
10
|
+
# alternatives in one array so FFI can fall back to platform-specific names.
|
|
9
11
|
ffi_lib ['libzmq.so.5', 'libzmq'], ['libczmq.so.4', 'libczmq']
|
|
10
12
|
|
|
11
13
|
# -----------------------------------------------------------------
|
|
@@ -122,6 +124,7 @@ module CZMQ
|
|
|
122
124
|
# -----------------------------------------------------------------
|
|
123
125
|
attach_function :zstr_send, [:pointer, :string], :int, **opts
|
|
124
126
|
attach_function :zstr_sendm, [:pointer, :string], :int, **opts
|
|
127
|
+
attach_function :zstr_free, [:pointer], :void
|
|
125
128
|
|
|
126
129
|
# -----------------------------------------------------------------
|
|
127
130
|
# zsock_wait (used for zactor START synchronization)
|
|
@@ -169,8 +172,8 @@ module CZMQ
|
|
|
169
172
|
end
|
|
170
173
|
|
|
171
174
|
module ClassMethods
|
|
172
|
-
def prevent_leak(ptr, destroy_fn)
|
|
173
|
-
prevent_leak_ptr = ::FFI::MemoryPointer.new(:pointer)
|
|
175
|
+
def prevent_leak(ptr, destroy_fn, ptr_ref: nil)
|
|
176
|
+
prevent_leak_ptr = ptr_ref || ::FFI::MemoryPointer.new(:pointer)
|
|
174
177
|
prevent_leak_ptr.write_pointer(ptr)
|
|
175
178
|
prevent_leak_fn = destroy_fn
|
|
176
179
|
->(id) { CZMQ::FFI.__send__(prevent_leak_fn, prevent_leak_ptr) }
|
|
@@ -261,10 +264,11 @@ module CZMQ
|
|
|
261
264
|
|
|
262
265
|
def initialize(type)
|
|
263
266
|
@ptr = CZMQ::FFI.zsock_new(type)
|
|
267
|
+
@ptr_ref = ::FFI::MemoryPointer.new(:pointer)
|
|
264
268
|
@moved = false
|
|
265
269
|
unless @ptr.null?
|
|
266
270
|
ObjectSpace.define_finalizer(self,
|
|
267
|
-
self.class.prevent_leak(@ptr, :zsock_destroy))
|
|
271
|
+
self.class.prevent_leak(@ptr, :zsock_destroy, ptr_ref: @ptr_ref))
|
|
268
272
|
end
|
|
269
273
|
end
|
|
270
274
|
|
|
@@ -284,11 +288,13 @@ module CZMQ
|
|
|
284
288
|
|
|
285
289
|
def self._wrap(ptr)
|
|
286
290
|
obj = allocate
|
|
291
|
+
ptr_ref = ::FFI::MemoryPointer.new(:pointer)
|
|
287
292
|
obj.instance_variable_set(:@ptr, ptr)
|
|
293
|
+
obj.instance_variable_set(:@ptr_ref, ptr_ref)
|
|
288
294
|
obj.instance_variable_set(:@moved, false)
|
|
289
295
|
unless ptr.null?
|
|
290
296
|
ObjectSpace.define_finalizer(obj,
|
|
291
|
-
prevent_leak(ptr, :zsock_destroy))
|
|
297
|
+
prevent_leak(ptr, :zsock_destroy, ptr_ref: ptr_ref))
|
|
292
298
|
end
|
|
293
299
|
obj
|
|
294
300
|
end
|
|
@@ -296,40 +302,39 @@ module CZMQ
|
|
|
296
302
|
|
|
297
303
|
# Instance methods
|
|
298
304
|
def endpoint
|
|
299
|
-
CZMQ::FFI.zsock_endpoint(
|
|
305
|
+
CZMQ::FFI.zsock_endpoint(to_ptr)
|
|
300
306
|
end
|
|
301
307
|
|
|
302
308
|
def connect(format, *args)
|
|
303
|
-
CZMQ::FFI.zsock_connect(
|
|
309
|
+
CZMQ::FFI.zsock_connect(to_ptr, format, *args)
|
|
304
310
|
end
|
|
305
311
|
|
|
306
312
|
def disconnect(format, *args)
|
|
307
|
-
CZMQ::FFI.zsock_disconnect(
|
|
313
|
+
CZMQ::FFI.zsock_disconnect(to_ptr, format, *args)
|
|
308
314
|
end
|
|
309
315
|
|
|
310
316
|
def bind(format, *args)
|
|
311
|
-
CZMQ::FFI.zsock_bind(
|
|
317
|
+
CZMQ::FFI.zsock_bind(to_ptr, format, *args)
|
|
312
318
|
end
|
|
313
319
|
|
|
314
320
|
def unbind(format, *args)
|
|
315
|
-
CZMQ::FFI.zsock_unbind(
|
|
321
|
+
CZMQ::FFI.zsock_unbind(to_ptr, format, *args)
|
|
316
322
|
end
|
|
317
323
|
|
|
318
324
|
def destroy
|
|
319
325
|
return if @moved
|
|
320
|
-
ptr_ptr = ::FFI::MemoryPointer.new(:pointer)
|
|
321
|
-
ptr_ptr.write_pointer(@ptr)
|
|
322
|
-
CZMQ::FFI.zsock_destroy(ptr_ptr)
|
|
323
326
|
@moved = true
|
|
324
327
|
ObjectSpace.undefine_finalizer(self)
|
|
328
|
+
# Native destruction releases the GVL and nulls the finalizer's reference.
|
|
329
|
+
CZMQ::FFI.zsock_destroy(@ptr_ref)
|
|
325
330
|
end
|
|
326
331
|
|
|
327
332
|
def set_subscribe(prefix)
|
|
328
|
-
CZMQ::FFI.zsock_set_subscribe(
|
|
333
|
+
CZMQ::FFI.zsock_set_subscribe(to_ptr, prefix)
|
|
329
334
|
end
|
|
330
335
|
|
|
331
336
|
def set_unsubscribe(prefix)
|
|
332
|
-
CZMQ::FFI.zsock_set_unsubscribe(
|
|
337
|
+
CZMQ::FFI.zsock_set_unsubscribe(to_ptr, prefix)
|
|
333
338
|
end
|
|
334
339
|
|
|
335
340
|
# Class methods that take a zsock pointer (or wrapper with to_ptr)
|
|
@@ -423,9 +428,15 @@ module CZMQ
|
|
|
423
428
|
# Override Object#send: int zmsg_send(zmsg_t **self_p, void *dest)
|
|
424
429
|
# Called as: Zmsg.send(zmsg_wrapper_or_ptr, destination)
|
|
425
430
|
def self.send(msg, dest)
|
|
426
|
-
msg_ptr = msg.respond_to?(:__ptr_give_ref) ? msg.__ptr_give_ref : msg
|
|
427
431
|
dest_ptr = dest.respond_to?(:to_ptr) ? dest.to_ptr : dest
|
|
428
|
-
|
|
432
|
+
msg_ptr = msg.respond_to?(:__ptr_give_ref) ? msg.__ptr_give_ref : msg
|
|
433
|
+
rc = CZMQ::FFI.zmsg_send(msg_ptr, dest_ptr)
|
|
434
|
+
unless rc.zero?
|
|
435
|
+
errno = CZMQ::FFI::Errors.errno
|
|
436
|
+
CZMQ::FFI.zmsg_destroy(msg_ptr) if msg.respond_to?(:__ptr_give_ref)
|
|
437
|
+
CZTop::HasFFIDelegate.raise_zmq_err(errno: errno)
|
|
438
|
+
end
|
|
439
|
+
rc
|
|
429
440
|
end
|
|
430
441
|
|
|
431
442
|
def self.recv(source)
|
|
@@ -437,17 +448,17 @@ module CZMQ
|
|
|
437
448
|
# Appends a Ruby string directly without intermediate MemoryPointer copy.
|
|
438
449
|
# Uses :buffer_in to pass the string's internal buffer pointer to C.
|
|
439
450
|
def add_buffer(str)
|
|
440
|
-
CZMQ::FFI.zmsg_addmem_s(
|
|
451
|
+
CZMQ::FFI.zmsg_addmem_s(to_ptr, str, str.bytesize)
|
|
441
452
|
end
|
|
442
453
|
|
|
443
454
|
def first
|
|
444
|
-
ptr = CZMQ::FFI.zmsg_first(
|
|
455
|
+
ptr = CZMQ::FFI.zmsg_first(to_ptr)
|
|
445
456
|
return nil if ptr.null?
|
|
446
457
|
_borrowed_frame(ptr)
|
|
447
458
|
end
|
|
448
459
|
|
|
449
460
|
def next
|
|
450
|
-
ptr = CZMQ::FFI.zmsg_next(
|
|
461
|
+
ptr = CZMQ::FFI.zmsg_next(to_ptr)
|
|
451
462
|
return nil if ptr.null?
|
|
452
463
|
_borrowed_frame(ptr)
|
|
453
464
|
end
|
|
@@ -456,27 +467,30 @@ module CZMQ
|
|
|
456
467
|
|
|
457
468
|
# Returns a Zframe that does NOT own the pointer (borrowed from zmsg).
|
|
458
469
|
def _borrowed_frame(ptr)
|
|
459
|
-
Zframe._from_ptr(ptr,
|
|
470
|
+
Zframe._from_ptr(ptr, owner: self)
|
|
460
471
|
end
|
|
461
472
|
end
|
|
462
473
|
|
|
463
474
|
# -----------------------------------------------------------------
|
|
464
|
-
# Zframe (lightweight
|
|
475
|
+
# Zframe (lightweight; only used for borrowed frames from Zmsg)
|
|
465
476
|
# -----------------------------------------------------------------
|
|
466
477
|
class Zframe
|
|
467
|
-
# Wraps a borrowed zframe_t pointer
|
|
478
|
+
# Wraps a borrowed zframe_t pointer and retains its owning message.
|
|
468
479
|
#
|
|
469
|
-
def self._from_ptr(ptr,
|
|
480
|
+
def self._from_ptr(ptr, owner:)
|
|
470
481
|
obj = allocate
|
|
471
482
|
obj.instance_variable_set(:@ptr, ptr)
|
|
483
|
+
obj.instance_variable_set(:@owner, owner)
|
|
472
484
|
obj
|
|
473
485
|
end
|
|
474
486
|
|
|
475
487
|
def data
|
|
488
|
+
@owner.to_ptr
|
|
476
489
|
CZMQ::FFI.zframe_data(@ptr)
|
|
477
490
|
end
|
|
478
491
|
|
|
479
492
|
def size
|
|
493
|
+
@owner.to_ptr
|
|
480
494
|
CZMQ::FFI.zframe_size(@ptr)
|
|
481
495
|
end
|
|
482
496
|
end
|
data/lib/cztop/monitor.rb
CHANGED
|
@@ -46,9 +46,9 @@ module CZTop
|
|
|
46
46
|
|
|
47
47
|
@closed = false
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
ObjectSpace.define_finalizer(self, self.class._make_destructor(
|
|
49
|
+
@actor_ref = ::FFI::MemoryPointer.new(:pointer)
|
|
50
|
+
@actor_ref.write_pointer(@actor_ptr)
|
|
51
|
+
ObjectSpace.define_finalizer(self, self.class._make_destructor(@actor_ref))
|
|
52
52
|
|
|
53
53
|
CZMQ::FFI.zstr_send(@actor_ptr, 'VERBOSE') if verbose
|
|
54
54
|
|
|
@@ -69,6 +69,7 @@ module CZTop
|
|
|
69
69
|
# @return [Event, nil] the event, or nil on timeout
|
|
70
70
|
#
|
|
71
71
|
def receive(timeout: 0.1)
|
|
72
|
+
raise IOError, 'monitor is closed' if @closed
|
|
72
73
|
CZMQ::FFI.zsock_set_rcvtimeo(@actor_ptr, (timeout * 1000).to_i)
|
|
73
74
|
|
|
74
75
|
zmsg_ptr = CZMQ::FFI.zmsg_recv(@actor_ptr)
|
|
@@ -102,11 +103,9 @@ module CZTop
|
|
|
102
103
|
def close
|
|
103
104
|
return if @closed
|
|
104
105
|
|
|
105
|
-
pp = ::FFI::MemoryPointer.new(:pointer)
|
|
106
|
-
pp.write_pointer(@actor_ptr)
|
|
107
|
-
CZMQ::FFI.zactor_destroy(pp)
|
|
108
106
|
@closed = true
|
|
109
107
|
ObjectSpace.undefine_finalizer(self)
|
|
108
|
+
CZMQ::FFI.zactor_destroy(@actor_ref)
|
|
110
109
|
end
|
|
111
110
|
|
|
112
111
|
|
data/lib/cztop/socket/dealer.rb
CHANGED
|
@@ -13,7 +13,7 @@ module CZTop
|
|
|
13
13
|
|
|
14
14
|
# @param endpoints [String] endpoints to connect to
|
|
15
15
|
# @param curve [Hash, nil] CURVE encryption options
|
|
16
|
-
# @param linger [
|
|
16
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
17
17
|
#
|
|
18
18
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
19
19
|
super
|
data/lib/cztop/socket/pair.rb
CHANGED
|
@@ -13,7 +13,7 @@ module CZTop
|
|
|
13
13
|
|
|
14
14
|
# @param endpoints [String] endpoints to connect to
|
|
15
15
|
# @param curve [Hash, nil] CURVE encryption options
|
|
16
|
-
# @param linger [
|
|
16
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
17
17
|
#
|
|
18
18
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
19
19
|
super
|
data/lib/cztop/socket/pub.rb
CHANGED
|
@@ -12,7 +12,7 @@ module CZTop
|
|
|
12
12
|
|
|
13
13
|
# @param endpoints [String] endpoints to bind to
|
|
14
14
|
# @param curve [Hash, nil] CURVE encryption options
|
|
15
|
-
# @param linger [
|
|
15
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
16
16
|
#
|
|
17
17
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
18
18
|
super
|
data/lib/cztop/socket/pull.rb
CHANGED
|
@@ -12,7 +12,7 @@ module CZTop
|
|
|
12
12
|
|
|
13
13
|
# @param endpoints [String] endpoints to bind to
|
|
14
14
|
# @param curve [Hash, nil] CURVE encryption options
|
|
15
|
-
# @param linger [
|
|
15
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
16
16
|
#
|
|
17
17
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
18
18
|
super
|
data/lib/cztop/socket/push.rb
CHANGED
|
@@ -12,7 +12,7 @@ module CZTop
|
|
|
12
12
|
|
|
13
13
|
# @param endpoints [String] endpoints to connect to
|
|
14
14
|
# @param curve [Hash, nil] CURVE encryption options
|
|
15
|
-
# @param linger [
|
|
15
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
16
16
|
#
|
|
17
17
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
18
18
|
super
|
|
@@ -18,6 +18,7 @@ module CZTop
|
|
|
18
18
|
# Fast path: nonblock recv (no GVL release)
|
|
19
19
|
parts = recv_nonblock
|
|
20
20
|
return parts if parts
|
|
21
|
+
raise IO::EAGAINWaitReadable if read_timeout == 0
|
|
21
22
|
|
|
22
23
|
# Slow path: FD poll → blocking recv
|
|
23
24
|
wait_readable
|
|
@@ -56,7 +57,11 @@ module CZTop
|
|
|
56
57
|
def recv_nonblock
|
|
57
58
|
sock_ptr = to_ptr
|
|
58
59
|
frame = CZMQ::FFI.zframe_recv_nowait(sock_ptr)
|
|
59
|
-
|
|
60
|
+
if frame.null?
|
|
61
|
+
errno = CZMQ::FFI::Errors.errno
|
|
62
|
+
HasFFIDelegate.raise_zmq_err(errno: errno) unless errno == Errno::EAGAIN::Errno
|
|
63
|
+
return nil
|
|
64
|
+
end
|
|
60
65
|
|
|
61
66
|
pp = _zframe_pp
|
|
62
67
|
parts = []
|
data/lib/cztop/socket/rep.rb
CHANGED
|
@@ -13,7 +13,7 @@ module CZTop
|
|
|
13
13
|
|
|
14
14
|
# @param endpoints [String] endpoints to bind to
|
|
15
15
|
# @param curve [Hash, nil] CURVE encryption options
|
|
16
|
-
# @param linger [
|
|
16
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
17
17
|
#
|
|
18
18
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
19
19
|
super
|
data/lib/cztop/socket/req.rb
CHANGED
|
@@ -13,7 +13,7 @@ module CZTop
|
|
|
13
13
|
|
|
14
14
|
# @param endpoints [String] endpoints to connect to
|
|
15
15
|
# @param curve [Hash, nil] CURVE encryption options
|
|
16
|
-
# @param linger [
|
|
16
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
17
17
|
#
|
|
18
18
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
19
19
|
super
|
data/lib/cztop/socket/router.rb
CHANGED
|
@@ -13,7 +13,7 @@ module CZTop
|
|
|
13
13
|
|
|
14
14
|
# @param endpoints [String] endpoints to bind to
|
|
15
15
|
# @param curve [Hash, nil] CURVE encryption options
|
|
16
|
-
# @param linger [
|
|
16
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
17
17
|
#
|
|
18
18
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
19
19
|
super
|
data/lib/cztop/socket/stream.rb
CHANGED
|
@@ -14,7 +14,7 @@ module CZTop
|
|
|
14
14
|
|
|
15
15
|
# @param endpoints [String] endpoints to connect to
|
|
16
16
|
# @param curve [Hash, nil] CURVE encryption options
|
|
17
|
-
# @param linger [
|
|
17
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
18
18
|
#
|
|
19
19
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
20
20
|
super
|
data/lib/cztop/socket/sub.rb
CHANGED
|
@@ -17,7 +17,7 @@ module CZTop
|
|
|
17
17
|
# @param prefix [String, nil] subscription prefix; defaults to no
|
|
18
18
|
# subscription. Pass {EVERYTHING} (+""+) to subscribe to everything.
|
|
19
19
|
# @param curve [Hash, nil] CURVE encryption options
|
|
20
|
-
# @param linger [
|
|
20
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
21
21
|
#
|
|
22
22
|
def initialize(endpoints = nil, prefix: nil, curve: nil, linger: 0)
|
|
23
23
|
super(endpoints, curve: curve, linger: linger)
|
|
@@ -16,18 +16,19 @@ module CZTop
|
|
|
16
16
|
# @return [self]
|
|
17
17
|
#
|
|
18
18
|
def send(message)
|
|
19
|
-
parts = message.is_a?(Array) ? message : [message]
|
|
19
|
+
parts = message.is_a?(Array) ? message.map(&:to_s) : [message.to_s]
|
|
20
20
|
raise ArgumentError, 'message has no parts' if parts.empty?
|
|
21
21
|
|
|
22
22
|
# Fast path: nonblock send (no GVL release)
|
|
23
23
|
return self if send_nonblock(parts)
|
|
24
|
+
raise IO::EAGAINWaitWritable if write_timeout == 0
|
|
24
25
|
|
|
25
26
|
# Slow path: FD poll → blocking send
|
|
26
27
|
wait_writable
|
|
27
28
|
|
|
28
29
|
zmsg = CZMQ::FFI::Zmsg.new
|
|
29
30
|
parts.each do |part|
|
|
30
|
-
rc = zmsg.add_buffer(part
|
|
31
|
+
rc = zmsg.add_buffer(part)
|
|
31
32
|
HasFFIDelegate.raise_zmq_err unless rc.zero?
|
|
32
33
|
end
|
|
33
34
|
|
|
@@ -65,9 +66,8 @@ module CZTop
|
|
|
65
66
|
last_idx = parts.size - 1
|
|
66
67
|
|
|
67
68
|
parts.each_with_index do |part, i|
|
|
68
|
-
|
|
69
|
-
frame
|
|
70
|
-
return false if frame.null?
|
|
69
|
+
frame = CZMQ::FFI.zframe_new_s(part, part.bytesize)
|
|
70
|
+
raise NoMemoryError, 'could not allocate message frame' if frame.null?
|
|
71
71
|
|
|
72
72
|
flags = CZMQ::FFI::ZFRAME_DONTWAIT
|
|
73
73
|
flags |= CZMQ::FFI::ZFRAME_MORE if i < last_idx
|
|
@@ -75,7 +75,9 @@ module CZTop
|
|
|
75
75
|
pp.write_pointer(frame)
|
|
76
76
|
rc = CZMQ::FFI.zframe_send(pp, sock_ptr, flags)
|
|
77
77
|
unless rc.zero?
|
|
78
|
+
errno = CZMQ::FFI::Errors.errno
|
|
78
79
|
CZMQ::FFI.zframe_destroy(pp)
|
|
80
|
+
HasFFIDelegate.raise_zmq_err(errno: errno) unless errno == Errno::EAGAIN::Errno
|
|
79
81
|
return false
|
|
80
82
|
end
|
|
81
83
|
end
|
data/lib/cztop/socket/xpub.rb
CHANGED
|
@@ -13,7 +13,7 @@ module CZTop
|
|
|
13
13
|
|
|
14
14
|
# @param endpoints [String] endpoints to bind to
|
|
15
15
|
# @param curve [Hash, nil] CURVE encryption options
|
|
16
|
-
# @param linger [
|
|
16
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
17
17
|
#
|
|
18
18
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
19
19
|
super
|
data/lib/cztop/socket/xsub.rb
CHANGED
|
@@ -13,7 +13,7 @@ module CZTop
|
|
|
13
13
|
|
|
14
14
|
# @param endpoints [String] endpoints to connect to
|
|
15
15
|
# @param curve [Hash, nil] CURVE encryption options
|
|
16
|
-
# @param linger [
|
|
16
|
+
# @param linger [Numeric, nil] linger period in seconds (default: 0)
|
|
17
17
|
#
|
|
18
18
|
def initialize(endpoints = nil, curve: nil, linger: 0)
|
|
19
19
|
super
|
data/lib/cztop/socket.rb
CHANGED
|
@@ -142,7 +142,7 @@ module CZTop
|
|
|
142
142
|
# Connects or binds based on CZMQ endpoint prefix convention.
|
|
143
143
|
# @api private
|
|
144
144
|
# @param endpoints [String] endpoint, optionally prefixed with +@+ (bind) or +>+ (connect)
|
|
145
|
-
# @param default [Symbol] +:connect+ or +:bind
|
|
145
|
+
# @param default [Symbol] +:connect+ or +:bind+; action when no prefix given
|
|
146
146
|
#
|
|
147
147
|
def _attach(endpoints, default:)
|
|
148
148
|
return unless endpoints
|
data/lib/cztop/version.rb
CHANGED
data/lib/cztop/zsock_options.rb
CHANGED
|
@@ -145,7 +145,15 @@ module CZTop
|
|
|
145
145
|
# @return [String] current socket identity
|
|
146
146
|
#
|
|
147
147
|
def identity
|
|
148
|
-
Zsock.identity(self)
|
|
148
|
+
ptr = Zsock.identity(self)
|
|
149
|
+
HasFFIDelegate.raise_zmq_err if ptr.null?
|
|
150
|
+
begin
|
|
151
|
+
ptr.read_string
|
|
152
|
+
ensure
|
|
153
|
+
ref = ::FFI::MemoryPointer.new(:pointer)
|
|
154
|
+
ref.write_pointer(ptr)
|
|
155
|
+
CZMQ::FFI.zstr_free(ref)
|
|
156
|
+
end
|
|
149
157
|
end
|
|
150
158
|
|
|
151
159
|
|
data/lib/cztop.rb
CHANGED
|
@@ -40,5 +40,5 @@ require_relative 'cztop/monitor'
|
|
|
40
40
|
require_relative 'cztop/curve'
|
|
41
41
|
require_relative 'cztop/curve/auth'
|
|
42
42
|
|
|
43
|
-
# Convenience alias
|
|
43
|
+
# Convenience alias; allows `Cztop::Socket::REQ` alongside `CZTop::Socket::REQ`.
|
|
44
44
|
Cztop = CZTop
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cztop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Patrik Wenger
|
|
@@ -198,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
198
198
|
- !ruby/object:Gem::Version
|
|
199
199
|
version: '0'
|
|
200
200
|
requirements: []
|
|
201
|
-
rubygems_version: 4.0.
|
|
201
|
+
rubygems_version: 4.0.20
|
|
202
202
|
specification_version: 4
|
|
203
203
|
summary: CZMQ FFI binding to bring ZMQ sockets to Ruby
|
|
204
204
|
test_files: []
|