haredo 2.0.9 → 3.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +68 -0
- data/README.md +53 -18
- data/src/lib/haredo/peer.rb +70 -23
- data/src/lib/haredo/plugin.rb +1 -1
- data/src/lib/haredo/service/config.rb +1 -1
- data/src/lib/haredo/service/daemon.rb +0 -12
- data/src/lib/haredo/version.rb +4 -4
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ef90f8c4b3c742587932fa39460612e48d394d9
|
4
|
+
data.tar.gz: e83d8563ce838be478d7c3be168e591370c44f89
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10a9b48836ea8291b7fc7f92d3be421157392d73f87d73cf7490f24fe2141e60e3e0bf80a556328a1fef2b0d97d65610fa95660fc87c42ca11b1de0f56284f89
|
7
|
+
data.tar.gz: 183c7a614608a0ee93bbe18f489706e38201694f3397fcf33f9894ff3e3eb5fbab05de345d46962729b586777db65148a5f5365e77482bbf4cc476797272bedf
|
data/CHANGES.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
## Version 3.0
|
4
|
+
|
5
|
+
### `Peer`
|
6
|
+
|
7
|
+
`@queue_name` has been removed. This is replaced by optional argument in
|
8
|
+
`Peer::listen()`.
|
9
|
+
|
10
|
+
`@name` attribute added. Taken from constructor. This is a convenience variable
|
11
|
+
for generic identification. It is not used for anything.
|
12
|
+
|
13
|
+
### `Peer::listen(args={})`:
|
14
|
+
|
15
|
+
No longer creates a new queue by default. It will use the default private
|
16
|
+
queue. If you provide a `queue` argument, then it will create a new queue and
|
17
|
+
keep track of it as a listen queue internally which will be destroyed on
|
18
|
+
`disconnect()`. Also takes an optional `exchange` argument. If provided, it will
|
19
|
+
bind the new queue to that exchange.
|
20
|
+
|
21
|
+
For example say you want to create a service which listens on its private
|
22
|
+
queue. Furthermore you want to receive messages on the default AMQP Fanout
|
23
|
+
queue. Here's a working example:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
#!/usr/bin/env ruby
|
27
|
+
|
28
|
+
require 'haredo/peer'
|
29
|
+
|
30
|
+
$mq_host = 'localhost'
|
31
|
+
$mq_username = 'guest'
|
32
|
+
$mq_password = 'guest'
|
33
|
+
$queue = 'doesntmatter'
|
34
|
+
|
35
|
+
class Service < HareDo::Peer
|
36
|
+
|
37
|
+
def initialize(name)
|
38
|
+
super name
|
39
|
+
connect( :host => $mq_host,
|
40
|
+
:user => $mq_username,
|
41
|
+
:password => $mq_password,
|
42
|
+
:vhost => '' )
|
43
|
+
|
44
|
+
@queue.bind('amq.fanout')
|
45
|
+
end
|
46
|
+
|
47
|
+
def serve(msg)
|
48
|
+
dump_message msg
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
service = Service.new('service')
|
54
|
+
service.listen({:blocking=>false})
|
55
|
+
|
56
|
+
# Client
|
57
|
+
|
58
|
+
client = HareDo::Peer.new()
|
59
|
+
client.connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
60
|
+
|
61
|
+
client.exchange = client.channel.fanout('amq.fanout')
|
62
|
+
client.send($queue, :headers => { :testing => 1 })
|
63
|
+
|
64
|
+
# Cleanup
|
65
|
+
|
66
|
+
client.disconnect()
|
67
|
+
service.disconnect()
|
68
|
+
```
|
data/README.md
CHANGED
@@ -2,8 +2,25 @@
|
|
2
2
|
|
3
3
|
## About
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
I'll bet that most people don't realize that when they use RabbitMQ they are
|
6
|
+
actually using the core software that runs big-freaking telecom systems (OTP --
|
7
|
+
Open Telecom Platform). That in itself is reason enough to consider RabbitMQ.
|
8
|
+
|
9
|
+
But RabbitMQ uses both an elegant but also somewhat elaborate model called AMQP
|
10
|
+
0-9-1. Notice the 0-9-1. This is important. Versions later than this are
|
11
|
+
crap. 0-9-1 is a work of pure genius and art which was later utterly mauled by
|
12
|
+
committees. Fortunately enough for you, RabbitMQ is and most likely always will
|
13
|
+
be AMQP 0-9-1. Hurray!
|
14
|
+
|
15
|
+
But the bottom line is this: You might be one of those pragmatic people that
|
16
|
+
doesn't want to have to know everything about AMQP. You want just want that
|
17
|
+
fancy telecom thing-a-majigger software to pump massive volumes of your messages
|
18
|
+
from one place to another using Ruby and give you 5 9's doing it.
|
19
|
+
|
20
|
+
If that's true for you then you've come to the right place.
|
21
|
+
|
22
|
+
Haredo is an easy-to-use framework for creating peer-to-peer applications in
|
23
|
+
Ruby via [RabbitMQ](http://www.rabbitmq.com/). Built atop the [Bunny AMQP
|
7
24
|
client](http://rubybunny.info/), it uses a small subset of RabbitMQ's
|
8
25
|
capabilities to provide an intuitive client/server framework for implementing
|
9
26
|
network services and simple peer to peer applications. It is specifically
|
@@ -40,6 +57,8 @@ this below).
|
|
40
57
|
```ruby
|
41
58
|
#!/usr/bin/env ruby
|
42
59
|
|
60
|
+
require 'haredo/peer'
|
61
|
+
|
43
62
|
$mq_host = 'localhost'
|
44
63
|
$mq_username = 'guest'
|
45
64
|
$mq_password = 'guest'
|
@@ -53,6 +72,7 @@ class Service < HareDo::Peer
|
|
53
72
|
end
|
54
73
|
|
55
74
|
def serve(msg)
|
75
|
+
#dump_message msg
|
56
76
|
data = msg.headers['i'].to_i + 1
|
57
77
|
reply(msg, :data => data.to_s)
|
58
78
|
end
|
@@ -60,14 +80,14 @@ class Service < HareDo::Peer
|
|
60
80
|
end
|
61
81
|
|
62
82
|
service = Service.new($queue)
|
63
|
-
service.listen(:blocking => false)
|
83
|
+
service.listen(:queue => $queue, :blocking => false)
|
64
84
|
|
65
85
|
client = HareDo::Peer.new()
|
66
86
|
client.connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
67
87
|
|
68
88
|
1.upto(10) do |i|
|
69
|
-
client.send($queue, :headers => { :i => i })
|
70
|
-
msg =
|
89
|
+
id = client.send($queue, :headers => { :i => i })
|
90
|
+
msg = client.receive(id)
|
71
91
|
|
72
92
|
puts msg.data.to_i == i + 1
|
73
93
|
end
|
@@ -134,6 +154,10 @@ class Service < HareDo::Peer
|
|
134
154
|
connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
135
155
|
end
|
136
156
|
|
157
|
+
def listen()
|
158
|
+
super :queue => @name
|
159
|
+
end
|
160
|
+
|
137
161
|
def serve(msg)
|
138
162
|
# Log the message somewhere
|
139
163
|
end
|
@@ -187,13 +211,17 @@ class Service < HareDo::Peer
|
|
187
211
|
connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
188
212
|
end
|
189
213
|
|
214
|
+
def listen()
|
215
|
+
super :queue => @name, :blocking => false
|
216
|
+
end
|
217
|
+
|
190
218
|
def serve(msg)
|
191
219
|
# Log the data somewhere
|
192
220
|
end
|
193
221
|
|
194
222
|
end
|
195
223
|
|
196
|
-
Service.new('logger').listen(
|
224
|
+
Service.new('logger').listen()
|
197
225
|
|
198
226
|
client = HareDo::Peer.new()
|
199
227
|
client.connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
@@ -206,10 +234,13 @@ client.disconnect()
|
|
206
234
|
### Send/Receive
|
207
235
|
|
208
236
|
The send/receive pattern is illustrated in the initial example -- the client
|
209
|
-
sends out ten integers and wait for the response.
|
210
|
-
|
211
|
-
|
212
|
-
|
237
|
+
sends out ten integers and wait for the response. Each time is calls send() it
|
238
|
+
gets a correlation ID as the return value. It passed this ID into receive()
|
239
|
+
which then looks for a return message with that correlation ID. This is how you
|
240
|
+
ensure you get back the message you are looking for (as opposed to some other
|
241
|
+
message that happened to arrive). While the responses come back in the correct
|
242
|
+
order in this example, there is no guarantee that this will happen every
|
243
|
+
time. This is why the correlation ID is important.
|
213
244
|
|
214
245
|
### Remote Procedure Call
|
215
246
|
|
@@ -240,7 +271,7 @@ class Service < HareDo::Peer
|
|
240
271
|
end
|
241
272
|
|
242
273
|
service = Service.new('rpc')
|
243
|
-
service.listen(:blocking => false)
|
274
|
+
service.listen(:queue => service.name, :blocking => false)
|
244
275
|
|
245
276
|
client = HareDo::Peer.new()
|
246
277
|
client.connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
@@ -326,7 +357,7 @@ class Service < HareDo::Peer
|
|
326
357
|
end
|
327
358
|
end
|
328
359
|
|
329
|
-
Service.new('rpc').listen()
|
360
|
+
Service.new('rpc').listen(queue => service.name)
|
330
361
|
service.disconnect()
|
331
362
|
```
|
332
363
|
|
@@ -389,13 +420,15 @@ Now I can implement my service and call it as follows:
|
|
389
420
|
```ruby
|
390
421
|
#!/usr/bin/env ruby
|
391
422
|
|
392
|
-
|
423
|
+
$queue = 'myservice'
|
424
|
+
|
425
|
+
service = HareDo::Peer.new($queue)
|
393
426
|
service.plugins.load('echo')
|
394
|
-
service.listen(:blocking => false)
|
427
|
+
service.listen(queue => service.name, :blocking => false)
|
395
428
|
|
396
429
|
client = HareDo::Peer.new()
|
397
430
|
client.connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
398
|
-
response = @client.call(
|
431
|
+
response = @client.call($queue, headers=>{:uuid=>'echo'}, :data=>'jujifruit')
|
399
432
|
|
400
433
|
client.disconnect()
|
401
434
|
service.disconnect()
|
@@ -453,7 +486,9 @@ For example:
|
|
453
486
|
```ruby
|
454
487
|
#!/usr/bin/env ruby
|
455
488
|
|
456
|
-
|
489
|
+
$queue = 'myservice'
|
490
|
+
|
491
|
+
service = HareDo::Peer.new($queue)
|
457
492
|
|
458
493
|
# Load modules from configuration
|
459
494
|
config = {
|
@@ -463,11 +498,11 @@ config = {
|
|
463
498
|
}
|
464
499
|
|
465
500
|
service.plugins.loadConfig(config)
|
466
|
-
service.listen(:blocking => false)
|
501
|
+
service.listen(:queue => $queue, :blocking => false)
|
467
502
|
|
468
503
|
client = HareDo::Peer.new()
|
469
504
|
client.connect(:user=>$mq_username, :password=>$mq_password, :host=>$mq_host)
|
470
|
-
response = @client.call(
|
505
|
+
response = @client.call($queue, headers=>{:uuid=>'example'}, :data => 'jujifruit')
|
471
506
|
|
472
507
|
service.disconnect()
|
473
508
|
client.disconnect()
|
data/src/lib/haredo/peer.rb
CHANGED
@@ -2,9 +2,14 @@ require 'syslog'
|
|
2
2
|
require 'bunny'
|
3
3
|
require 'haredo/version'
|
4
4
|
|
5
|
-
def dump_message(msg, name)
|
5
|
+
def dump_message(msg, name=nil)
|
6
6
|
puts name if name
|
7
7
|
|
8
|
+
if msg.nil?
|
9
|
+
puts 'Message is nil'
|
10
|
+
return
|
11
|
+
end
|
12
|
+
|
8
13
|
if msg.properties != nil
|
9
14
|
puts ' Headers:'
|
10
15
|
msg.properties.each do |k,v|
|
@@ -157,8 +162,8 @@ end # module Plugins
|
|
157
162
|
|
158
163
|
class Peer
|
159
164
|
|
160
|
-
attr_reader :queue, :plugins, :mid
|
161
|
-
attr_accessor :timeout, :sleep_interval
|
165
|
+
attr_reader :queue, :plugins, :mid, :name
|
166
|
+
attr_accessor :timeout, :sleep_interval, :channel, :exchange
|
162
167
|
attr_accessor :trace
|
163
168
|
|
164
169
|
def initialize(name=nil)
|
@@ -171,16 +176,14 @@ class Peer
|
|
171
176
|
@receive_queue = {}
|
172
177
|
@trace = false
|
173
178
|
|
174
|
-
# Server attributes
|
175
|
-
# The queue name used for listen()
|
176
|
-
@queue_name = name
|
177
|
-
|
178
179
|
@listen_queues = []
|
179
180
|
|
180
181
|
# The number of messages to prefecth from Rabbit
|
181
182
|
@prefetch = 10
|
182
183
|
|
183
184
|
@plugins = Plugins::Manager.new(self)
|
185
|
+
|
186
|
+
@name = name
|
184
187
|
end
|
185
188
|
|
186
189
|
# Connect to RabbitMQ
|
@@ -206,19 +209,38 @@ class Peer
|
|
206
209
|
port = args[:port] || '5672'
|
207
210
|
vhost = args[:vhost] || ''
|
208
211
|
queue_props = args[:queue] || queue_args
|
212
|
+
exchange = args[:exchange] || ''
|
213
|
+
exclusive = args[:exclusive] || true
|
209
214
|
ssl = args[:ssl] || {}
|
210
|
-
tls_cert = ssl['tls_cert'] ||
|
211
|
-
tls_key = ssl['tls_key'] ||
|
212
|
-
tls_ca_certs =
|
215
|
+
tls_cert = ssl['tls_cert'] || nil
|
216
|
+
tls_key = ssl['tls_key'] || nil
|
217
|
+
tls_ca_certs = nil
|
213
218
|
|
219
|
+
if ssl['tls_cert']
|
220
|
+
tls_cert = ssl['tls_cert']
|
221
|
+
end
|
222
|
+
|
223
|
+
if ssl['tls_key']
|
224
|
+
tls_key = ssl['tls_key']
|
225
|
+
end
|
226
|
+
|
227
|
+
if ssl['tls_ca']
|
228
|
+
tls_ca_certs = [ssl['tls_ca']]
|
229
|
+
end
|
230
|
+
|
214
231
|
use_ssl = false
|
215
232
|
if ssl.size > 0 and ssl['enable'] == true
|
216
233
|
use_ssl = true
|
217
234
|
port = ssl['port'] || '5671'
|
218
235
|
end
|
219
236
|
|
237
|
+
if vhost == '/'
|
238
|
+
vhost = ''
|
239
|
+
end
|
240
|
+
|
220
241
|
if use_ssl == true
|
221
242
|
@cnx = Bunny.new( "amqps://#{user}:#{password}@#{host}:#{port}#{vhost}",
|
243
|
+
:log_file => '/dev/null',
|
222
244
|
:tls_cert => tls_cert,
|
223
245
|
:tls_key => tls_key,
|
224
246
|
:tls_ca_certificates => tls_ca_certs)
|
@@ -230,16 +252,18 @@ class Peer
|
|
230
252
|
|
231
253
|
@channel = @cnx.create_channel()
|
232
254
|
|
255
|
+
@channel.prefetch(@prefetch)
|
256
|
+
|
233
257
|
@queue = @channel.queue( '',
|
234
258
|
:auto_delete => true,
|
235
|
-
:exclusive
|
236
|
-
:arguments
|
259
|
+
:exclusive => exclusive,
|
260
|
+
:arguments => queue_props )
|
237
261
|
|
238
262
|
@exchange = @channel.default_exchange()
|
239
263
|
|
240
264
|
return true
|
241
265
|
end
|
242
|
-
|
266
|
+
|
243
267
|
# Disconnect from RabbitMQ
|
244
268
|
def disconnect()
|
245
269
|
|
@@ -407,27 +431,50 @@ class Peer
|
|
407
431
|
|
408
432
|
# Defined the queue this service will listen on. Assumes a single-instance
|
409
433
|
# service therefore declares queue as exclusive.
|
410
|
-
def createQueue()
|
411
|
-
|
434
|
+
def createQueue(args={})
|
435
|
+
|
436
|
+
queue_args = {
|
437
|
+
#'x-expires' => 30000
|
438
|
+
#'x-message-ttl' => 1000
|
439
|
+
}
|
440
|
+
|
441
|
+
queue_name = args[:queue]
|
442
|
+
queue_props = args[:properties] || queue_args
|
443
|
+
auto_delete = args[:auto_delete] || true
|
444
|
+
exclusive = true
|
445
|
+
|
446
|
+
if args.has_key?(:exclusive)
|
447
|
+
exclusive = args[:exclusive]
|
448
|
+
end
|
449
|
+
|
450
|
+
return @channel.queue( queue_name,
|
451
|
+
:auto_delete => true,
|
452
|
+
:exclusive => exclusive )
|
412
453
|
end
|
413
454
|
|
414
455
|
# Causes the service to listen for incoming messages.
|
415
456
|
#
|
416
457
|
# @param :blocking If this is set to true, will go into indefinite blocking
|
417
458
|
# loop processing incoming messages.
|
418
|
-
|
459
|
+
#
|
419
460
|
# @returns Returns nil if non-blocking. Never returns if blocking.
|
420
461
|
|
421
|
-
def listen(args)
|
422
|
-
listen_queue = createQueue()
|
462
|
+
def listen(args={})
|
423
463
|
|
424
|
-
|
464
|
+
queue = @queue
|
425
465
|
|
426
|
-
|
466
|
+
if args.has_key?(:queue)
|
467
|
+
listen_queue = createQueue(args)
|
468
|
+
@listen_queues << listen_queue
|
427
469
|
|
428
|
-
|
470
|
+
if args.has_key?(:exchange)
|
471
|
+
listen_queue.bind(args[:exchange])
|
472
|
+
end
|
429
473
|
|
430
|
-
|
474
|
+
queue = listen_queue
|
475
|
+
end
|
476
|
+
|
477
|
+
block = args[:blocking] || false
|
431
478
|
|
432
479
|
if $syslog.nil?
|
433
480
|
Syslog.open( "haredo #{@name}", Syslog::LOG_PID,
|
@@ -438,7 +485,7 @@ class Peer
|
|
438
485
|
|
439
486
|
Syslog.notice('listen()')
|
440
487
|
|
441
|
-
|
488
|
+
queue.subscribe(:block => block, :manual_ack => true) do |info, props, data|
|
442
489
|
@channel.acknowledge(info.delivery_tag, false)
|
443
490
|
if serve(RabbitMQ::Message.new(info, props, data)) == false
|
444
491
|
exit 0
|
data/src/lib/haredo/plugin.rb
CHANGED
@@ -14,7 +14,7 @@ module Config
|
|
14
14
|
# @return Returns PID of running daemon if it corresponds to a running
|
15
15
|
# process. Returns nil otherwise.
|
16
16
|
def daemonPid()
|
17
|
-
pid = File.open(@pid_file).read().strip.chomp
|
17
|
+
pid = File.open(@pid_file, 'a+').read().strip.chomp
|
18
18
|
|
19
19
|
return nil if pid.size == 0
|
20
20
|
|
@@ -1,18 +1,6 @@
|
|
1
1
|
require 'syslog'
|
2
2
|
require 'haredo/service/config'
|
3
3
|
|
4
|
-
def dump_message(msg)
|
5
|
-
if msg.properties != nil
|
6
|
-
puts ' Headers:'
|
7
|
-
msg.properties.each do |k,v|
|
8
|
-
puts " #{k}: #{v}"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
puts " Data: #{msg.data}"
|
13
|
-
puts
|
14
|
-
end
|
15
|
-
|
16
4
|
module HareDo
|
17
5
|
module Service
|
18
6
|
|
data/src/lib/haredo/version.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
# Version information. Auto-generated by CMake.
|
2
2
|
module HareDo
|
3
3
|
|
4
|
-
VERSION_MAJ = '
|
4
|
+
VERSION_MAJ = '3'
|
5
5
|
VERSION_MIN = '0'
|
6
6
|
VERSION_CL = ''
|
7
|
-
VERSION_PL = '
|
8
|
-
VERSION = '
|
9
|
-
RELEASE_DATE = 'Wed,
|
7
|
+
VERSION_PL = '2'
|
8
|
+
VERSION = '3.0.2-1'
|
9
|
+
RELEASE_DATE = 'Wed, 01 Aug 2018 17:30:02 -0500'
|
10
10
|
|
11
11
|
end # module HareDo
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haredo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Owens
|
8
8
|
autorequire:
|
9
9
|
bindir: src/bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bunny
|
@@ -31,7 +31,9 @@ executables:
|
|
31
31
|
extensions: []
|
32
32
|
extra_rdoc_files:
|
33
33
|
- README.md
|
34
|
+
- CHANGES.md
|
34
35
|
files:
|
36
|
+
- CHANGES.md
|
35
37
|
- README.md
|
36
38
|
- src/bin/haredo
|
37
39
|
- src/lib/haredo/admin/config.rb
|
@@ -65,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
65
67
|
version: '0'
|
66
68
|
requirements: []
|
67
69
|
rubyforge_project:
|
68
|
-
rubygems_version: 2.
|
70
|
+
rubygems_version: 2.5.2.1
|
69
71
|
signing_key:
|
70
72
|
specification_version: 4
|
71
73
|
summary: A simple client/server framework using RabbitMQ
|