cztop 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rspec +2 -0
- data/.travis.yml +31 -0
- data/.yardopts +1 -0
- data/AUTHORS +1 -0
- data/CHANGES.md +3 -0
- data/Gemfile +10 -0
- data/Guardfile +61 -0
- data/LICENSE +5 -0
- data/Procfile +3 -0
- data/README.md +408 -0
- data/Rakefile +6 -0
- data/bin/console +7 -0
- data/bin/setup +7 -0
- data/ci-scripts/install-deps +9 -0
- data/cztop.gemspec +36 -0
- data/examples/ruby_actor/actor.rb +100 -0
- data/examples/simple_req_rep/rep.rb +12 -0
- data/examples/simple_req_rep/req.rb +35 -0
- data/examples/taxi_system/.gitignore +2 -0
- data/examples/taxi_system/Makefile +2 -0
- data/examples/taxi_system/README.gsl +115 -0
- data/examples/taxi_system/README.md +276 -0
- data/examples/taxi_system/broker.rb +98 -0
- data/examples/taxi_system/client.rb +34 -0
- data/examples/taxi_system/generate_keys.rb +24 -0
- data/examples/taxi_system/start_broker.sh +2 -0
- data/examples/taxi_system/start_clients.sh +11 -0
- data/lib/cztop/actor.rb +308 -0
- data/lib/cztop/authenticator.rb +97 -0
- data/lib/cztop/beacon.rb +96 -0
- data/lib/cztop/certificate.rb +176 -0
- data/lib/cztop/config/comments.rb +66 -0
- data/lib/cztop/config/serialization.rb +82 -0
- data/lib/cztop/config/traversing.rb +157 -0
- data/lib/cztop/config.rb +119 -0
- data/lib/cztop/frame.rb +158 -0
- data/lib/cztop/has_ffi_delegate.rb +85 -0
- data/lib/cztop/message/frames.rb +74 -0
- data/lib/cztop/message.rb +191 -0
- data/lib/cztop/monitor.rb +102 -0
- data/lib/cztop/poller.rb +334 -0
- data/lib/cztop/polymorphic_zsock_methods.rb +24 -0
- data/lib/cztop/proxy.rb +149 -0
- data/lib/cztop/send_receive_methods.rb +35 -0
- data/lib/cztop/socket/types.rb +207 -0
- data/lib/cztop/socket.rb +106 -0
- data/lib/cztop/version.rb +3 -0
- data/lib/cztop/z85.rb +157 -0
- data/lib/cztop/zsock_options.rb +334 -0
- data/lib/cztop.rb +55 -0
- data/perf/README.md +79 -0
- data/perf/inproc_lat.rb +49 -0
- data/perf/inproc_thru.rb +42 -0
- data/perf/local_lat.rb +35 -0
- data/perf/remote_lat.rb +26 -0
- metadata +297 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: eb0ba59995fcb10d5dd7054d72ba49cf886281ea
|
4
|
+
data.tar.gz: deea479538b525d5f92673bd694b8d34f5b8e7d8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1849347983836cf93974f9f51d41147a1cacd6e4950b77b8ebac2a62429827b58fff40e8de41fe6c16cc44c8663c4009b8e20f44fe74c00956047885ccc21a73
|
7
|
+
data.tar.gz: e278d6d22d69c2e0f83bbaaed62057be6883a175749eee567aafd8343fde586cf3cb812c5e8e75e56ad56ec6808abd4617a907dc11f4ce06e5f1091fd167e4f7
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
language: ruby
|
2
|
+
sudo: false
|
3
|
+
cache:
|
4
|
+
directories:
|
5
|
+
- $HOME/.ccache
|
6
|
+
- $HOME/.bundle
|
7
|
+
rvm:
|
8
|
+
- 2.3.0
|
9
|
+
- 2.2.4
|
10
|
+
- 2.1.8
|
11
|
+
- jruby-head
|
12
|
+
- rbx
|
13
|
+
env:
|
14
|
+
# recognized by czmq-ffi-gen's ci-scripts
|
15
|
+
- CZMQ_VERSION=HEAD ZMQ_VERSION=HEAD
|
16
|
+
- CZMQ_VERSION=3.0 ZMQ_VERSION=4.1
|
17
|
+
matrix:
|
18
|
+
exclude:
|
19
|
+
# old ruby versions don't get to test bleeding edge functionality. basta.
|
20
|
+
- rvm: 2.2.4
|
21
|
+
env: CZMQ_VERSION=HEAD ZMQ_VERSION=HEAD
|
22
|
+
- rvm: 2.1.8
|
23
|
+
env: CZMQ_VERSION=HEAD ZMQ_VERSION=HEAD
|
24
|
+
before_install:
|
25
|
+
- PATH="/usr/lib/ccache:$PATH" # enable ccache
|
26
|
+
- export LD_LIBRARY_PATH=$HOME/lib # custom libs (for execution)
|
27
|
+
- export PKG_CONFIG_PATH=$HOME/lib/pkgconfig # custom libs (for linking)
|
28
|
+
- export BUNDLE_PATH=$HOME/.bundle # bundle caching
|
29
|
+
- ci-scripts/install-deps
|
30
|
+
- gem install bundler -v 1.10.6
|
31
|
+
script: bundle exec rake spec
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--private lib/**/*.rb - README.md LICENSE
|
data/AUTHORS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Patrik Wenger <paddor@gmail.com>
|
data/CHANGES.md
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
# useful when working on czmq-ffi-gen in parallel
|
5
|
+
#gem "czmq-ffi-gen", git: "https://github.com/paddor/czmq-ffi-gen.git"
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem 'rubocop', require: false
|
9
|
+
gem 'coveralls', require: false, platform: :mri
|
10
|
+
end
|
data/Guardfile
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require "guard/rspec/dsl"
|
2
|
+
|
3
|
+
# Start using
|
4
|
+
#
|
5
|
+
# bundle exec guard -g doc & bundle exec guard -g spec
|
6
|
+
#
|
7
|
+
# This way you get parallel execution, so
|
8
|
+
# * documentation is regenerated immediately
|
9
|
+
# * specs are run immediately
|
10
|
+
|
11
|
+
README_FILE = %r{^README\.md}
|
12
|
+
|
13
|
+
# set these later using help from guard-rspec
|
14
|
+
ruby_lib_files = nil
|
15
|
+
spec_files = nil
|
16
|
+
|
17
|
+
# I don't need no shell that hogs my CPU whenever I hit return.
|
18
|
+
interactor :off
|
19
|
+
|
20
|
+
group :spec do
|
21
|
+
guard :rspec, cmd: "bundle exec rspec" do
|
22
|
+
dsl = Guard::RSpec::Dsl.new(self)
|
23
|
+
|
24
|
+
# RSpec files
|
25
|
+
rspec = dsl.rspec
|
26
|
+
watch(rspec.spec_helper) { rspec.spec_dir }
|
27
|
+
watch(rspec.spec_support) { rspec.spec_dir }
|
28
|
+
watch(rspec.spec_files)
|
29
|
+
spec_files = rspec.spec_files
|
30
|
+
|
31
|
+
# # Ruby files
|
32
|
+
ruby = dsl.ruby
|
33
|
+
watch(ruby.lib_files) { |m| rspec.spec.(m[1]) }
|
34
|
+
ruby_lib_files = ruby.lib_files
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
puts "README pattern: %p" % README_FILE
|
39
|
+
puts "ruby lib files pattern: %p" % ruby_lib_files
|
40
|
+
puts "spec files pattern: %p" % spec_files
|
41
|
+
end
|
42
|
+
|
43
|
+
group :syntax_check do
|
44
|
+
guard :shell do
|
45
|
+
# check Ruby syntax
|
46
|
+
watch(Regexp.union(ruby_lib_files, spec_files)) do |m|
|
47
|
+
puts "Checking Ruby syntax of %p ..." % m[0]
|
48
|
+
if not system("ruby -c #{m[0]}")
|
49
|
+
n "#{m[0]} is incorrect", 'Ruby Syntax', :failed
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
YARD_OPTS = "--use-cache .yardoc/cache.db"
|
56
|
+
|
57
|
+
group :doc do
|
58
|
+
guard 'yard' do
|
59
|
+
watch(Regexp.union(README_FILE, ruby_lib_files))
|
60
|
+
end
|
61
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,5 @@
|
|
1
|
+
Copyright (c) 2016, Patrik Wenger
|
2
|
+
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
4
|
+
|
5
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/Procfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,408 @@
|
|
1
|
+
[![Build Status on Travis CI](https://travis-ci.org/paddor/cztop.svg?branch=master)](https://travis-ci.org/paddor/cztop?branch=master)
|
2
|
+
[![Code Climate](https://codeclimate.com/repos/56677a7849f50a141c001784/badges/48f3cca3c62df9e4b17b/gpa.svg)](https://codeclimate.com/repos/56677a7849f50a141c001784/feed)
|
3
|
+
[![Inline docs](http://inch-ci.org/github/paddor/cztop.svg?branch=master&style=shields)](http://inch-ci.org/github/paddor/cztop)
|
4
|
+
[![Dependency Status](https://gemnasium.com/paddor/cztop.svg)](https://gemnasium.com/paddor/cztop)
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/paddor/cztop/badge.svg?branch=master&service=github)](https://coveralls.io/github/paddor/cztop?branch=master)
|
6
|
+
|
7
|
+
# CZTop
|
8
|
+
|
9
|
+
```
|
10
|
+
_________ _____________________
|
11
|
+
\_ ___ \ \____ /\__ ___/____ ______
|
12
|
+
/ \ \/ / / | | / _ \ \____ \
|
13
|
+
\ \____ / /_ | | ( <_> )| |_> >
|
14
|
+
\______ //_______ \ |____| \____/ | __/
|
15
|
+
\/ \/ |__|
|
16
|
+
```
|
17
|
+
|
18
|
+
CZTop is a CZMQ binding for Ruby. It is based on
|
19
|
+
[czmq-ffi-gen](https://github.com/paddor/czmq-ffi-gen), the generated low-level
|
20
|
+
FFI binding of [CZMQ](https://github.com/zeromq/czmq) and has a focus on being
|
21
|
+
easy to use for Rubyists (POLS) and providing first class support for security
|
22
|
+
mechanisms (like CURVE).
|
23
|
+
|
24
|
+
## Reasons
|
25
|
+
|
26
|
+
Why another CZMQ Ruby binding? Here is a list of existing projects I found and
|
27
|
+
the issues with them, from my point of view:
|
28
|
+
|
29
|
+
* [Asmod4n/ruby-ffi-czmq](https://github.com/Asmod4n/ruby-ffi-czmq)
|
30
|
+
* outdated
|
31
|
+
* according to its author, it's an "abomination"
|
32
|
+
* [methodmissing/rbczmq](https://github.com/methodmissing/rbczmq)
|
33
|
+
* no support for security features (see [methodmissing/rbczmq#28](https://github.com/methodmissing/rbczmq/issues/28))
|
34
|
+
* no JRuby support (see [methodmissing/rbczmq#48](https://github.com/methodmissing/rbczmq/issues/48))
|
35
|
+
* doesn't feel like Ruby
|
36
|
+
* [mtortonesi/ruby-czmq](https://github.com/mtortonesi/ruby-czmq)
|
37
|
+
* no tests
|
38
|
+
* outdated
|
39
|
+
* doesn't feel like Ruby
|
40
|
+
* [chuckremes/ffi-rzmq](https://github.com/chuckremes/ffi-rzmq)
|
41
|
+
* low level ZMQ gem, not CZMQ
|
42
|
+
|
43
|
+
Furthermore, I knew about the generated low-level Ruby FFI binding in the
|
44
|
+
[zeromq/czmq](https://github.com/zeromq/czmq) repository. I wanted to make use
|
45
|
+
of it because I love that it's generated (and thus, most likely correct
|
46
|
+
and up-to-date). Unfortunately, it was in pretty bad shape and missing a few
|
47
|
+
CZMQ classes.
|
48
|
+
|
49
|
+
So I decided to improve the quality and usability of the binding and add the
|
50
|
+
missing classes. The result is
|
51
|
+
[czmq-ffi-gen](https://github.com/paddor/czmq-ffi-gen) which provides a solid
|
52
|
+
foundation for CZTop.
|
53
|
+
|
54
|
+
## Goals
|
55
|
+
|
56
|
+
Here are some some of the goals I have/had in mind for this library:
|
57
|
+
|
58
|
+
- [x] as easy as possible, Ruby-esque API
|
59
|
+
- [x] first class support for security (CURVE mechanism)
|
60
|
+
- [x] including handling of certificates
|
61
|
+
- [x] support MRI, Rubinius, and JRuby
|
62
|
+
- [x] high-quality API documentation
|
63
|
+
- [x] 100% test coverage
|
64
|
+
- [x] provide a portable Z85 implementation
|
65
|
+
* unlike [fpesce/z85](https://github.com/fpesce/z85), which is a C extension
|
66
|
+
- [ ] use it to replace the [Celluloid::ZMQ](https://github.com/celluloid/celluloid-zmq) part of [Celluloid](https://github.com/celluloid/celluloid)
|
67
|
+
- [ ] implement some of the missing (CZMQ based) Ruby examples in the [ZMQ Guide](http://zguide.zeromq.org/page:all)
|
68
|
+
|
69
|
+
## Overview
|
70
|
+
|
71
|
+
### Class Hierarchy
|
72
|
+
|
73
|
+
Here's an overview of the core classes:
|
74
|
+
|
75
|
+
* CZTop
|
76
|
+
* Actor
|
77
|
+
* Authentiator < Actor
|
78
|
+
* Beacon < Actor
|
79
|
+
* Certificate
|
80
|
+
* Config
|
81
|
+
* Frame
|
82
|
+
* Message
|
83
|
+
* Monitor < Actor
|
84
|
+
* Proxy < Actor
|
85
|
+
* Poller
|
86
|
+
* Socket
|
87
|
+
* REQ < Socket
|
88
|
+
* REP < Socket
|
89
|
+
* ROUTER < Socket
|
90
|
+
* DEALER < Socket
|
91
|
+
* PUSH < Socket
|
92
|
+
* PULL < Socket
|
93
|
+
* PUB < Socket
|
94
|
+
* SUB < Socket
|
95
|
+
* XPUB < Socket
|
96
|
+
* XSUB < Socket
|
97
|
+
* PAIR < Socket
|
98
|
+
* STREAM < Socket
|
99
|
+
* CLIENT < Socket
|
100
|
+
* SERVER < Socket
|
101
|
+
* Z85
|
102
|
+
* Padded < Z85
|
103
|
+
|
104
|
+
More information in the [API documentation](http://www.rubydoc.info/github/paddor/cztop).
|
105
|
+
|
106
|
+
### Features
|
107
|
+
|
108
|
+
* Ruby-like API
|
109
|
+
* method names
|
110
|
+
* sending a message via a socket is done with `Socket#<<`
|
111
|
+
* `socket << "simple message"`
|
112
|
+
* `socket << ["multi", "frame", "message"]`
|
113
|
+
* `#x=` methods instead of `#set_x` (e.g. socket options)
|
114
|
+
* `#[]` where it makes sense (e.g. on a Message, Config, or Certificate)
|
115
|
+
* no manual error checking needed
|
116
|
+
* if there's an error, an appropriate exception is raised
|
117
|
+
* of course, no manual dealing with the ZMQ context
|
118
|
+
* easy security
|
119
|
+
* use `Socket#CURVE_server!(cert)` on the server
|
120
|
+
* and `Socket#CURVE_client!(client_cert, server_cert)` on the client
|
121
|
+
* socket types as Ruby classes
|
122
|
+
* no need to manually pass some constant
|
123
|
+
* but you can: `CZTop::Socket.new_by_type(:REP)`
|
124
|
+
* e.g. `#subscribe` only exists on CZTop::Socket::SUB
|
125
|
+
* SERVER and CLIENT ready
|
126
|
+
* see CZTop::Socket::SERVER and CZTop::Socket::CLIENT
|
127
|
+
* there are `#routing_id` and `#routing_id=` on the following classes:
|
128
|
+
* CZTop::Message
|
129
|
+
* CZTop::Frame
|
130
|
+
* requires ZMQ >= 4.2
|
131
|
+
* ZMTP 3.1 heartbeat ready
|
132
|
+
* `socket.options.heartbeat_ivl = 2000`
|
133
|
+
* `socket.options.heartbeat_timeout = 8000`
|
134
|
+
* requires ZMQ >= 4.2
|
135
|
+
|
136
|
+
## Requirements
|
137
|
+
|
138
|
+
You'll need:
|
139
|
+
|
140
|
+
* CZMQ >= 3.0.2
|
141
|
+
* ZMQ >= 4.0
|
142
|
+
|
143
|
+
For security mechanisms like CURVE, you'll need:
|
144
|
+
|
145
|
+
* [libsodium](https://github.com/jedisct1/libsodium)
|
146
|
+
|
147
|
+
To install on OSX using homebrew, run:
|
148
|
+
|
149
|
+
$ brew install libsodium
|
150
|
+
$ brew install zmq --with-libsodium
|
151
|
+
$ brew install czmq
|
152
|
+
|
153
|
+
If you're running Linux, go check [this page](http://zeromq.org/distro:_start)
|
154
|
+
to get more help. Make sure to install CZMQ, not only ZMQ.
|
155
|
+
|
156
|
+
**Warning**: To make use of the full feature set of CZTop (including
|
157
|
+
CLIENT/SERVER sockets and ZMTP 3.1 heartbeats), you'll need to install both ZMQ
|
158
|
+
and CZMQ from master, like this:
|
159
|
+
|
160
|
+
# instead of the last two commands from above
|
161
|
+
$ brew install zmq --with-libsodium --HEAD
|
162
|
+
$ brew install czmq --HEAD
|
163
|
+
|
164
|
+
See next section.
|
165
|
+
|
166
|
+
### Known Issues if using the current stable releases
|
167
|
+
|
168
|
+
When using ZMQ 4.1/4.0:
|
169
|
+
* no CLIENT/SERVER sockets. Don't try.
|
170
|
+
* no ZMTP 3.1 heartbeats. Setting the options will have no effect.
|
171
|
+
|
172
|
+
When using CZMQ 3.0:
|
173
|
+
* don't use `Certificate#[]=` to unset meta data (by passing `nil`)
|
174
|
+
* `zcert_unset_meta()` was added more recently for that case
|
175
|
+
* see [zeromq/czmq#1248](https://github.com/zeromq/czmq/pull/1248)
|
176
|
+
* if you use Beacon, make sure you also call `Beacon#configure`. Otherwise it closes STDIN when being destroyed.
|
177
|
+
* see [zeromq/czmq#1281](https://github.com/zeromq/czmq/issues/1281)
|
178
|
+
* no CLIENT/SERVER sockets. Don't try.
|
179
|
+
* no ZMTP 3.1 heartbeats. Don't try.
|
180
|
+
|
181
|
+
### Supported Ruby versions
|
182
|
+
|
183
|
+
See [.travis.yml](https://github.com/paddor/cztop/blob/master/.travis.yml) for a list of Ruby versions against which CZTop
|
184
|
+
is tested.
|
185
|
+
|
186
|
+
At the time of writing, these include:
|
187
|
+
|
188
|
+
* MRI (2.3, 2.2.4, 2.1.8)
|
189
|
+
* Rubinius (HEAD)
|
190
|
+
* JRuby 9000 (HEAD)
|
191
|
+
|
192
|
+
## Installation
|
193
|
+
|
194
|
+
To use this gem, add this line to your application's Gemfile:
|
195
|
+
|
196
|
+
```ruby
|
197
|
+
gem 'cztop'
|
198
|
+
```
|
199
|
+
|
200
|
+
And then execute:
|
201
|
+
|
202
|
+
$ bundle
|
203
|
+
|
204
|
+
Or install it yourself as:
|
205
|
+
|
206
|
+
$ gem install cztop
|
207
|
+
|
208
|
+
## Usage
|
209
|
+
|
210
|
+
See the [examples](https://github.com/paddor/cztop/blob/master/examples) directory for some examples. Here's a very simple one:
|
211
|
+
|
212
|
+
### rep.rb:
|
213
|
+
|
214
|
+
```ruby
|
215
|
+
#!/usr/bin/env ruby
|
216
|
+
require_relative '../../lib/cztop'
|
217
|
+
|
218
|
+
# create and bind socket
|
219
|
+
socket = CZTop::Socket::REP.new("ipc:///tmp/req_rep_example")
|
220
|
+
puts "<<< Socket bound to #{socket.last_endpoint.inspect}"
|
221
|
+
|
222
|
+
# Simply echo every message, with every frame String#upcase'd.
|
223
|
+
while msg = socket.receive
|
224
|
+
puts "<<< #{msg.to_a.inspect}"
|
225
|
+
socket << msg.to_a.map(&:upcase)
|
226
|
+
end
|
227
|
+
```
|
228
|
+
|
229
|
+
### req.rb:
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
#!/usr/bin/env ruby
|
233
|
+
require_relative '../../lib/cztop'
|
234
|
+
|
235
|
+
# connect
|
236
|
+
socket = CZTop::Socket::REQ.new("ipc:///tmp/req_rep_example")
|
237
|
+
puts ">>> Socket connected."
|
238
|
+
|
239
|
+
# simple string
|
240
|
+
socket << "foobar"
|
241
|
+
msg = socket.receive
|
242
|
+
puts ">>> #{msg.to_a.inspect}"
|
243
|
+
|
244
|
+
# multi frame message as array
|
245
|
+
socket << %w[foo bar baz]
|
246
|
+
msg = socket.receive
|
247
|
+
puts ">>> #{msg.to_a.inspect}"
|
248
|
+
|
249
|
+
# manually instantiating a Message
|
250
|
+
msg = CZTop::Message.new("bla")
|
251
|
+
msg << "another frame" # append a frame
|
252
|
+
socket << msg
|
253
|
+
msg = socket.receive
|
254
|
+
puts ">>> #{msg.to_a.inspect}"
|
255
|
+
|
256
|
+
##
|
257
|
+
# This will send 20 additional messages:
|
258
|
+
#
|
259
|
+
# ./req.rb 20
|
260
|
+
#
|
261
|
+
if ARGV.first
|
262
|
+
ARGV.first.to_i.times do
|
263
|
+
socket << ["fooooooooo", "baaaaaar"]
|
264
|
+
puts ">>> " + socket.receive.to_a.inspect
|
265
|
+
end
|
266
|
+
end
|
267
|
+
```
|
268
|
+
|
269
|
+
### Running it
|
270
|
+
|
271
|
+
```
|
272
|
+
$ ./rep.rb & ./req.rb 3
|
273
|
+
[3] 35321
|
274
|
+
>>> Socket connected.
|
275
|
+
<<< Socket bound to "ipc:///tmp/req_rep_example"
|
276
|
+
<<< ["foobar"]
|
277
|
+
>>> ["FOOBAR"]
|
278
|
+
<<< ["foo", "bar", "baz"]
|
279
|
+
>>> ["FOO", "BAR", "BAZ"]
|
280
|
+
<<< ["bla", "another frame"]
|
281
|
+
>>> ["BLA", "ANOTHER FRAME"]
|
282
|
+
<<< ["fooooooooo", "baaaaaar"]
|
283
|
+
>>> ["FOOOOOOOOO", "BAAAAAAR"]
|
284
|
+
<<< ["fooooooooo", "baaaaaar"]
|
285
|
+
>>> ["FOOOOOOOOO", "BAAAAAAR"]
|
286
|
+
<<< ["fooooooooo", "baaaaaar"]
|
287
|
+
>>> ["FOOOOOOOOO", "BAAAAAAR"]
|
288
|
+
$
|
289
|
+
```
|
290
|
+
|
291
|
+
## Documentation
|
292
|
+
|
293
|
+
The API should be fairly straight-forward to anyone who is familiar with CZMQ
|
294
|
+
and Ruby. The following API documentation is currently available:
|
295
|
+
|
296
|
+
* [YARD API documentation](http://www.rubydoc.info/github/paddor/cztop)
|
297
|
+
|
298
|
+
Feel free to start a [wiki](https://github.com/paddor/cztop/wiki) page.
|
299
|
+
|
300
|
+
## Performance
|
301
|
+
|
302
|
+
Performance should be pretty okay since this is based on czmq-ffi-gen, which is
|
303
|
+
reasonably thin. CZTop is basically only a convenience layer on top, with some
|
304
|
+
nice error checking. But hey, it's Ruby. Don't expect 5M messages per second
|
305
|
+
with a latency of 3us.
|
306
|
+
|
307
|
+
The measured latency on my laptop ranges from ~20us to ~60us per message for
|
308
|
+
1kb messages, depending on whether transport is inproc, IPC, or TCP/IP.
|
309
|
+
|
310
|
+
Make sure you check out the
|
311
|
+
[perf](https://github.com/paddor/cztop/blob/master/perf) directory for latency
|
312
|
+
and throughput measurement scripts.
|
313
|
+
|
314
|
+
## TODO
|
315
|
+
|
316
|
+
* [x] pack generated code into its own gem ([czmq-ffi-gen](https://github.com/paddor/czmq-ffi-gen))
|
317
|
+
* think of a neat Ruby API, including:
|
318
|
+
- [x] Actor
|
319
|
+
- [x] Beacon
|
320
|
+
- [x] Certificate
|
321
|
+
- [x] Socket
|
322
|
+
- [50%] access to all socket options
|
323
|
+
- [x] Security mechanisms
|
324
|
+
- [x] Message
|
325
|
+
- [x] Frame
|
326
|
+
- [x] enumerable Frames
|
327
|
+
- [x] Authenticator
|
328
|
+
- [x] Loop
|
329
|
+
- [x] Monitor
|
330
|
+
- [x] Poller
|
331
|
+
- [x] Proxy
|
332
|
+
- [x] Config
|
333
|
+
- [x] Z85
|
334
|
+
* write the missing XML API files in CZMQ
|
335
|
+
- [x] zarmour.xml
|
336
|
+
- [x] zconfig.xml
|
337
|
+
- [x] zsock_option.xml
|
338
|
+
- [x] zcert.xml
|
339
|
+
- [x] zcertstore.xml
|
340
|
+
* [x] check availability of libsodium within CZTop
|
341
|
+
* [x] read error strings for exceptions where appropriate (zmq_strerror)
|
342
|
+
* [x] add support for ZMTP 3.1 heartbeats in CZMQ
|
343
|
+
* [x] add padded variant of Z85
|
344
|
+
* add more examples
|
345
|
+
* [x] [simple REQ/REP](https://github.com/paddor/cztop/tree/master/examples/simple_req_rep)
|
346
|
+
* [x] [Taxy System](https://github.com/paddor/cztop/tree/master/examples/taxi_system) with CURVE security and heartbeating
|
347
|
+
* [x] change from ROUTER/DEALER to SERVER/CLIENT
|
348
|
+
* [x] [Actor](https://github.com/paddor/cztop/tree/master/examples/ruby_actor) with Ruby block
|
349
|
+
* [ ] PUSH/PULL
|
350
|
+
* [ ] PUB/SUB
|
351
|
+
* [ ] add performance benchmarks
|
352
|
+
* [x] inproc latency
|
353
|
+
* [x] inproc throughput
|
354
|
+
* [x] local/remote latency
|
355
|
+
* [ ] local/remote throughput
|
356
|
+
* see [perf](https://github.com/paddor/cztop/blob/master/perf) directory
|
357
|
+
* [x] support older versions of ZMQ
|
358
|
+
* [x] ZMQ HEAD
|
359
|
+
* [x] tested on CI
|
360
|
+
* [x] ZMQ 4.1
|
361
|
+
* [x] tested on CI
|
362
|
+
* [x] ZMQ 4.0
|
363
|
+
* [x] tested on CI
|
364
|
+
* [ ] ZMQ 3.2
|
365
|
+
* too big a pain ([d5172ab](https://github.com/paddor/czmq-ffi-gen/commit/d5172ab6db64999c50ba24f71569acf1dd45af51))
|
366
|
+
* [x] support multiple versions of CZMQ
|
367
|
+
* [x] CZMQ HEAD
|
368
|
+
* [x] test on CI
|
369
|
+
* [x] CZMQ 3.0.2 (current stable)
|
370
|
+
* no `zcert_meta_unset()` ([zeromq/czmq#1246](https://github.com/zeromq/czmq/issues/1246))
|
371
|
+
* [x] adapt czmq-ffi-gen so it doesn't raise while `attach_function`
|
372
|
+
* no `zproc`(especially no `zproc_has_curve()`)
|
373
|
+
* [x] adapt czmq-ffi-gen so it doesn't raise while `attach_function`, attach `zsys_has_curve()` instead (under same name)
|
374
|
+
* [x] adapt test suite to skip affected test examples
|
375
|
+
* [x] test on CI
|
376
|
+
* [x] port Poller to `zmq_poll()`
|
377
|
+
* backwards compatible (`#add_reader`, `#add_writer`, `#wait` behave the same)
|
378
|
+
* but in addition, it has `#readables` and `#writables` which return arrays of sockets
|
379
|
+
* level-triggered (not sure if `zmq_poll()` itelf is, but it'll be trivial)
|
380
|
+
* could then be used in Celluloid::ZMQ
|
381
|
+
* want to use `zmq_poller()` because it can deal with CLIENT/SERVER sockets and is the future
|
382
|
+
* but can't use it because
|
383
|
+
* it doesn't allow me to get all readable/writable sockets back after one call to `#wait`
|
384
|
+
* can't just recall `#wait` with zero timeout until it says there are no
|
385
|
+
more, because ZMQ sockets (option ZMQ_FD) are edge-triggered :-(
|
386
|
+
* maybe I don't really need that functionality, though
|
387
|
+
* can't use `zpoller`, because it doesn't support polling for writing
|
388
|
+
* [ ] add `Message#to_s`
|
389
|
+
* return frame as string, if there's only one frame
|
390
|
+
* raise if there are multiple frames
|
391
|
+
* only safe to use on messages from SERVER/CLIENT sockets
|
392
|
+
* single-part messages are the future
|
393
|
+
* [x] get rid of Loop
|
394
|
+
* cannot handle SERVER socket
|
395
|
+
* there are other timer libraries for Ruby
|
396
|
+
* Poller can be used to embed in an existing event loop (Celluloid), or make your own trivial one.
|
397
|
+
|
398
|
+
## Contributing
|
399
|
+
|
400
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/paddor/cztop.
|
401
|
+
|
402
|
+
To run the tests before/after you made any changes to the source and have
|
403
|
+
created a test case for it, use `rake spec`.
|
404
|
+
|
405
|
+
## License
|
406
|
+
|
407
|
+
The gem is available as open source under the terms of the [ISC License](http://opensource.org/licenses/ISC).
|
408
|
+
See the [LICENSE](https://github.com/paddor/cztop/blob/master/LICENSE) file.
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
data/cztop.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cztop/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cztop"
|
8
|
+
spec.version = CZTop::VERSION
|
9
|
+
spec.authors = ["Patrik Wenger"]
|
10
|
+
spec.email = ["paddor@gmail.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{CZMQ Ruby binding, based on the generated low-level FFI bindings of CZMQ}
|
13
|
+
spec.homepage = "https://github.com/paddor/cztop"
|
14
|
+
spec.license = "ISC"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = "exe"
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "czmq-ffi-gen", "~> 0.7.0"
|
22
|
+
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec"
|
26
|
+
spec.add_development_dependency "minitest"
|
27
|
+
spec.add_development_dependency "rspec-given", "~> 3.8.0"
|
28
|
+
spec.add_development_dependency "pry"
|
29
|
+
spec.add_development_dependency "yard"
|
30
|
+
spec.add_development_dependency "guard"
|
31
|
+
spec.add_development_dependency "guard-rspec"
|
32
|
+
spec.add_development_dependency "guard-yard"
|
33
|
+
spec.add_development_dependency "guard-shell"
|
34
|
+
spec.add_development_dependency 'terminal-notifier-guard'
|
35
|
+
spec.add_development_dependency 'foreman'
|
36
|
+
end
|