lagomorph 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/lagomorph/supervisor.rb +9 -6
- data/lib/lagomorph/version.rb +1 -1
- data/spec/concurrency_spec.rb +107 -0
- data/spec/lagomorph_spec.rb +20 -58
- data/spec/pong_worker.rb +19 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2d20cf2cb1f8a168b4ebb17fc72be5fbf8a0e50
|
4
|
+
data.tar.gz: 7031959395e7240bfa4949f36c882faf827cf500
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56c80bb6be3859710bbd42f5dec9476ab69e497f905bad332cbb2a77d4ed3e46f2753b5f9eb5507aebbed3bfe271acb0e0f4d2154fd64e017b3e542b8bce5db9
|
7
|
+
data.tar.gz: 147ec08b33614f341cda169b93adb711bea58d159fb79350a7c0e601effd4123142c597cae2f1d81e239a463c3218efb45916b4612edbd94f27465f3ad5c6b3e
|
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Lagomorph
|
2
2
|
|
3
|
-
[![Gem Version](https://badge.fury.io/rb/
|
3
|
+
[![Gem Version](https://badge.fury.io/rb/lagomorph.png)](http://badge.fury.io/rb/lagomorph)
|
4
4
|
[![Build Status](https://travis-ci.org/sealink/lagomorph.png?branch=master)](https://travis-ci.org/sealink/lagomorph)
|
5
5
|
[![Coverage Status](https://coveralls.io/repos/sealink/lagomorph/badge.png)](https://coveralls.io/r/sealink/lagomorph)
|
6
6
|
[![Dependency Status](https://gemnasium.com/sealink/lagomorph.png)](https://gemnasium.com/sealink/lagomorph)
|
data/lib/lagomorph/supervisor.rb
CHANGED
@@ -8,14 +8,17 @@ module Lagomorph
|
|
8
8
|
@session = session
|
9
9
|
end
|
10
10
|
|
11
|
-
def route(queue_name, worker_class)
|
12
|
-
prefetch
|
13
|
-
durable
|
11
|
+
def route(queue_name, worker_class, options = {})
|
12
|
+
prefetch = options.fetch :prefetch, 10
|
13
|
+
durable = options.fetch :durable, false
|
14
|
+
subscribers = options.fetch :subscribers, 1
|
14
15
|
|
15
|
-
|
16
|
-
|
16
|
+
subscribers.times.map do
|
17
|
+
channel = @session.create_channel(prefetch)
|
18
|
+
queue = QueueBuilder.new(channel).queue(queue_name, durable: durable)
|
17
19
|
|
18
|
-
|
20
|
+
Subscriber.new(worker_class).subscribe(queue, channel)
|
21
|
+
end
|
19
22
|
end
|
20
23
|
|
21
24
|
end
|
data/lib/lagomorph/version.rb
CHANGED
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'benchmark'
|
4
|
+
|
5
|
+
require 'yaml'
|
6
|
+
require 'lagomorph/session'
|
7
|
+
require 'lagomorph/supervisor'
|
8
|
+
require 'lagomorph/subscriber'
|
9
|
+
require 'lagomorph/rpc_call'
|
10
|
+
require 'lagomorph/exceptions'
|
11
|
+
|
12
|
+
require 'pong_worker'
|
13
|
+
|
14
|
+
describe 'a Lagomorph RPC process' do
|
15
|
+
|
16
|
+
let(:rabbitmq_config) {
|
17
|
+
YAML.load_file(
|
18
|
+
File.join(File.expand_path(File.dirname(__FILE__)),'rabbitmq.yml')
|
19
|
+
)
|
20
|
+
}
|
21
|
+
|
22
|
+
context 'when supervising a PongWorker on the ping queue' do
|
23
|
+
let(:connection_params) {
|
24
|
+
{
|
25
|
+
host: rabbitmq_config.fetch('host'),
|
26
|
+
username: rabbitmq_config.fetch('username'),
|
27
|
+
password: rabbitmq_config.fetch('password')
|
28
|
+
}
|
29
|
+
}
|
30
|
+
|
31
|
+
let(:session) { Lagomorph::Session.connect(connection_params) }
|
32
|
+
|
33
|
+
let(:supervisor) { Lagomorph::Supervisor.new(session) }
|
34
|
+
|
35
|
+
let(:queue) { 'ping' }
|
36
|
+
|
37
|
+
context 'with tasks of varying completion time' do
|
38
|
+
let(:queue) { 'sleep' }
|
39
|
+
let!(:rpc_call) { Lagomorph::RpcCall.new(session) }
|
40
|
+
let!(:results) { [] }
|
41
|
+
let(:threads) {
|
42
|
+
2.times.map {
|
43
|
+
Thread.new { results << rpc_call.dispatch(queue, 'nap', 1) }
|
44
|
+
}
|
45
|
+
}
|
46
|
+
let(:execution_time) {
|
47
|
+
Benchmark.realtime { threads.each(&:join) }
|
48
|
+
}
|
49
|
+
|
50
|
+
before do
|
51
|
+
supervisor.route queue, PongWorker, subscribers: number_subscribers
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with only one subscriber' do
|
55
|
+
let(:number_subscribers) { 1 }
|
56
|
+
it 'will return results after the sum of the execution time' do
|
57
|
+
expect(execution_time).to be > 2
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with multiple subscribers' do
|
62
|
+
let(:number_subscribers) { 2 }
|
63
|
+
it 'will return results before the sum of the execution time' do
|
64
|
+
expect(execution_time).to be < 2
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
after do
|
69
|
+
rpc_call.close_channel
|
70
|
+
session.close_connection
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'when using 8 threads, with one instance per thread' do
|
75
|
+
before do
|
76
|
+
supervisor.route queue, PongWorker
|
77
|
+
end
|
78
|
+
|
79
|
+
let(:number_of_threads) { 8 }
|
80
|
+
let(:total_calls) { 800 }
|
81
|
+
let(:calls_per_thread) { (total_calls / number_of_threads).ceil }
|
82
|
+
|
83
|
+
let(:rpc_calls) {
|
84
|
+
1.upto(number_of_threads).map { Lagomorph::RpcCall.new(session) }
|
85
|
+
}
|
86
|
+
|
87
|
+
specify 'each thread will get the expected response' do
|
88
|
+
rpc_calls.map do |rpc_call|
|
89
|
+
Thread.new do
|
90
|
+
calls_per_thread.times.map { |call_index|
|
91
|
+
rpc_call.dispatch(queue, 'echo', call_index).tap { |result|
|
92
|
+
expect(result).to eq call_index
|
93
|
+
}
|
94
|
+
}
|
95
|
+
end
|
96
|
+
end.each(&:join)
|
97
|
+
|
98
|
+
rpc_calls.each(&:close_channel)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
after do
|
103
|
+
session.close_connection
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
data/spec/lagomorph_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
|
2
3
|
require 'yaml'
|
3
4
|
require 'lagomorph/session'
|
4
5
|
require 'lagomorph/supervisor'
|
@@ -6,6 +7,8 @@ require 'lagomorph/subscriber'
|
|
6
7
|
require 'lagomorph/rpc_call'
|
7
8
|
require 'lagomorph/exceptions'
|
8
9
|
|
10
|
+
require 'pong_worker'
|
11
|
+
|
9
12
|
describe 'a Lagomorph RPC process' do
|
10
13
|
|
11
14
|
let(:rabbitmq_config) {
|
@@ -14,20 +17,6 @@ describe 'a Lagomorph RPC process' do
|
|
14
17
|
)
|
15
18
|
}
|
16
19
|
|
17
|
-
class PongWorker < Lagomorph::Worker
|
18
|
-
def pong
|
19
|
-
'pong'
|
20
|
-
end
|
21
|
-
|
22
|
-
def echo(request)
|
23
|
-
request
|
24
|
-
end
|
25
|
-
|
26
|
-
def generate_failure
|
27
|
-
fail 'Could not process request'
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
20
|
context 'when supervising a PongWorker on the ping queue' do
|
32
21
|
let(:connection_params) {
|
33
22
|
{
|
@@ -47,58 +36,31 @@ describe 'a Lagomorph RPC process' do
|
|
47
36
|
supervisor.route queue, PongWorker
|
48
37
|
end
|
49
38
|
|
50
|
-
|
51
|
-
let!(:rpc_call) { Lagomorph::RpcCall.new(session) }
|
52
|
-
|
53
|
-
context 'when a pong rpc call is made on the ping queue' do
|
54
|
-
let(:result) { rpc_call.dispatch(queue, 'pong') }
|
55
|
-
it { expect(result).to eq 'pong' }
|
56
|
-
end
|
57
|
-
|
58
|
-
context 'when an echo rpc call is made on the ping queue' do
|
59
|
-
let(:result) { rpc_call.dispatch(queue, 'echo', 'test') }
|
60
|
-
it { expect(result).to eq 'test' }
|
61
|
-
end
|
62
|
-
|
63
|
-
context 'when a worker for an rpc call yields a nil result' do
|
64
|
-
let(:result) { rpc_call.dispatch(queue, 'echo', nil) }
|
65
|
-
it { expect(result).to eq nil }
|
66
|
-
end
|
39
|
+
let!(:rpc_call) { Lagomorph::RpcCall.new(session) }
|
67
40
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
'Could not process request' }
|
72
|
-
end
|
73
|
-
|
74
|
-
after { rpc_call.close_channel }
|
41
|
+
context 'when a pong rpc call is made on the ping queue' do
|
42
|
+
let(:result) { rpc_call.dispatch(queue, 'pong') }
|
43
|
+
it { expect(result).to eq 'pong' }
|
75
44
|
end
|
76
45
|
|
77
|
-
context 'when
|
78
|
-
let(:
|
79
|
-
|
80
|
-
|
46
|
+
context 'when an echo rpc call is made on the ping queue' do
|
47
|
+
let(:result) { rpc_call.dispatch(queue, 'echo', 'test') }
|
48
|
+
it { expect(result).to eq 'test' }
|
49
|
+
end
|
81
50
|
|
82
|
-
|
83
|
-
|
84
|
-
}
|
51
|
+
context 'when a worker for an rpc call yields a nil result' do
|
52
|
+
let(:result) { rpc_call.dispatch(queue, 'echo', nil) }
|
53
|
+
it { expect(result).to eq nil }
|
54
|
+
end
|
85
55
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
rpc_call.dispatch(queue, 'echo', call_index).tap { |result|
|
91
|
-
expect(result).to eq call_index
|
92
|
-
}
|
93
|
-
}
|
94
|
-
end
|
95
|
-
end.each(&:join)
|
96
|
-
|
97
|
-
rpc_calls.each(&:close_channel)
|
98
|
-
end
|
56
|
+
context 'when a method which fails is made on the ping queue' do
|
57
|
+
let(:result) { rpc_call.dispatch(queue, 'generate_failure') }
|
58
|
+
it { expect { result }.to raise_error Lagomorph::RpcError,
|
59
|
+
'Could not process request' }
|
99
60
|
end
|
100
61
|
|
101
62
|
after do
|
63
|
+
rpc_call.close_channel
|
102
64
|
session.close_connection
|
103
65
|
end
|
104
66
|
end
|
data/spec/pong_worker.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lagomorph
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alessandro Berardi
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-11-
|
12
|
+
date: 2014-11-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -155,7 +155,9 @@ files:
|
|
155
155
|
- lib/lagomorph/supervisor.rb
|
156
156
|
- lib/lagomorph/version.rb
|
157
157
|
- lib/lagomorph/worker.rb
|
158
|
+
- spec/concurrency_spec.rb
|
158
159
|
- spec/lagomorph_spec.rb
|
160
|
+
- spec/pong_worker.rb
|
159
161
|
- spec/rabbitmq.yml.example
|
160
162
|
- spec/spec_helper.rb
|
161
163
|
homepage: ''
|
@@ -183,6 +185,8 @@ signing_key:
|
|
183
185
|
specification_version: 4
|
184
186
|
summary: RPC Messaging pattern using RabbitMQ
|
185
187
|
test_files:
|
188
|
+
- spec/concurrency_spec.rb
|
186
189
|
- spec/lagomorph_spec.rb
|
190
|
+
- spec/pong_worker.rb
|
187
191
|
- spec/rabbitmq.yml.example
|
188
192
|
- spec/spec_helper.rb
|