fluffle 0.2.0 → 0.2.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 +4 -4
- data/README.md +39 -5
- data/examples/client.rb +2 -0
- data/examples/server.rb +1 -1
- data/lib/fluffle/client.rb +3 -3
- data/lib/fluffle/connectable.rb +7 -1
- data/lib/fluffle/server.rb +3 -2
- data/lib/fluffle/version.rb +1 -1
- data/spec/client_spec.rb +27 -0
- data/spec/handlers/delegator_spec.rb +26 -0
- data/spec/handlers/dispatcher_spec.rb +27 -0
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 255eee82ad3d15d6a7b9623e2abc52327c0b029c
|
|
4
|
+
data.tar.gz: 9d0496f43f6f63e85b8de2d861d516959ec92cb5
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5dad9fde293a176c4b3f9cfe1c8dcc3cee2359f683db422d3e8a1f0273be9d84e57b5c24b1bd044a8f7416db58fa9d96551c87d4c1c19ee1e75ad31df9165e8c
|
|
7
|
+
data.tar.gz: 1d5e676a4db1978eda8e987c56d045ae137cd06345917ad10a0678db108d1b18d8240f9c2361ed47b00f4d512690443e3910fa99450e412198bd460b86e8cce7
|
data/README.md
CHANGED
|
@@ -14,8 +14,10 @@ An implementation of [JSON-RPC][] over RabbitMQ through the [Bunny][] library. P
|
|
|
14
14
|
|
|
15
15
|
## Features
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
Both the client and server implementations should be thread-safe, as their behavior is implemented on top of the excellent [concurrent-ruby][] gem's data structures.
|
|
18
|
+
|
|
19
|
+
- Client: Thread-safe client that can perform multiple requests concurrently
|
|
20
|
+
- Server: Single or multi-threaded server (one request/response per thread)
|
|
19
21
|
- Server: Easy-to-use built-in handlers and straightforward API for building custom handlers
|
|
20
22
|
|
|
21
23
|
[concurrent-ruby]: https://github.com/ruby-concurrency/concurrent-ruby
|
|
@@ -26,9 +28,41 @@ See the [`examples`](examples/) directory.
|
|
|
26
28
|
|
|
27
29
|
The server provides a few options for handling RPC requests:
|
|
28
30
|
|
|
29
|
-
- Dispatcher
|
|
30
|
-
- Delegator
|
|
31
|
-
- Custom: any handler needs to implement the API described in `Fluffle::Handlers::Base`
|
|
31
|
+
- [Dispatcher](lib/fluffle/handlers/dispatcher.rb): `dispatcher.handle('upcase') { |str| str.upcase }`
|
|
32
|
+
- [Delegator](lib/fluffle/handlers/delegator.rb): delegate will receive the `#upcase` message with a single argument (the string)
|
|
33
|
+
- Custom: any handler needs to implement the API described in [`Fluffle::Handlers::Base`](lib/fluffle/handlers/base.rb)
|
|
34
|
+
|
|
35
|
+
### Basic server and client
|
|
36
|
+
|
|
37
|
+
A server has two basic requirements: the URL of a RabbitMQ server to connect to and one or more queues to drain (with a handler for each queue).
|
|
38
|
+
|
|
39
|
+
Below is a basic server providing an `upcase` method to return the upper cased version of its argument:
|
|
40
|
+
|
|
41
|
+
```ruby
|
|
42
|
+
require 'fluffle'
|
|
43
|
+
|
|
44
|
+
server = Fluffle::Server.new url: 'amqp://localhost'
|
|
45
|
+
|
|
46
|
+
server.drain do |dispatcher|
|
|
47
|
+
dispatcher.handle('upcase') { |str| str.upcase }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
server.start
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
This example relies on a couple features of `Server#drain`:
|
|
54
|
+
|
|
55
|
+
1. By default it will drain the `default` queue.
|
|
56
|
+
2. You can provide a block to the method to have it set up a [`Dispatcher`](lib/fluffle/handlers/dispatcher.rb) handler and pass that in to the block.
|
|
57
|
+
|
|
58
|
+
And client to call that `upcase` method looks like:
|
|
59
|
+
|
|
60
|
+
```ruby
|
|
61
|
+
client = Fluffle::Client.new url: 'amqp://localhost'
|
|
62
|
+
|
|
63
|
+
client.call 'upcase', ['Hello world!']
|
|
64
|
+
# => "HELLO WORLD!"
|
|
65
|
+
```
|
|
32
66
|
|
|
33
67
|
## License
|
|
34
68
|
|
data/examples/client.rb
CHANGED
|
@@ -4,6 +4,8 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
4
4
|
require 'fluffle'
|
|
5
5
|
|
|
6
6
|
client = Fluffle::Client.new url: 'amqp://localhost'
|
|
7
|
+
# You can also pass `connection:` to use an existing Bunny connection:
|
|
8
|
+
# Fluffle::Client.new(connection: Bunny.new('amqp://localhost', heartbeat: 2))
|
|
7
9
|
|
|
8
10
|
timings = 10.times.map do
|
|
9
11
|
t0 = Time.now
|
data/examples/server.rb
CHANGED
|
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
|
3
3
|
|
|
4
4
|
require 'fluffle'
|
|
5
5
|
|
|
6
|
-
server = Fluffle::Server.new url: 'amqp://localhost'
|
|
6
|
+
server = Fluffle::Server.new url: 'amqp://localhost', concurrency: 5
|
|
7
7
|
|
|
8
8
|
server.drain do |dispatcher|
|
|
9
9
|
dispatcher.handle('foo') { 'bar' }
|
data/lib/fluffle/client.rb
CHANGED
|
@@ -12,12 +12,12 @@ module Fluffle
|
|
|
12
12
|
attr_accessor :default_timeout
|
|
13
13
|
attr_accessor :logger
|
|
14
14
|
|
|
15
|
-
def initialize(url:)
|
|
15
|
+
def initialize(url: nil, connection: nil)
|
|
16
|
+
self.connect(url || connection)
|
|
17
|
+
|
|
16
18
|
@default_timeout = 5
|
|
17
19
|
@logger = Fluffle.logger
|
|
18
20
|
|
|
19
|
-
self.connect url
|
|
20
|
-
|
|
21
21
|
@uuid = UUIDTools::UUID.timestamp_create.to_s
|
|
22
22
|
@channel = @connection.create_channel
|
|
23
23
|
@exchange = @channel.default_exchange
|
data/lib/fluffle/connectable.rb
CHANGED
data/lib/fluffle/server.rb
CHANGED
|
@@ -6,8 +6,9 @@ module Fluffle
|
|
|
6
6
|
|
|
7
7
|
# url: - Optional URL to pass to `Bunny.new` to immediately connect
|
|
8
8
|
# concurrency: - Number of threads to handle messages on (default: 1)
|
|
9
|
-
def initialize(url: nil, concurrency: 1)
|
|
10
|
-
|
|
9
|
+
def initialize(url: nil, connection: nil, concurrency: 1)
|
|
10
|
+
url_or_connection = url || connection
|
|
11
|
+
self.connect(url_or_connection) if url_or_connection
|
|
11
12
|
|
|
12
13
|
@handlers = {}
|
|
13
14
|
@handler_pool = Concurrent::FixedThreadPool.new concurrency
|
data/lib/fluffle/version.rb
CHANGED
data/spec/client_spec.rb
CHANGED
|
@@ -13,6 +13,33 @@ describe Fluffle::Client do
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
describe '#initialize' do
|
|
17
|
+
it 'allows user to pass an `amqp://` URL via `url:`' do
|
|
18
|
+
client = Fluffle::Client.new url: 'amqp://localhost'
|
|
19
|
+
|
|
20
|
+
expect(client.connection).to be_a Bunny::Session
|
|
21
|
+
expect(client.connected?).to eq true
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'allows user to provide existing Bunny connection via `connection:`' do
|
|
25
|
+
bunny_channel = double 'Bunny::Channel',
|
|
26
|
+
default_exchange: double('Bunny::Exchange'),
|
|
27
|
+
queue: double('Bunny::Queue', subscribe: nil)
|
|
28
|
+
|
|
29
|
+
bunny_session = double 'Bunny::Session',
|
|
30
|
+
create_channel: bunny_channel,
|
|
31
|
+
start: nil,
|
|
32
|
+
connected?: true
|
|
33
|
+
|
|
34
|
+
allow(bunny_session).to receive(:is_a?).with(Bunny::Session).and_return(true)
|
|
35
|
+
|
|
36
|
+
client = Fluffle::Client.new connection: bunny_session
|
|
37
|
+
|
|
38
|
+
expect(client.connection).to eq bunny_session
|
|
39
|
+
expect(client.connected?).to eq true
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
16
43
|
describe '#call' do
|
|
17
44
|
def prepare_response(payload)
|
|
18
45
|
->(id) do
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Fluffle::Handlers::Delegator do
|
|
4
|
+
before do
|
|
5
|
+
@delegated_object = double 'Delegated Object'
|
|
6
|
+
|
|
7
|
+
@handler = Fluffle::Handlers::Delegator.new @delegated_object
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'calls the method with the params on the delegated object' do
|
|
11
|
+
param1 = 'One'
|
|
12
|
+
param2 = 'Two'
|
|
13
|
+
result = 'Three'
|
|
14
|
+
|
|
15
|
+
expect(@delegated_object).to receive(:some_method)
|
|
16
|
+
.with(param1, param2)
|
|
17
|
+
.and_return(result)
|
|
18
|
+
|
|
19
|
+
actual_result = @handler.call id: 'abc123',
|
|
20
|
+
method: 'some_method',
|
|
21
|
+
params: [param1, param2],
|
|
22
|
+
meta: {}
|
|
23
|
+
|
|
24
|
+
expect(actual_result).to eq(result)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Fluffle::Handlers::Dispatcher do
|
|
4
|
+
before do
|
|
5
|
+
@handler = Fluffle::Handlers::Dispatcher.new
|
|
6
|
+
|
|
7
|
+
@handler.handle('double_it') { |arg| arg * 2 }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'calls the method with the params on the delegated object' do
|
|
11
|
+
result = @handler.call id: 'abc123',
|
|
12
|
+
method: 'double_it',
|
|
13
|
+
params: [2],
|
|
14
|
+
meta: {}
|
|
15
|
+
|
|
16
|
+
expect(result).to eq(4)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'raises error if method not configured' do
|
|
20
|
+
expect {
|
|
21
|
+
@handler.call id: 'def456',
|
|
22
|
+
method: 'doesnt_exist',
|
|
23
|
+
params: ['whatever'],
|
|
24
|
+
meta: {}
|
|
25
|
+
}.to raise_error(NoMethodError, /doesnt_exist/)
|
|
26
|
+
end
|
|
27
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fluffle
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dirk Gadsden
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2016-08-
|
|
11
|
+
date: 2016-08-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bunny
|
|
@@ -139,6 +139,8 @@ files:
|
|
|
139
139
|
- lib/fluffle/testing.rb
|
|
140
140
|
- lib/fluffle/version.rb
|
|
141
141
|
- spec/client_spec.rb
|
|
142
|
+
- spec/handlers/delegator_spec.rb
|
|
143
|
+
- spec/handlers/dispatcher_spec.rb
|
|
142
144
|
- spec/server_spec.rb
|
|
143
145
|
- spec/spec_helper.rb
|
|
144
146
|
homepage: https://github.com/Everlane/fluffle
|