rodent 0.0.2

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: 337e4f2fc38ca7b6be8c28ee796a13583f280e8f
4
+ data.tar.gz: 96dbe13907fb4d55a692281a438cce0bbc617cf8
5
+ SHA512:
6
+ metadata.gz: e816bbd6e3b597a247f744e9aa60857b7e43631da59207a348f51b379a2195892b2b0010739923958cdd02024dcac26e452a7fd4bd55f246c17db07677c4ea73
7
+ data.tar.gz: e14d6ae70fc3bbeedcb913452a74c631fc3411ca51fb0f3502fcc66e5771bae5f1807a468e4c7cdaeb32952b8c3c2db09c7b75f5a43b115bb03a4d1b108af044
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Artem Maschenko
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
1
+ module Rodent
2
+ class Base
3
+ class << self
4
+ attr_reader :listeners, :instance
5
+
6
+ def listeners
7
+ @listeners ||= []
8
+ end
9
+
10
+ def route(type)
11
+ @listeners.each do |listener|
12
+ return listener if type == listener.type
13
+ end
14
+ nil
15
+ end
16
+
17
+ def listen(type, &block)
18
+ listeners << Rodent::Listener.new(type, &block)
19
+ end
20
+
21
+ def bind
22
+ listeners.each(&:bind)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,59 @@
1
+ require 'bson'
2
+ require 'multi_json'
3
+ require 'amqp'
4
+ require 'goliath'
5
+
6
+ module Rodent
7
+ module Goliath
8
+ class Middleware
9
+ include ::Goliath::Rack::AsyncMiddleware
10
+
11
+ def initialize(app, header_proxy_name = 'Rodent-Proxy')
12
+ @header_proxy_name = header_proxy_name
13
+ super(app)
14
+ end
15
+
16
+ def hook_into_callback_chain(env, *args)
17
+ async_callback = env['async.callback']
18
+
19
+ downstream_callback = proc do |status, headers, response|
20
+ result_response = [status, headers, response]
21
+ if proxy_type = headers.delete(@header_proxy_name)
22
+ result_response = safely(env) { proxy_request(env, proxy_type, response.body.join, headers) }
23
+ end
24
+ async_callback.call(result_response) unless result_response == ::Goliath::Connection::AsyncResponse
25
+ end
26
+
27
+ env['async.callback'] = downstream_callback
28
+ end
29
+
30
+ protected
31
+ def proxy_request(env, type, body, headers = {})
32
+ async_callback = env['async.callback']
33
+
34
+ message_id = BSON::ObjectId.new.to_s
35
+
36
+ env.channels.execute(false) do |channel|
37
+ replies_queue = channel.queue(message_id, exclusive: true, auto_delete: true)
38
+
39
+ consumer = AMQP::Consumer.new(channel, replies_queue)
40
+
41
+ consumer.consume do
42
+ consumer.on_delivery do |metadata, payload|
43
+ response = MultiJson.load(payload)
44
+ response['Content-Length'] = response['body'].length.to_s
45
+ response['Content-Type'] = 'application/json'
46
+ async_callback.call([response['status'], headers.merge(response['headers']), response['body']])
47
+ metadata.ack
48
+ consumer.cancel
49
+ end
50
+ end
51
+
52
+ channel.direct('rodent.requests').publish(body, routing_key: type, message_id: message_id, reply_to: replies_queue.name)
53
+ end
54
+
55
+ ::Goliath::Connection::AsyncResponse
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,23 @@
1
+ require 'em-synchrony'
2
+ require 'amqp'
3
+ require 'goliath'
4
+
5
+ module Rodent
6
+ module Goliath
7
+ class Plugin
8
+ def initialize(address, port, config, status, logger)
9
+ @port = port
10
+ @status = status
11
+ @config = config
12
+ @logger = logger
13
+ end
14
+
15
+ def run(connection_string = 'amqp://guest:guest@localhost', pool_size = 50)
16
+ @config['amqp'] = AMQP.connect(connection_string)
17
+ @config['channels'] = EM::Synchrony::ConnectionPool.new(size: pool_size) do
18
+ AMQP::Channel.new(@config['amqp'])
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,45 @@
1
+ require 'multi_json'
2
+ require 'amqp'
3
+
4
+ module Rodent
5
+ class Listener
6
+ attr_reader :type
7
+ attr_accessor :params, :status, :headers, :body
8
+
9
+ def initialize(type, &block)
10
+ @type = type
11
+ @source = block
12
+ end
13
+
14
+ def bind
15
+ AMQP::Channel.new do |channel|
16
+ channel.prefetch(100)
17
+ queue = channel.queue(@type, exclusive: true, auto_delete: true)
18
+ queue.bind(channel.direct('rodent.requests'), routing_key: @type)
19
+ queue.subscribe(ack: true) do |metadata, payload|
20
+ self.params = MultiJson.load(payload)
21
+ self.body = call
22
+ channel.default_exchange.publish(MultiJson.dump(response), routing_key: metadata.reply_to, correlation_id: metadata.message_id)
23
+ metadata.ack
24
+ end
25
+ end
26
+ end
27
+
28
+ def call
29
+ self.status = 200
30
+ self.headers = {}
31
+ unless respond_to?(method_name)
32
+ define_singleton_method(method_name, @source)
33
+ end
34
+ MultiJson.dump(self.send(method_name))
35
+ end
36
+
37
+ def method_name
38
+ ('rodent_' + @type).gsub('.', '_').to_sym
39
+ end
40
+
41
+ def response
42
+ {status: status, headers: headers, body: body}
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,30 @@
1
+ require 'amqp'
2
+
3
+ module Rodent
4
+ class Server
5
+ class << self
6
+ attr_accessor :settings
7
+
8
+ def configure(&block)
9
+ @settings ||= {}
10
+ yield
11
+ end
12
+
13
+ def set(attr, value)
14
+ settings[attr] = value
15
+ end
16
+
17
+ def run(&block)
18
+ EM.run do
19
+ AMQP.connection ||= AMQP.connect(settings[:connection])
20
+
21
+ block.call.each(&:bind)
22
+ end
23
+ end
24
+
25
+ def stop
26
+ AMQP.connection.close { EM.stop }
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ module Rodent
2
+ module Test
3
+ module Helpers
4
+ def request(path, *args)
5
+ @rodent_response = api.route(path).call(*args)
6
+ end
7
+
8
+ def response
9
+ @rodent_response
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,3 @@
1
+ module Rodent
2
+ VERSION = '0.0.2'
3
+ end
data/lib/rodent.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'rodent/version'
2
+ require 'rodent/listener'
3
+ require 'rodent/base'
4
+ require 'rodent/server'
5
+ require 'rodent/goliath/plugin'
6
+ require 'rodent/goliath/middleware'
data/rodent.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path('../lib', __FILE__)
3
+ require 'rodent/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rodent'
7
+ s.version = Rodent::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['Artem Maschenko']
10
+ s.email = ['artem.maschenko@gmail.com']
11
+ s.homepage = 'https://github.com/kkdoo/rodent'
12
+ s.summary = 'Framework for micro services'
13
+ s.description = s.summary
14
+ s.license = 'MIT'
15
+
16
+ s.rubyforge_project = 'rodent'
17
+
18
+ s.required_ruby_version = '>=1.9.2'
19
+
20
+ s.add_dependency 'multi_json'
21
+ s.add_dependency 'goliath'
22
+ s.add_dependency 'amqp'
23
+ s.add_dependency 'em-synchrony'
24
+
25
+ s.files = `git ls-files`.split("\n")
26
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
27
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
28
+ s.require_paths = ["lib"]
29
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rodent
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Artem Maschenko
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-09-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: goliath
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: amqp
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: em-synchrony
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Framework for micro services
70
+ email:
71
+ - artem.maschenko@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE
79
+ - lib/rodent.rb
80
+ - lib/rodent/base.rb
81
+ - lib/rodent/goliath/middleware.rb
82
+ - lib/rodent/goliath/plugin.rb
83
+ - lib/rodent/listener.rb
84
+ - lib/rodent/server.rb
85
+ - lib/rodent/test_helpers.rb
86
+ - lib/rodent/version.rb
87
+ - rodent.gemspec
88
+ homepage: https://github.com/kkdoo/rodent
89
+ licenses:
90
+ - MIT
91
+ metadata: {}
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - '>='
99
+ - !ruby/object:Gem::Version
100
+ version: 1.9.2
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project: rodent
108
+ rubygems_version: 2.0.3
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: Framework for micro services
112
+ test_files: []
113
+ has_rdoc: