mafia_amqp 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 +7 -0
- data/README.md +3 -0
- data/lib/mafia/consumer.rb +36 -0
- data/lib/mafia/consumer_pool.rb +57 -0
- data/lib/mafia/dealer.rb +67 -0
- data/lib/mafia/default_consumer.rb +8 -0
- data/lib/mafia/logger.rb +28 -0
- data/lib/mafia.rb +37 -0
- metadata +137 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 05ebe33c6ea5bd5237fd52d94b1f7df3704d5136
|
4
|
+
data.tar.gz: 211ba3f7435bc30d1015e594b7ab3406013a8c90
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0a4f7ffba83604ab9f3bc6ab1703c39a1a9d10a1b8daf2f7877f3e2568ce4689326c2df121f6dd2a41f9652e270ed36eb63fb746d1b0f03e87fb6f0bc1af1e02
|
7
|
+
data.tar.gz: c05b95d890524b09bb8bcc5d58fa602d5687e64cc4b759f671660490655ca67352ed474d9fcddc68cc2822a36681c80893b245a49d0d1520e73d589a2f49d537
|
data/README.md
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Mafia
|
2
|
+
module Consumer
|
3
|
+
def initialize(routing_key=nil)
|
4
|
+
@routing_key = routing_key
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
Mafia.register_consumer(base)
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
attr_reader :routing_key
|
14
|
+
|
15
|
+
def consume(routing_key)
|
16
|
+
@routing_key = routing_key
|
17
|
+
end
|
18
|
+
|
19
|
+
def process(routing_key, *args)
|
20
|
+
new(routing_key).process(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Explicitly set the queue name
|
24
|
+
def queue_name(name)
|
25
|
+
@queue_name = name
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_queue_name
|
29
|
+
return @queue_name unless @queue_name.nil?
|
30
|
+
queue_name = self.name.gsub(/::/, ':')
|
31
|
+
queue_name.gsub!(/([^A-Z:])([A-Z])/) { "#{$1}_#{$2}" }
|
32
|
+
queue_name.downcase
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Mafia
|
2
|
+
class ConsumerPool
|
3
|
+
def initialize(config=nil)
|
4
|
+
@config = config || Mafia.config
|
5
|
+
|
6
|
+
@conn = Bunny.new(@config.slice(:host, :port, :username, :password, :vhost))
|
7
|
+
@conn.start
|
8
|
+
|
9
|
+
# create a channel and exchange that both client and server know about
|
10
|
+
@channel = @conn.create_channel
|
11
|
+
@queue = @channel.queue(@config[:queue])
|
12
|
+
@exchange = @channel.default_exchange
|
13
|
+
end
|
14
|
+
|
15
|
+
def subscribe
|
16
|
+
@queue.subscribe(block: true) do |delivery_info, properties, payload|
|
17
|
+
req_message = JSON.parse payload
|
18
|
+
|
19
|
+
# calculate a result
|
20
|
+
klass = fetch_consumer(req_message['method'])
|
21
|
+
|
22
|
+
begin
|
23
|
+
args = (req_message['params'].unshift(req_message['method']))
|
24
|
+
result = [:ok, klass.process(*args)]
|
25
|
+
rescue Exception => e
|
26
|
+
Mafia.logger.error("error while running #{klass} with args: #{req_message['params']}: #{e.message}")
|
27
|
+
result = [:error, e.message]
|
28
|
+
end
|
29
|
+
|
30
|
+
reply = {
|
31
|
+
'id' => req_message['id'],
|
32
|
+
'result' => result,
|
33
|
+
'jsonrpc' => '2.0'
|
34
|
+
}
|
35
|
+
|
36
|
+
# enqueue our reply in the return queue
|
37
|
+
|
38
|
+
Mafia.logger.info("publish to return queue #{properties.reply_to}")
|
39
|
+
@exchange.publish(JSON.generate(reply), {
|
40
|
+
routing_key: properties.reply_to,
|
41
|
+
correlation_id: properties.correlation_id})
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch_consumer(routing_key)
|
46
|
+
Mafia.consumers.each do |consumer|
|
47
|
+
if consumer.routing_key == routing_key
|
48
|
+
Mafia.logger.info("Routing key `#{routing_key}` to consumer #{consumer.name}")
|
49
|
+
return consumer
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
Mafia.logger.info("Routing key `#{routing_key}` to default consumer")
|
54
|
+
DefaultConsumer
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/mafia/dealer.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
module Mafia
|
2
|
+
class Dealer
|
3
|
+
def initialize(config=nil)
|
4
|
+
@config = config || Mafia.config
|
5
|
+
|
6
|
+
@conn = Bunny.new(@config.slice(:host, :port, :username, :password, :vhost))
|
7
|
+
@conn.start
|
8
|
+
|
9
|
+
# create a channel and exchange that both client and server know about
|
10
|
+
@channel = @conn.create_channel
|
11
|
+
@queue = @channel.queue(@config[:queue])
|
12
|
+
@exchange = @channel.default_exchange
|
13
|
+
end
|
14
|
+
|
15
|
+
def publish(channel, *args)
|
16
|
+
start_time = Time.now
|
17
|
+
# request id will be used as the name of the return queue
|
18
|
+
params = *args
|
19
|
+
Mafia.logger.info("Publish to channel `#{channel}` params: #{params}")
|
20
|
+
|
21
|
+
req_message = {
|
22
|
+
'id' => SecureRandom.hex,
|
23
|
+
'jsonrpc' => '2.0',
|
24
|
+
'method' => channel,
|
25
|
+
'params' => params
|
26
|
+
}
|
27
|
+
|
28
|
+
response = nil
|
29
|
+
|
30
|
+
# create a return queue for this client
|
31
|
+
reply_q = @channel.queue('', exclusive: true)
|
32
|
+
|
33
|
+
Mafia.logger.info("subscribe to return queue #{reply_q.name}")
|
34
|
+
queue_consumer = reply_q.subscribe do |delivery_info, properties, payload|
|
35
|
+
if properties[:correlation_id] == req_message['id']
|
36
|
+
response = payload # visible via closure
|
37
|
+
delivery_info.consumer.cancel # unblock the consumer
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# send out our request, serialized as JSON
|
42
|
+
@exchange.publish(JSON.generate(req_message), {
|
43
|
+
correlation_id: req_message['id'],
|
44
|
+
reply_to: reply_q.name,
|
45
|
+
routing_key: @queue.name,
|
46
|
+
})
|
47
|
+
begin
|
48
|
+
# wait from response from return queue
|
49
|
+
Timeout.timeout(@config[:rpc_timeout]) do
|
50
|
+
loop do
|
51
|
+
unless response.nil?
|
52
|
+
res = JSON.parse(response)
|
53
|
+
ret = res["result"]
|
54
|
+
|
55
|
+
Mafia.logger.info("Finished in #{Time.now - start_time}s with response #{ret}")
|
56
|
+
queue_consumer.cancel
|
57
|
+
return ret
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
rescue Timeout::Error
|
62
|
+
Mafia.logger.error("Timeout waiting for rpc response")
|
63
|
+
raise
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/mafia/logger.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Mafia
|
2
|
+
module Logger
|
3
|
+
class MafiaFormatter < ::Logger::Formatter
|
4
|
+
def call(severity, time, program_name, message)
|
5
|
+
"#{time.utc.iso8601} #{Process.pid} #{severity} -- #{message}\n"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.setup_logger(target = $stdout)
|
10
|
+
@logger = ::Logger.new(target)
|
11
|
+
@logger.level = Mafia.log_level
|
12
|
+
@logger.formatter = MafiaFormatter.new
|
13
|
+
@logger
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.logger
|
17
|
+
@logger || setup_logger
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.logger=(logger)
|
21
|
+
@logger = logger
|
22
|
+
end
|
23
|
+
|
24
|
+
def logger
|
25
|
+
Mafia::Logger.logger
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/mafia.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'securerandom'
|
3
|
+
require 'timeout'
|
4
|
+
require 'bunny'
|
5
|
+
require 'active_support'
|
6
|
+
|
7
|
+
require 'mafia/logger'
|
8
|
+
require 'mafia/dealer'
|
9
|
+
require 'mafia/consumer'
|
10
|
+
require 'mafia/consumer_pool'
|
11
|
+
require 'mafia/default_consumer'
|
12
|
+
|
13
|
+
module Mafia
|
14
|
+
def self.register_consumer(consumer)
|
15
|
+
self.consumers << consumer
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.consumers
|
19
|
+
@consumers ||= []
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.configure(c={})
|
23
|
+
@config = config.merge(c)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.config
|
27
|
+
@config ||= {}
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.logger
|
31
|
+
Mafia::Logger.logger
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.log_level
|
35
|
+
@config[:log_level] || ::Logger::INFO
|
36
|
+
end
|
37
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mafia_amqp
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Teodor Pripoae
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-02 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bunny
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.2'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.2'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.4'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.4'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.1'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: database_url
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.1'
|
97
|
+
description: |
|
98
|
+
# Mafia
|
99
|
+
|
100
|
+
RPC on top of rabbitmq.
|
101
|
+
email: toni@kuende.com
|
102
|
+
executables: []
|
103
|
+
extensions: []
|
104
|
+
extra_rdoc_files: []
|
105
|
+
files:
|
106
|
+
- README.md
|
107
|
+
- lib/mafia.rb
|
108
|
+
- lib/mafia/consumer.rb
|
109
|
+
- lib/mafia/consumer_pool.rb
|
110
|
+
- lib/mafia/dealer.rb
|
111
|
+
- lib/mafia/default_consumer.rb
|
112
|
+
- lib/mafia/logger.rb
|
113
|
+
homepage: http://github.com/teodor-pripoae/mafia
|
114
|
+
licenses:
|
115
|
+
- MIT
|
116
|
+
metadata: {}
|
117
|
+
post_install_message:
|
118
|
+
rdoc_options: []
|
119
|
+
require_paths:
|
120
|
+
- lib
|
121
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - ">="
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
requirements: []
|
132
|
+
rubyforge_project:
|
133
|
+
rubygems_version: 2.4.5
|
134
|
+
signing_key:
|
135
|
+
specification_version: 4
|
136
|
+
summary: RPC on top of rabbitmq
|
137
|
+
test_files: []
|