mafia_amqp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,3 @@
1
+ # Mafia
2
+
3
+ RPC on top of rabbitmq.
@@ -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
@@ -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
@@ -0,0 +1,8 @@
1
+ module Mafia
2
+ class DefaultConsumer
3
+ def self.process(*args)
4
+ routing_key = args.pop
5
+ raise "Called DefaultConsumer with args #{args}, routing key: #{routing_key}"
6
+ end
7
+ end
8
+ end
@@ -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: []