fluffle 0.0.3 → 0.1.0
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/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
|