lagomorph 0.0.6 → 0.0.7
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/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
|
-
[](http://badge.fury.io/rb/lagomorph)
|
4
4
|
[](https://travis-ci.org/sealink/lagomorph)
|
5
5
|
[](https://coveralls.io/r/sealink/lagomorph)
|
6
6
|
[](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
|