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 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: []