fluffle 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/examples/testing.rb +23 -0
- data/lib/fluffle/client.rb +13 -16
- data/lib/fluffle/server.rb +3 -12
- data/lib/fluffle/testing.rb +134 -0
- data/lib/fluffle/version.rb +1 -1
- metadata +3 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a7267d1c8c0b56d933eb3e755e15541901aa4a5f
|
4
|
+
data.tar.gz: 0413ba9a5100acd9dbfef940c61f18ef8df4d0d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 04044d6fab23dc039b32b1fba003f18c070c77d07eddb1785de5b44296af97299f99d9e48eb8d189e719c9316bbe8dd7dd1e20f9d2ff2318287ebde5aae19157
|
7
|
+
data.tar.gz: 9bea8e8e0029b92eb4f97cc56b4ca1f8612627ab88a6bb95cbea524a9cacaabd3c71c181677f675292594941af2ec0b2130a32dd1caa162880c4679ef0ed4629
|
data/examples/testing.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
lib = File.join File.dirname(__FILE__), '..', 'lib'
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
|
4
|
+
require 'fluffle'
|
5
|
+
require 'fluffle/testing'
|
6
|
+
|
7
|
+
server = Fluffle::Server.new url: 'amqp://localhost'
|
8
|
+
|
9
|
+
server.drain do |dispatcher|
|
10
|
+
dispatcher.handle('foo') { 'bar' }
|
11
|
+
end
|
12
|
+
|
13
|
+
server.start
|
14
|
+
|
15
|
+
client = Fluffle::Client.new url: 'amqp://localhost'
|
16
|
+
|
17
|
+
timings = 10.times.map do
|
18
|
+
t0 = Time.now
|
19
|
+
client.call('foo').inspect
|
20
|
+
Time.now - t0
|
21
|
+
end
|
22
|
+
|
23
|
+
puts timings
|
data/lib/fluffle/client.rb
CHANGED
@@ -83,16 +83,22 @@ module Fluffle
|
|
83
83
|
end
|
84
84
|
end
|
85
85
|
|
86
|
-
protected
|
87
|
-
|
88
86
|
# Publish a payload to the server and wait (block) for the response
|
89
87
|
#
|
90
|
-
#
|
88
|
+
# It creates an `IVar` future for the response, stores that in
|
89
|
+
# `@pending_responses`, and then publishes the payload to the server.
|
90
|
+
# After publishing it waits for the `IVar` to be set with the response.
|
91
|
+
# It also clears that `IVar` if it times out to avoid leaking.
|
92
|
+
#
|
93
|
+
# Returns a Hash from the JSON response from the server
|
91
94
|
# Raises TimeoutError if server failed to respond in time
|
92
95
|
def publish_and_wait(payload, queue:, timeout:)
|
93
96
|
id = payload['id']
|
94
97
|
|
95
|
-
ivar =
|
98
|
+
ivar = Concurrent::IVar.new
|
99
|
+
@pending_responses[id] = ivar
|
100
|
+
|
101
|
+
self.publish payload, queue: queue
|
96
102
|
|
97
103
|
response = ivar.value timeout
|
98
104
|
|
@@ -108,27 +114,18 @@ module Fluffle
|
|
108
114
|
@pending_responses.delete id
|
109
115
|
end
|
110
116
|
|
111
|
-
# Create an `IVar` future for the response, store that in
|
112
|
-
# `@pending_responses`, and finally publish the payload to the server
|
113
|
-
#
|
114
|
-
# Returns the `IVar`
|
115
117
|
def publish(payload, queue:)
|
116
|
-
id = payload['id']
|
117
|
-
|
118
118
|
opts = {
|
119
119
|
routing_key: Fluffle.request_queue_name(queue),
|
120
|
-
correlation_id: id,
|
120
|
+
correlation_id: payload['id'],
|
121
121
|
reply_to: @reply_queue.name
|
122
122
|
}
|
123
123
|
|
124
|
-
ivar = Concurrent::IVar.new
|
125
|
-
@pending_responses[id] = ivar
|
126
|
-
|
127
124
|
@exchange.publish Oj.dump(payload), opts
|
128
|
-
|
129
|
-
ivar
|
130
125
|
end
|
131
126
|
|
127
|
+
protected
|
128
|
+
|
132
129
|
def random_bytes_as_hex(bytes)
|
133
130
|
# Adapted from `SecureRandom.hex`
|
134
131
|
@prng.bytes(bytes).unpack('H*')[0]
|
data/lib/fluffle/server.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
module Fluffle
|
2
2
|
class Server
|
3
|
-
|
4
|
-
attr_accessor :default_server
|
5
|
-
end
|
3
|
+
include Connectable
|
6
4
|
|
7
5
|
attr_reader :connection, :handlers
|
8
6
|
|
@@ -15,15 +13,8 @@ module Fluffle
|
|
15
13
|
self.class.default_server ||= self
|
16
14
|
end
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
@connection = Bunny.new *args
|
22
|
-
@connection.start
|
23
|
-
end
|
24
|
-
|
25
|
-
def connected?
|
26
|
-
@connection&.connected?
|
16
|
+
class << self
|
17
|
+
attr_accessor :default_server
|
27
18
|
end
|
28
19
|
|
29
20
|
def drain(queue: 'default', handler: nil, &block)
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
|
3
|
+
module Fluffle
|
4
|
+
module Testing
|
5
|
+
# Patch in a new `#connect` method that injects the loopback
|
6
|
+
module Connectable
|
7
|
+
def self.included(klass)
|
8
|
+
klass.class_eval do
|
9
|
+
alias_method :original_connect, :connect
|
10
|
+
|
11
|
+
def connect(*args)
|
12
|
+
@connection = Loopback.instance.connection
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.inject_connectable
|
19
|
+
[Fluffle::Client, Fluffle::Server].each do |mod|
|
20
|
+
mod.include Connectable
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Fake RabbitMQ server presented through a subset of the `Bunny`
|
25
|
+
# library's interface
|
26
|
+
class Loopback
|
27
|
+
# Singleton server instance that lives in the process
|
28
|
+
def self.instance
|
29
|
+
@instance ||= self.new
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@queues = Concurrent::Map.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def connection
|
37
|
+
Connection.new self
|
38
|
+
end
|
39
|
+
|
40
|
+
def add_queue_subscriber(queue_name, block)
|
41
|
+
subscribers = (@queues[queue_name] ||= Concurrent::Array.new)
|
42
|
+
|
43
|
+
subscribers << block
|
44
|
+
end
|
45
|
+
|
46
|
+
def publish(payload, opts)
|
47
|
+
queue_name = opts[:routing_key]
|
48
|
+
raise "Missing `:routing_key' in `#publish' opts" unless queue_name
|
49
|
+
|
50
|
+
delivery_info = nil
|
51
|
+
|
52
|
+
properties = {
|
53
|
+
reply_to: opts[:reply_to],
|
54
|
+
correlation_id: opts[:correlation_id]
|
55
|
+
}
|
56
|
+
|
57
|
+
subscribers = @queues[queue_name]
|
58
|
+
|
59
|
+
if subscribers.nil? || subscribers.empty?
|
60
|
+
$stderr.puts "No subscribers active for queue '#{queue_name}'"
|
61
|
+
return nil
|
62
|
+
end
|
63
|
+
|
64
|
+
subscribers.each do |subscriber|
|
65
|
+
Thread.new do
|
66
|
+
subscriber.call(delivery_info, properties, payload)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Connection
|
72
|
+
def initialize(server)
|
73
|
+
@server = server
|
74
|
+
end
|
75
|
+
|
76
|
+
def create_channel
|
77
|
+
Channel.new(@server)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
class Channel
|
82
|
+
def initialize(server)
|
83
|
+
@server = server
|
84
|
+
end
|
85
|
+
|
86
|
+
def default_exchange
|
87
|
+
@default_exchange ||= Exchange.new(@server)
|
88
|
+
end
|
89
|
+
|
90
|
+
def work_pool
|
91
|
+
@work_pool ||= WorkPool.new
|
92
|
+
end
|
93
|
+
|
94
|
+
def queue(name, **opts)
|
95
|
+
opts = opts.merge server: @server
|
96
|
+
|
97
|
+
Queue.new name, opts
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Exchange
|
102
|
+
def initialize(server)
|
103
|
+
@server = server
|
104
|
+
end
|
105
|
+
|
106
|
+
def publish(payload, opts)
|
107
|
+
@server.publish(payload, opts)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
class Queue
|
112
|
+
attr_reader :name
|
113
|
+
|
114
|
+
def initialize(name, server:, **opts)
|
115
|
+
@name = name
|
116
|
+
@server = server
|
117
|
+
end
|
118
|
+
|
119
|
+
def subscribe(&block)
|
120
|
+
@server.add_queue_subscriber @name, block
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
class WorkPool
|
125
|
+
# No-op in testing
|
126
|
+
def join
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end # class LoopbackServer
|
131
|
+
end # module Testing
|
132
|
+
end # module Fluffle
|
133
|
+
|
134
|
+
Fluffle::Testing.inject_connectable
|
data/lib/fluffle/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fluffle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dirk Gadsden
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- Rakefile
|
124
124
|
- examples/client.rb
|
125
125
|
- examples/server.rb
|
126
|
+
- examples/testing.rb
|
126
127
|
- fluffle.gemspec
|
127
128
|
- fluffle.jpg
|
128
129
|
- lib/fluffle.rb
|
@@ -133,6 +134,7 @@ files:
|
|
133
134
|
- lib/fluffle/handlers/delegator.rb
|
134
135
|
- lib/fluffle/handlers/dispatcher.rb
|
135
136
|
- lib/fluffle/server.rb
|
137
|
+
- lib/fluffle/testing.rb
|
136
138
|
- lib/fluffle/version.rb
|
137
139
|
- spec/client_spec.rb
|
138
140
|
- spec/server_spec.rb
|