tom 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -10,8 +10,13 @@ All you have to do is define some `Adapter`s that get activated for certain rout
10
10
  As you have seen in the video above, Tom Smykowski talks extra much when
11
11
  consultants are present who might fire him. So this gem will log to
12
12
  STDOUT when you're in development mode or the BOBS environment variable
13
- is set. Useful for debugging, but nothing you really want in
14
- production/testing.
13
+ is set. For example, you could
14
+
15
+ BOBS=present ruby yourapp.rb
16
+
17
+ Useful for debugging, but nothing you really want in production/testing.
18
+ Also, Tom is yard documented. Just run `yard --server` and direct your
19
+ browser to `http://localhost:8808`.
15
20
 
16
21
  # TL;DR
17
22
 
@@ -111,8 +116,6 @@ Same goes for mergers.
111
116
  # Todo
112
117
 
113
118
  - handle adapter errors/states in mergers
114
- - register routes with concurrency on and off
115
- - use Goliath::Rack::Params
116
119
  - use Goliath::Rack::Heartbeat
117
120
  - think about consensus protocols
118
121
  - ...
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.2.1
@@ -2,6 +2,12 @@ require 'em-synchrony/em-http'
2
2
  require_relative 'http'
3
3
 
4
4
  module Tom
5
+
6
+ # Please see the {https://github.com/moviepilot/tom#readme README} for
7
+ # examples on how to use this.
8
+ #
9
+ # @attribute host [String] The hostname this adapter is connecting to (the
10
+ # "other" API endpoint).
5
11
  class Adapter
6
12
  class << self
7
13
  attr_accessor :host
@@ -16,13 +22,16 @@ module Tom
16
22
  #
17
23
  # @param route [String] The route this Adapter should
18
24
  # respond to.
25
+ #
19
26
  # @param methods [Array<Symbol>] Optional array of methods
20
27
  # that this Adapter is listening to. It defaults to
21
- # all (`:head`, `:get`, `:put`, `:post`, `:delete`)
28
+ # all (:head, :get, :put, :post, :delete)
29
+ #
30
+ # @return [Hash] See {Tom::Routes.register}
22
31
  def self.register_route(*args)
23
32
  route = args[0]
24
33
  methods = args[1..-1]
25
- Dispatcher.register(route: /#{route}/, adapter: self, methods: methods)
34
+ Tom::Routes.register(route: /#{route}/, adapter: self, methods: methods)
26
35
  end
27
36
 
28
37
  def initialize
@@ -35,6 +44,9 @@ module Tom
35
44
  #
36
45
  # @param env [Array] The incoming (original request)
37
46
  # rack env object
47
+ #
48
+ # @return [Array] Your beloved triple of [status_code, headers,
49
+ # response_body]
38
50
  def forward_request(env)
39
51
  rewrite_request(env)
40
52
  options = http_request_options(env)
@@ -54,6 +66,10 @@ module Tom
54
66
  # and POSTs this will add the request body
55
67
  #
56
68
  # @param env [Array] A rack env object
69
+ #
70
+ # @return [Hash] Has the value of @request[:body] inside its
71
+ # :body key, but only when the request method in the given
72
+ # env matches :put or :post
57
73
  def http_request_options(env)
58
74
  opts = {}
59
75
  if [:put, :post].include? @request[:method]
@@ -68,6 +84,10 @@ module Tom
68
84
  # this is what we feed into the EM::HttpRequest
69
85
  #
70
86
  # @param env [Array] A rack env object
87
+ #
88
+ # @return [Hash] Returns whatever the client POSTed/PUT and defaults
89
+ # to an empty hash (while debugging, consider your middlewares,
90
+ # they might touch this depending on the Content-Type)
71
91
  def extract_request_body(env)
72
92
  Rack::Request.new(env).POST rescue {}
73
93
  end
@@ -78,6 +98,8 @@ module Tom
78
98
  # before forwarding it.
79
99
  #
80
100
  # @param env [Array] A rack env object
101
+ #
102
+ # @return [Hash] The @request variable
81
103
  def rewrite_request(env)
82
104
  rewritten = rewrite_host(env)
83
105
  @request = rewritten.merge(@request)
@@ -88,6 +110,8 @@ module Tom
88
110
  #
89
111
  # @param env [Array] The incoming (original request)
90
112
  # rack env object
113
+ #
114
+ # @return [void] This mofo raises and never returns anything.
91
115
  def handle(env)
92
116
  raise "Subclass, implement #handle(env)!"
93
117
  end
@@ -99,6 +123,8 @@ module Tom
99
123
  # hostname.
100
124
  #
101
125
  # @param env [Array] A rack env object
126
+ #
127
+ # @return [Hash] With :host, :uri and :method
102
128
  def rewrite_host(env)
103
129
  { host: self.class.host,
104
130
  uri: env["REQUEST_URI"],
@@ -1,16 +1,6 @@
1
1
  require "em-synchrony/fiber_iterator"
2
- require 'logger'
3
2
 
4
3
  module Tom
5
-
6
- LOG = ::Logger.new(STDOUT)
7
- LOG.level = ::Logger::ERROR
8
- LOG.datetime_format = "%H:%M:%S:"
9
- Logger::Formatter.module_eval(
10
- %q{ def call(severity, time, progname, msg)} +
11
- %q{ "#{format_datetime(time)} #{msg2str(msg)}\n" end}
12
- )
13
-
14
4
  class Dispatcher
15
5
 
16
6
  # Dispatches this request to all adapters that registered
@@ -18,9 +8,11 @@ module Tom
18
8
  # to compose a response
19
9
  #
20
10
  # @param env [Array] A rack env object
21
- # @return (see #merge)
11
+ #
12
+ # @return [Array] Whatever {Tom::Dispatcher.merge} had to say
22
13
  def self.dispatch(env)
23
- adapters = adapters_for_route(env)
14
+ route, method = route_and_method(env)
15
+ adapters = Tom::Routes.adapters_for_route(route, method)
24
16
  return [404, {}, '{reason: "No adapters for this route"}'] if adapters.empty?
25
17
 
26
18
  # Hit APIs. All at the same time. Oh, mygodd!
@@ -44,125 +36,30 @@ module Tom
44
36
  # The merger used depends on the route.
45
37
  #
46
38
  # @param env [Array] A rack env object
39
+ #
47
40
  # @return [Array] The merged result of all requests
48
41
  # made as an array of status code, headers and body, e.g.
49
- # `[200, {}, "Hi!"]`
42
+ # [200, {}, "Hi!"]
50
43
  def self.merge(env, responses)
51
- merger = merger_for_route(env)
44
+ route, method = route_and_method(env)
45
+ merger = Tom::Routes.merger_for_route(route, method)
52
46
  Tom::LOG.info "Merging with:"
53
47
  Tom::LOG.info " -> #{merger}"
54
48
  merger.new.merge env, responses
55
49
  end
56
50
 
57
- # Registers a opts[:adapter] or opts[:merger] for the
58
- # given opts[:route].
59
- #
60
- # This method should not be called directly, use register_route
61
- # in Tom::Adapter or Tom::Merger instead.
62
- #
63
- # @param opts [Hash] Needs to have at least `:route` and
64
- # either `:adapter` or `:merger` set, depending on what you
65
- # are registering. But you don't need to use this method
66
- # directly, Adapter and Merger provide convenience methods
67
- # for you.
68
- def self.register(opts)
69
- return register_adapter(opts) if opts[:adapter]
70
- return register_merger(opts) if opts[:merger]
71
- raise "You need to supply opts[:adapter] or opts[:merger]"
72
- end
73
-
74
- private
75
-
76
- #
77
- # Registers an adapter for a given route and request method
78
- #
79
- def self.register_adapter(opts)
80
- validate_type(opts[:adapter], Adapter)
81
- methods = get_methods(opts)
82
- @adapters ||= default_methods_hash
83
- methods.each do |method|
84
- @adapters[method][opts[:route]] ||= []
85
- @adapters[method][opts[:route]] << opts[:adapter]
86
- end
87
- end
88
51
 
89
- #
90
- # Registers merger for a given route and request method
91
- #
92
- def self.register_merger(opts)
93
- validate_type(opts[:merger], Merger)
94
- methods = get_methods(opts)
95
- @mergers ||= default_methods_hash
96
- methods.each do |method|
97
- @mergers[method][opts[:route]] ||= []
98
- @mergers[method][opts[:route]] << opts[:merger]
99
- end
100
- end
101
52
 
53
+ # Extract the route/request uri and the method from a
54
+ # rack env
102
55
  #
103
- # Fetches the methods from the options hash, defaults
104
- # to all methods.
105
- #
106
- def self.get_methods(opts)
107
- return opts[:methods] unless opts[:methods].empty?
108
- [:head, :get, :put, :post, :delete]
109
- end
110
-
111
- #
112
- # Just some defaults to initialize thing
113
- #
114
- def self.default_methods_hash
115
- { head: {},
116
- get: {},
117
- put: {},
118
- post: {},
119
- delete: {}
120
- }
121
- end
122
-
123
- #
124
- # Find the right adapter for a route
125
- #
126
- def self.adapters_for_route(env)
127
- @adapters ||= default_methods_hash
128
- route, method = route_and_method(env)
129
- matches = []
130
- @adapters[method].map do |reg_route, adapters|
131
- next unless reg_route.match(route)
132
- matches += adapters
133
- end
134
- matches.uniq
135
- end
136
-
137
- #
138
- # Find the right merger for a route
139
- #
140
- def self.merger_for_route(env)
141
- @mergers ||= default_methods_hash
142
- route, method = route_and_method(env)
143
- @mergers[method].each do |reg_route, mergers|
144
- next unless reg_route.match(route)
145
- return mergers.first
146
- end
147
- raise "Found no merger for route #{route}"
148
- end
149
-
150
- #
151
- # Extract the route/request uri and the method from a
152
- # rack env
56
+ # @param env [Hash] A rack env
153
57
  #
58
+ # @return [Array] Contains request_path, request_method as symbols
154
59
  def self.route_and_method(env)
155
60
  [env["REQUEST_PATH"],
156
61
  env["REQUEST_METHOD"].downcase.to_sym]
157
62
  end
158
63
 
159
- #
160
- # Make sure one class is a subclass of another class
161
- #
162
- def self.validate_type(c, expected)
163
- return if c < expected
164
- raise "Invalid type. Expected #{expected} got #{c}"
165
- end
166
-
167
64
  end
168
65
  end
@@ -0,0 +1,33 @@
1
+ module Tom
2
+
3
+ # WE HAZ ALL TEH GOLIATH REQUESTS AND FORWARDETH
4
+ # THEM TO DEH DISPATCHERETH.
5
+ #
6
+ # We have to see if this is the right way to do
7
+ # it when it comes to parallel stuff and so on...
8
+ class GoliathAPI < Goliath::API
9
+ use Goliath::Rack::Render
10
+
11
+ # Forwards env to {Tom::Dispatcher.dispatch}, look there.
12
+ #
13
+ # @param env [Hash] Rack env
14
+ def response(env)
15
+ begin
16
+ Tom::Dispatcher.dispatch(env)
17
+ rescue => e
18
+ handle_exception e, env
19
+ end
20
+ end
21
+
22
+ # Hardcoded JSON stacktrace stuff for now...
23
+ def handle_exception(e, env)
24
+ trace = e.backtrace.join "\n"
25
+ Tom::LOG.info e
26
+ Tom::LOG.info trace
27
+ [500, {}, {error: e,
28
+ stacktrace: trace,
29
+ url: env["REQUEST_URI"]
30
+ }.to_json]
31
+ end
32
+ end
33
+ end
@@ -1,8 +1,18 @@
1
1
  require 'bundler'
2
2
  Bundler.require :default
3
3
 
4
- module Tom; end
4
+ # Init Goliath env unless it was done already
5
+ Goliath.env rescue Goliath.env = (ENV['RACK_ENV'] || 'development').to_sym
5
6
 
7
+ # In dev mode, we do some logging (defaults to Logger::ERROR in other
8
+ # envs)
9
+ if Goliath.env == :development || ENV['BOBS']
10
+ Tom::LOG.level = Logger::INFO
11
+ end
12
+ Tom::LOG.info "Started goliath in #{Goliath.env} environment (change with ruby your_app.rb -e development or by setting $RACK_ENV)"
13
+
14
+ # Fetch the codes
15
+ require_relative 'goliath_api'
6
16
  require_relative 'dispatcher'
7
17
  require_relative 'adapter'
8
18
  require_relative 'merger'
@@ -1,4 +1,7 @@
1
1
  module Tom
2
+
3
+ # Please see the {https://github.com/moviepilot/tom#readme README} for
4
+ # examples on how to use this.
2
5
  class Merger
3
6
 
4
7
  # Registers a route with the request dispatcher
@@ -18,7 +21,7 @@ module Tom
18
21
  def self.register_route(*args)
19
22
  route = args[0]
20
23
  methods = args[1..-1]
21
- Dispatcher.register(route: /#{route}/, merger: self, methods: methods)
24
+ Tom::Routes.register(route: /#{route}/, merger: self, methods: methods)
22
25
  end
23
26
 
24
27
  # When the request dispatcher made all the requests,
@@ -29,7 +32,7 @@ module Tom
29
32
  # rack env object
30
33
  # @param responses [Hash] Replies from all Adapters that
31
34
  # got triggered by route and method, e.g.
32
- # `{MyAdapter: rack_env, MyOtherAdapter: other_env}`
35
+ # `{ MyAdapter: rack_env, MyOtherAdapter: other_env }`
33
36
  # @return [Array] A rack response (for example, something
34
37
  # like [200, {}, "body"])
35
38
  def merge(env, responses)
data/lib/tom.rb CHANGED
@@ -1,59 +1,10 @@
1
+ require_relative 'tom/log'
2
+ require_relative 'tom/routes'
3
+ require_relative 'tom/config'
1
4
  require_relative 'init'
2
5
 
3
- # Init Goliath env unless it was done already
4
- Goliath.env rescue Goliath.env = (ENV['RACK_ENV'] || 'development').to_sym
5
-
6
- # In dev mode, we do some logging (defaults to Logger::ERROR in other
7
- # envs)
8
- if Goliath.env == :development || ENV['BOBS']
9
- Tom::LOG.level = Logger::INFO
10
- end
11
- Tom::LOG.info "Started goliath in #{Goliath.env} environment (change with ruby your_app.rb -e development or by setting $RACK_ENV)"
12
-
6
+ # The only thing you should really do with the Tom class is
7
+ # setting or reading its configuration.
13
8
  module Tom
14
-
15
- def self.config
16
- @config || default_config
17
- end
18
-
19
- def self.config=(config)
20
- @config = config
21
- end
22
-
23
- #
24
- # WE HAZ ALL TEH GOLIATH REQUESTS AND FORWARDETH
25
- # THEM TO DEH DISPATCHERETH.
26
- #
27
- # We have to see if this is the right way to do
28
- # it when it comes to parallel stuff and so on...
29
- #
30
- class GoliathAPI < Goliath::API
31
- use Goliath::Rack::Render
32
-
33
- def response(env)
34
- begin
35
- Tom::Dispatcher.dispatch(env)
36
- rescue => e
37
- handle_exception e, env
38
- end
39
- end
40
-
41
- def handle_exception(e, env)
42
- trace = e.backtrace.join "\n"
43
- Tom::LOG.info e
44
- Tom::LOG.info trace
45
- [500, {}, {error: e,
46
- stacktrace: trace,
47
- url: env["REQUEST_URI"]
48
- }.to_json]
49
- end
50
- end
51
-
52
- private
53
-
54
- def self.default_config
55
- { timeouts:
56
- { connect_timeout: 5,
57
- inactivity_timeout: 10 } }
58
- end
9
+ extend Tom::Config
59
10
  end
@@ -0,0 +1,32 @@
1
+ module Tom
2
+
3
+ # Don't use this module directly - access these methods
4
+ # through {Tom} who does a `extend Tom::Config`
5
+ module Config
6
+
7
+ # @return [Hash] configuration
8
+ def config
9
+ @config || default_config
10
+ end
11
+
12
+
13
+ # @param config [Hash] The configuration you want
14
+ # to set. Currently, only the `:timeout` key is
15
+ # read, and in it the `:connect_timeout` and the
16
+ # `:inactivity_timeout` keys can be set to an int
17
+ # value (seconds)
18
+ # @return [Hash] configuration
19
+ def config=(config)
20
+ @config = config
21
+ end
22
+
23
+
24
+ private
25
+
26
+ def default_config
27
+ { timeouts:
28
+ { connect_timeout: 5,
29
+ inactivity_timeout: 10 } }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,11 @@
1
+ require 'logger'
2
+
3
+ module Tom
4
+ LOG = ::Logger.new(STDOUT)
5
+ LOG.level = ::Logger::ERROR
6
+ LOG.datetime_format = "%H:%M:%S:"
7
+ Logger::Formatter.module_eval(
8
+ %q{ def call(severity, time, progname, msg)} +
9
+ %q{ "#{format_datetime(time)} #{msg2str(msg)}\n" end}
10
+ )
11
+ end
@@ -0,0 +1,136 @@
1
+ module Tom
2
+
3
+ # Takes care of registering adapters and mergers for routes,
4
+ # and then matching routes and methods to adapters and mergers.
5
+ module Routes
6
+
7
+ # Registers a opts[:adapter] or opts[:merger] for the
8
+ # given opts[:route].
9
+ #
10
+ # This method should not be called directly in your app, you
11
+ # would use {Tom::Adapter.register_route} or
12
+ # {Tom::Merger.register_route} in your subclass of {Tom::Adapter}
13
+ # or {Tom::Merger}
14
+ #
15
+ # @param opts [Hash] Needs to have at least :route and
16
+ # either :adapter or :merger set, depending on what you
17
+ # are registering. But you don't need to use this method
18
+ # directly, Adapter and Merger provide convenience methods
19
+ # for you.
20
+ #
21
+ # @return [Hash] See {Tom::Routes.register_adapter} or
22
+ # {Tom::Routes.register_merger}
23
+ def self.register(opts)
24
+ return register_adapter(opts) if opts[:adapter]
25
+ return register_merger(opts) if opts[:merger]
26
+ raise "You need to supply opts[:adapter] or opts[:merger]"
27
+ end
28
+
29
+ # Registers an {Adapter} for a given route and request method
30
+ #
31
+ # @param opts [Hash] Needs to have the :route and :adapter
32
+ # keys set with a regular expression and a subclass of
33
+ # {Tom::Adapter}
34
+ #
35
+ # @return [Hash] First level are the HTTP methods, second
36
+ # level are the regular expressions for routes, and the
37
+ # values are arrays of Adapters for the combination of
38
+ # request method and route.
39
+ def self.register_adapter(opts)
40
+ validate_type(opts[:adapter], Adapter)
41
+ methods = get_methods(opts)
42
+ @adapters ||= default_methods_hash
43
+ methods.each do |method|
44
+ @adapters[method][opts[:route]] ||= []
45
+ @adapters[method][opts[:route]] << opts[:adapter]
46
+ end
47
+ @adapters
48
+ end
49
+
50
+ # Registers a {Merger} for a given route and request method
51
+ #
52
+ # @return [Hash] First level are the HTTP methods, second
53
+ # level are the regular expressions for routes, and the
54
+ # values are arrays of Mergers for the combination of
55
+ # request method and route.
56
+ def self.register_merger(opts)
57
+ validate_type(opts[:merger], Merger)
58
+ methods = get_methods(opts)
59
+ @mergers ||= default_methods_hash
60
+ methods.each do |method|
61
+ @mergers[method][opts[:route]] ||= []
62
+ @mergers[method][opts[:route]] << opts[:merger]
63
+ end
64
+ @mergers
65
+ end
66
+
67
+ # @return [Hash] See what {Tom::Routes.register_adapter} returns
68
+ def self.adapters
69
+ @adapters
70
+ end
71
+
72
+ # @return [Hash] See what {Tom::Routes.register_merger} returns
73
+ def self.mergers
74
+ @mergers
75
+ end
76
+
77
+ private
78
+
79
+ # Fetches the methods from the options hash, defaults
80
+ # to all methods.
81
+ #
82
+ # @param opts [Hash] We're looking for :methods in this hash
83
+ #
84
+ # @return [Hash] Returns what's in :methods, and defaults to
85
+ # [:head, :get, :put, :post, :delete]
86
+ def self.get_methods(opts)
87
+ return opts[:methods] unless opts[:methods].empty?
88
+ [:head, :get, :put, :post, :delete]
89
+ end
90
+
91
+ #
92
+ # Just some defaults to initialize thing
93
+ #
94
+ def self.default_methods_hash
95
+ { head: {},
96
+ get: {},
97
+ put: {},
98
+ post: {},
99
+ delete: {}
100
+ }
101
+ end
102
+
103
+ #
104
+ # Find the right adapter for a route
105
+ #
106
+ def self.adapters_for_route(route, method)
107
+ @adapters ||= default_methods_hash
108
+ matches = []
109
+ @adapters[method].map do |reg_route, adapters|
110
+ next unless reg_route.match(route)
111
+ matches += adapters
112
+ end
113
+ matches.uniq
114
+ end
115
+
116
+ #
117
+ # Find the right merger for a route
118
+ #
119
+ def self.merger_for_route(route, method)
120
+ @mergers ||= default_methods_hash
121
+ @mergers[method].each do |reg_route, mergers|
122
+ next unless reg_route.match(route)
123
+ return mergers.first
124
+ end
125
+ raise "Found no merger for route #{route}"
126
+ end
127
+
128
+ #
129
+ # Make sure one class is a subclass of another class
130
+ #
131
+ def self.validate_type(c, expected)
132
+ return if c < expected
133
+ raise "Invalid type. Expected #{expected} got #{c}"
134
+ end
135
+ end
136
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "tom"
8
- s.version = "0.2.0"
8
+ s.version = "0.2.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jannis Hermanns"]
12
- s.date = "2011-12-06"
12
+ s.date = "2011-12-07"
13
13
  s.description = " Tom uses Goliath to dispatch HTTP requests to multiple other APIs (via Adapters) in parallel. In a next step, a Merger merges the result and responds to the clients request."
14
14
  s.email = "jannis@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -27,10 +27,14 @@ Gem::Specification.new do |s|
27
27
  "VERSION",
28
28
  "lib/adapter.rb",
29
29
  "lib/dispatcher.rb",
30
+ "lib/goliath_api.rb",
30
31
  "lib/http.rb",
31
32
  "lib/init.rb",
32
33
  "lib/merger.rb",
33
34
  "lib/tom.rb",
35
+ "lib/tom/config.rb",
36
+ "lib/tom/log.rb",
37
+ "lib/tom/routes.rb",
34
38
  "spec/lib/adapter_spec.rb",
35
39
  "spec/lib/dispatcher_spec.rb",
36
40
  "spec/spec_helper.rb",
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-12-06 00:00:00.000000000Z
12
+ date: 2011-12-07 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: goliath
16
- requirement: &70326256348120 !ruby/object:Gem::Requirement
16
+ requirement: &70109120203120 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70326256348120
24
+ version_requirements: *70109120203120
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: em-synchrony
27
- requirement: &70326256347400 !ruby/object:Gem::Requirement
27
+ requirement: &70109120202620 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70326256347400
35
+ version_requirements: *70109120202620
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: em-http-request
38
- requirement: &70326256346700 !ruby/object:Gem::Requirement
38
+ requirement: &70109120202140 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *70326256346700
46
+ version_requirements: *70109120202140
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: json
49
- requirement: &70326256345860 !ruby/object:Gem::Requirement
49
+ requirement: &70109120201560 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *70326256345860
57
+ version_requirements: *70109120201560
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &70326256345260 !ruby/object:Gem::Requirement
60
+ requirement: &70109120201040 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ~>
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: 0.9.2
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *70326256345260
68
+ version_requirements: *70109120201040
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: bundler
71
- requirement: &70326256344680 !ruby/object:Gem::Requirement
71
+ requirement: &70109120200460 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ~>
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: 1.0.0
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70326256344680
79
+ version_requirements: *70109120200460
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: jeweler
82
- requirement: &70326256344180 !ruby/object:Gem::Requirement
82
+ requirement: &70109120199960 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ~>
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: 1.6.4
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70326256344180
90
+ version_requirements: *70109120199960
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: shoulda
93
- requirement: &70326256343660 !ruby/object:Gem::Requirement
93
+ requirement: &70109120199420 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70326256343660
101
+ version_requirements: *70109120199420
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: rcov
104
- requirement: &70326256343040 !ruby/object:Gem::Requirement
104
+ requirement: &70109120198820 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,10 +109,10 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70326256343040
112
+ version_requirements: *70109120198820
113
113
  - !ruby/object:Gem::Dependency
114
114
  name: ruby-debug19
115
- requirement: &70326256342520 !ruby/object:Gem::Requirement
115
+ requirement: &70109120198220 !ruby/object:Gem::Requirement
116
116
  none: false
117
117
  requirements:
118
118
  - - ! '>='
@@ -120,10 +120,10 @@ dependencies:
120
120
  version: '0'
121
121
  type: :development
122
122
  prerelease: false
123
- version_requirements: *70326256342520
123
+ version_requirements: *70109120198220
124
124
  - !ruby/object:Gem::Dependency
125
125
  name: rspec
126
- requirement: &70326256342000 !ruby/object:Gem::Requirement
126
+ requirement: &70109120197620 !ruby/object:Gem::Requirement
127
127
  none: false
128
128
  requirements:
129
129
  - - ! '>='
@@ -131,10 +131,10 @@ dependencies:
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
- version_requirements: *70326256342000
134
+ version_requirements: *70109120197620
135
135
  - !ruby/object:Gem::Dependency
136
136
  name: webmock
137
- requirement: &70326256341460 !ruby/object:Gem::Requirement
137
+ requirement: &70109120197020 !ruby/object:Gem::Requirement
138
138
  none: false
139
139
  requirements:
140
140
  - - ! '>='
@@ -142,10 +142,10 @@ dependencies:
142
142
  version: '0'
143
143
  type: :development
144
144
  prerelease: false
145
- version_requirements: *70326256341460
145
+ version_requirements: *70109120197020
146
146
  - !ruby/object:Gem::Dependency
147
147
  name: yard
148
- requirement: &70326256340960 !ruby/object:Gem::Requirement
148
+ requirement: &70109120196420 !ruby/object:Gem::Requirement
149
149
  none: false
150
150
  requirements:
151
151
  - - ! '>='
@@ -153,10 +153,10 @@ dependencies:
153
153
  version: '0'
154
154
  type: :development
155
155
  prerelease: false
156
- version_requirements: *70326256340960
156
+ version_requirements: *70109120196420
157
157
  - !ruby/object:Gem::Dependency
158
158
  name: rdiscount
159
- requirement: &70326256340460 !ruby/object:Gem::Requirement
159
+ requirement: &70109120195780 !ruby/object:Gem::Requirement
160
160
  none: false
161
161
  requirements:
162
162
  - - ! '>='
@@ -164,7 +164,7 @@ dependencies:
164
164
  version: '0'
165
165
  type: :development
166
166
  prerelease: false
167
- version_requirements: *70326256340460
167
+ version_requirements: *70109120195780
168
168
  description: ! ' Tom uses Goliath to dispatch HTTP requests to multiple other APIs
169
169
  (via Adapters) in parallel. In a next step, a Merger merges the result and responds
170
170
  to the clients request.'
@@ -185,10 +185,14 @@ files:
185
185
  - VERSION
186
186
  - lib/adapter.rb
187
187
  - lib/dispatcher.rb
188
+ - lib/goliath_api.rb
188
189
  - lib/http.rb
189
190
  - lib/init.rb
190
191
  - lib/merger.rb
191
192
  - lib/tom.rb
193
+ - lib/tom/config.rb
194
+ - lib/tom/log.rb
195
+ - lib/tom/routes.rb
192
196
  - spec/lib/adapter_spec.rb
193
197
  - spec/lib/dispatcher_spec.rb
194
198
  - spec/spec_helper.rb
@@ -208,7 +212,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
208
212
  version: '0'
209
213
  segments:
210
214
  - 0
211
- hash: -2944832155486996740
215
+ hash: 1267034355888235248
212
216
  required_rubygems_version: !ruby/object:Gem::Requirement
213
217
  none: false
214
218
  requirements: