ezmq 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +25 -0
- data/Rakefile +34 -0
- data/doc/EZMQ.html +126 -0
- data/doc/EZMQ/Client.html +385 -0
- data/doc/EZMQ/Publisher.html +401 -0
- data/doc/EZMQ/Server.html +449 -0
- data/doc/EZMQ/Socket.html +1084 -0
- data/doc/EZMQ/Subscriber.html +693 -0
- data/doc/_index.html +169 -0
- data/doc/class_list.html +58 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +339 -0
- data/doc/file.README.html +95 -0
- data/doc/file_list.html +60 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +95 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +181 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +183 -0
- data/doc/top-level-namespace.html +112 -0
- data/ezmq.gemspec +27 -0
- data/lib/ezmq.rb +227 -0
- metadata +212 -0
data/ezmq.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.name = 'ezmq'
|
3
|
+
gem.version = '0.1.1'
|
4
|
+
gem.licenses = 'MIT'
|
5
|
+
gem.authors = ['Chris Olstrom']
|
6
|
+
gem.email = 'chris@olstrom.com'
|
7
|
+
gem.homepage = 'https://github.com/colstrom/ezmq'
|
8
|
+
gem.summary = 'Effortless ZMQ'
|
9
|
+
gem.description = 'Syntactic sugar around FFI bindings for ZMQ, to stop C from seeping into your Ruby.'
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split("\n")
|
12
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
13
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
14
|
+
gem.require_paths = ['lib']
|
15
|
+
|
16
|
+
gem.add_runtime_dependency 'ffi-rzmq', '~> 2.0'
|
17
|
+
|
18
|
+
gem.add_development_dependency 'rake'
|
19
|
+
gem.add_development_dependency 'rubocop'
|
20
|
+
gem.add_development_dependency 'flog'
|
21
|
+
gem.add_development_dependency 'flay'
|
22
|
+
gem.add_development_dependency 'roodi'
|
23
|
+
gem.add_development_dependency 'reek'
|
24
|
+
gem.add_development_dependency 'churn'
|
25
|
+
gem.add_development_dependency 'yard'
|
26
|
+
gem.add_development_dependency 'inch'
|
27
|
+
end
|
data/lib/ezmq.rb
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'ffi-rzmq'
|
2
|
+
|
3
|
+
# Syntactic sugar for 0MQ, because Ruby shouldn't feel like C.
|
4
|
+
module EZMQ
|
5
|
+
# Wrapper class to simplify 0MQ sockets.
|
6
|
+
class Socket
|
7
|
+
attr_accessor :context, :socket, :encode, :decode
|
8
|
+
|
9
|
+
# Creates a 0MQ socket.
|
10
|
+
#
|
11
|
+
# @param [Symbol] mode the mode of the socket. `:bind` or `:connect`
|
12
|
+
# @param [Object] type the type of socket to use.
|
13
|
+
# @param [Hash] options optional parameters.
|
14
|
+
#
|
15
|
+
# @option options [ZMQ::Context] context a context to use for this socket
|
16
|
+
# (one will be created if not provided).
|
17
|
+
# @option options [lambda] encode how to encode messages. Default unaltered.
|
18
|
+
# @option options [lambda] decode how to decode messages. Default unaltered.
|
19
|
+
# @option options [String] address specifies protocol, address and port (if
|
20
|
+
# needed). Default is 'tcp://127.0.0.1:5555'
|
21
|
+
#
|
22
|
+
# @return [Socket] a new instance of Socket.
|
23
|
+
#
|
24
|
+
def initialize(mode, type, **options)
|
25
|
+
fail ArgumentError unless [:bind, :connect].include? mode
|
26
|
+
@context = options[:context] || ZMQ::Context.new
|
27
|
+
@socket = @context.socket type
|
28
|
+
@encode = options[:encode] || -> m { m }
|
29
|
+
@decode = options[:decode] || -> m { m }
|
30
|
+
method(mode).call address: options[:address] || 'tcp://127.0.0.1:5555'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Receive a message from the socket.
|
34
|
+
#
|
35
|
+
# @note This method blocks until a message arrives.
|
36
|
+
#
|
37
|
+
# @param [lambda] decode how to decode the message.
|
38
|
+
#
|
39
|
+
# @return [void] the decoded message.
|
40
|
+
#
|
41
|
+
def receive(decode: @decode)
|
42
|
+
message = ''
|
43
|
+
@socket.recv_string message
|
44
|
+
decode.call message
|
45
|
+
end
|
46
|
+
|
47
|
+
# Sends a message on the socket.
|
48
|
+
#
|
49
|
+
# @note If `message` is not a String, `encode` must convert it to one.
|
50
|
+
#
|
51
|
+
# @param [String] message the message to send.
|
52
|
+
# @param [lambda] encode how to encode the message.
|
53
|
+
#
|
54
|
+
# @return [Fixnum] the size of the message.
|
55
|
+
#
|
56
|
+
def send(message = '', encode: @encode)
|
57
|
+
@socket.send_string encode.call message
|
58
|
+
end
|
59
|
+
|
60
|
+
# Binds the socket to the given address.
|
61
|
+
#
|
62
|
+
# @note 'localhost' does not always work as expected. Prefer '127.0.0.1'
|
63
|
+
#
|
64
|
+
# @param [String] address specifies protocol, address and port (if needed).
|
65
|
+
# Default is 'tcp://127.0.0.1:5555'
|
66
|
+
#
|
67
|
+
# @return [Boolean] was binding successful?
|
68
|
+
#
|
69
|
+
def bind(address: 'tcp://127.0.0.1:5555')
|
70
|
+
@socket.bind(address) == 0 ? true : false
|
71
|
+
end
|
72
|
+
|
73
|
+
# Connects the socket to the given address.
|
74
|
+
#
|
75
|
+
# @param [String] address specifies protocol, address and port (if needed).
|
76
|
+
# Default is 'tcp://127.0.0.1:5555'
|
77
|
+
#
|
78
|
+
# @return [Boolean] was connection successful?
|
79
|
+
#
|
80
|
+
def connect(address: 'tcp://127.0.0.1:5555')
|
81
|
+
@socket.connect(address) == 0 ? true : false
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Reply socket that listens for and replies to requests.
|
86
|
+
class Server < EZMQ::Socket
|
87
|
+
attr_accessor :provides
|
88
|
+
|
89
|
+
# Creates a new Server socket.
|
90
|
+
#
|
91
|
+
# @param [lambda] provides the service provided by this server.
|
92
|
+
# @param [Hash] options optional parameters
|
93
|
+
#
|
94
|
+
# @see EZMQ::Socket EZMQ::Socket for a list of optional parameters.
|
95
|
+
#
|
96
|
+
# @return [Server] a new instance of Server
|
97
|
+
#
|
98
|
+
def initialize(provides: -> m { m }, **options)
|
99
|
+
@provides = provides
|
100
|
+
super :bind, ZMQ::REP, options
|
101
|
+
end
|
102
|
+
|
103
|
+
# By default, waits to receive a message, calls @action with it, replies
|
104
|
+
# with the result, then loops.
|
105
|
+
#
|
106
|
+
# @param [lambda] handler how requests are handled.
|
107
|
+
#
|
108
|
+
# @return [void] the return from handler.
|
109
|
+
#
|
110
|
+
def listen(handler: -> { send @provides.call(receive) })
|
111
|
+
loop { handler.call }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Request socket that sends messages and receives replies.
|
116
|
+
class Client < EZMQ::Socket
|
117
|
+
# Creates a new Client socket.
|
118
|
+
#
|
119
|
+
# @param [Hash] options optional parameters
|
120
|
+
#
|
121
|
+
# @see EZMQ::Socket EZMQ::Socket for a list of optional parameters.
|
122
|
+
#
|
123
|
+
# @return [Client] a new instance of Client.
|
124
|
+
#
|
125
|
+
def initialize(**options)
|
126
|
+
super :connect, ZMQ::REQ, options
|
127
|
+
end
|
128
|
+
|
129
|
+
# Sends a message and waits to receive a response.
|
130
|
+
#
|
131
|
+
# @param [String] message the message to send.
|
132
|
+
# @param [lambda] encode how to encode the message.
|
133
|
+
# @param [lambda] decode how to decode the message.
|
134
|
+
#
|
135
|
+
# @return [void] the decoded response message.
|
136
|
+
#
|
137
|
+
def request(message = '', encode: @encode, decode: @decode)
|
138
|
+
send message, encode: encode
|
139
|
+
receive decode: decode
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
# Publish socket that broadcasts messages with an optional topic.
|
144
|
+
class Publisher < EZMQ::Socket
|
145
|
+
# Creates a new Publisher socket.
|
146
|
+
#
|
147
|
+
# @param [Hash] options optional parameters
|
148
|
+
#
|
149
|
+
# @see EZMQ::Socket EZMQ::Socket for a list of optional parameters.
|
150
|
+
#
|
151
|
+
# @return [Publisher] a new instance of Publisher.
|
152
|
+
#
|
153
|
+
def initialize(**options)
|
154
|
+
super :bind, ZMQ::PUB, options
|
155
|
+
end
|
156
|
+
|
157
|
+
# Sends a message on the socket, with an optional topic.
|
158
|
+
#
|
159
|
+
# @param [String] message the message to send.
|
160
|
+
# @param [String] topic an optional topic for the message.
|
161
|
+
# @param [lambda] encode how to encode the message.
|
162
|
+
#
|
163
|
+
# @return [Fixnum] the size of the message.
|
164
|
+
#
|
165
|
+
def send(message = '', topic: '', encode: @encode)
|
166
|
+
@socket.send_string "#{ topic } #{ encode.call message }"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
# Subscribe socket that listens for messages with an optional topic.
|
171
|
+
class Subscriber < EZMQ::Socket
|
172
|
+
attr_accessor :action
|
173
|
+
|
174
|
+
# Creates a new Subscriber socket.
|
175
|
+
#
|
176
|
+
# @param [lambda] action the action to perform when a message is received.
|
177
|
+
# @param [Hash] options optional parameters
|
178
|
+
#
|
179
|
+
# @option options [String] topic a topic to subscribe to.
|
180
|
+
#
|
181
|
+
# @see EZMQ::Socket EZMQ::Socket for a list of optional parameters.
|
182
|
+
#
|
183
|
+
# @return [Publisher] a new instance of Publisher.
|
184
|
+
#
|
185
|
+
def initialize(action: -> m { m }, **options)
|
186
|
+
@action = action
|
187
|
+
super :connect, ZMQ::SUB, options
|
188
|
+
subscribe options[:topic] if options[:topic]
|
189
|
+
end
|
190
|
+
|
191
|
+
# Establishes a new message filter on the socket.
|
192
|
+
#
|
193
|
+
# @note By default, a Subscriber filters all incoming messages. Without
|
194
|
+
# calling subscribe at least once, no messages will be accepted. If topic
|
195
|
+
# was provided, #initialize calls #subscribe automatically.
|
196
|
+
#
|
197
|
+
# @param [String] topic a topic to subscribe to. Messages matching this
|
198
|
+
# prefix will be accepted.
|
199
|
+
#
|
200
|
+
# @return [Boolean] was subscription successful?
|
201
|
+
#
|
202
|
+
def subscribe(topic)
|
203
|
+
@socket.setsockopt(ZMQ::SUBSCRIBE, topic) == 0 ? true : false
|
204
|
+
end
|
205
|
+
|
206
|
+
# Removes a message filter (as set with subscribe) from the socket.
|
207
|
+
#
|
208
|
+
# @param [String] topic the topic to unsubscribe from. If multiple filters
|
209
|
+
# with the same topic are set, this will only remove one.
|
210
|
+
#
|
211
|
+
# @return [Boolean] was unsubscription successful?
|
212
|
+
#
|
213
|
+
def unsubscribe(topic)
|
214
|
+
@socket.setsockopt(ZMQ::UNSUBSCRIBE, topic) == 0 ? true : false
|
215
|
+
end
|
216
|
+
|
217
|
+
# By default, waits for a message and calls @action with the message.
|
218
|
+
#
|
219
|
+
# @param [lambda] handler how requests are handled.
|
220
|
+
#
|
221
|
+
# @return [void] the return from handler.
|
222
|
+
#
|
223
|
+
def listen(handler: -> { @action.call(receive) })
|
224
|
+
loop { handler.call }
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
metadata
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ezmq
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Chris Olstrom
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-06 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: ffi-rzmq
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '2.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '2.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: flog
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: flay
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: roodi
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: reek
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: churn
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '>='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: yard
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - '>='
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: inch
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - '>='
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
description: Syntactic sugar around FFI bindings for ZMQ, to stop C from seeping into
|
154
|
+
your Ruby.
|
155
|
+
email: chris@olstrom.com
|
156
|
+
executables: []
|
157
|
+
extensions: []
|
158
|
+
extra_rdoc_files: []
|
159
|
+
files:
|
160
|
+
- .gitignore
|
161
|
+
- Gemfile
|
162
|
+
- LICENSE
|
163
|
+
- README.md
|
164
|
+
- Rakefile
|
165
|
+
- doc/EZMQ.html
|
166
|
+
- doc/EZMQ/Client.html
|
167
|
+
- doc/EZMQ/Publisher.html
|
168
|
+
- doc/EZMQ/Server.html
|
169
|
+
- doc/EZMQ/Socket.html
|
170
|
+
- doc/EZMQ/Subscriber.html
|
171
|
+
- doc/_index.html
|
172
|
+
- doc/class_list.html
|
173
|
+
- doc/css/common.css
|
174
|
+
- doc/css/full_list.css
|
175
|
+
- doc/css/style.css
|
176
|
+
- doc/file.README.html
|
177
|
+
- doc/file_list.html
|
178
|
+
- doc/frames.html
|
179
|
+
- doc/index.html
|
180
|
+
- doc/js/app.js
|
181
|
+
- doc/js/full_list.js
|
182
|
+
- doc/js/jquery.js
|
183
|
+
- doc/method_list.html
|
184
|
+
- doc/top-level-namespace.html
|
185
|
+
- ezmq.gemspec
|
186
|
+
- lib/ezmq.rb
|
187
|
+
homepage: https://github.com/colstrom/ezmq
|
188
|
+
licenses:
|
189
|
+
- MIT
|
190
|
+
metadata: {}
|
191
|
+
post_install_message:
|
192
|
+
rdoc_options: []
|
193
|
+
require_paths:
|
194
|
+
- lib
|
195
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
196
|
+
requirements:
|
197
|
+
- - '>='
|
198
|
+
- !ruby/object:Gem::Version
|
199
|
+
version: '0'
|
200
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - '>='
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: '0'
|
205
|
+
requirements: []
|
206
|
+
rubyforge_project:
|
207
|
+
rubygems_version: 2.0.14
|
208
|
+
signing_key:
|
209
|
+
specification_version: 4
|
210
|
+
summary: Effortless ZMQ
|
211
|
+
test_files: []
|
212
|
+
has_rdoc:
|