alephant-broker 0.1.6 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/alephant/broker.rb +40 -5
  3. data/lib/alephant/broker/component.rb +74 -0
  4. data/lib/alephant/broker/{call_environment.rb → environment.rb} +11 -7
  5. data/lib/alephant/broker/request.rb +13 -0
  6. data/lib/alephant/broker/request/asset.rb +37 -0
  7. data/lib/alephant/broker/request/batch.rb +38 -0
  8. data/lib/alephant/broker/request/factory.rb +24 -0
  9. data/lib/alephant/broker/request/handler.rb +35 -0
  10. data/lib/alephant/broker/response.rb +23 -0
  11. data/lib/alephant/broker/response/asset.rb +28 -0
  12. data/lib/alephant/broker/response/base.rb +60 -0
  13. data/lib/alephant/broker/response/batch.rb +45 -0
  14. data/lib/alephant/broker/response/factory.rb +27 -0
  15. data/lib/alephant/broker/version.rb +1 -1
  16. data/spec/rack_spec.rb +14 -15
  17. data/spec/spec_helper.rb +0 -1
  18. metadata +14 -27
  19. data/lib/alephant/broker/app.rb +0 -20
  20. data/lib/alephant/broker/app/rack.rb +0 -25
  21. data/lib/alephant/broker/models/request.rb +0 -41
  22. data/lib/alephant/broker/models/request/error_request.rb +0 -11
  23. data/lib/alephant/broker/models/request/get_request.rb +0 -38
  24. data/lib/alephant/broker/models/request/notfound_request.rb +0 -11
  25. data/lib/alephant/broker/models/request/post_request.rb +0 -50
  26. data/lib/alephant/broker/models/request/status_request.rb +0 -11
  27. data/lib/alephant/broker/models/request_factory.rb +0 -26
  28. data/lib/alephant/broker/models/request_handler.rb +0 -50
  29. data/lib/alephant/broker/models/response.rb +0 -27
  30. data/lib/alephant/broker/models/response/asset_response.rb +0 -90
  31. data/lib/alephant/broker/models/response/batch_response.rb +0 -61
  32. data/lib/alephant/broker/models/response_factory.rb +0 -39
  33. data/spec/asset_response_spec.rb +0 -78
  34. data/spec/batch_response_spec.rb +0 -87
  35. data/spec/get_request_spec.rb +0 -72
  36. data/spec/post_request_spec.rb +0 -49
  37. data/spec/response_factory_spec.rb +0 -60
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7410ac49baac4bf594eabcfde56e669343902682
4
- data.tar.gz: 1ab7c48a49eb1e41182d4968c9cfe14a736032ce
3
+ metadata.gz: 38bbbde873e9befab83b241a575c79c3e60bb587
4
+ data.tar.gz: d6d650f9cb5e9e50ff3b665cc4f9f6759110c279
5
5
  SHA512:
6
- metadata.gz: 197a8602b01a878fd66154c23e4a783f4cc1fc7603c351ac016a55d6df5b9ab87bc07a12ece82a7dbeda6c0ab3f25f76912ce0e2befed2a730525f8bad39e251
7
- data.tar.gz: a5f6f485240d886380682631df0b558377a46b8d65838b87d9c4aa5216d4b5cb39bfb3cf2a2d483b51648585ddc5683d956c3aa74a9d0e609972031d46e476be
6
+ metadata.gz: faf61092ff24d4b65bbeee0dc8915662e731d8ed067ce6a789d0a663d2bc2ada0d6da2640424711decfa3500f97ec54a65a4124d918216dc28bb7bc0ab359079
7
+ data.tar.gz: 78132a0acdd19c4eda3ad0e3a5363bb4ec07081fd37c6364578e09baa786ffb580177b457b4c2ee3c488dd2486564d77dc9ba44d5e156094ece521c05e676519
@@ -1,12 +1,47 @@
1
- require "alephant/broker/version"
2
- require "alephant/broker/models/request_handler"
1
+ require 'alephant/broker/version'
2
+ require 'alephant/broker/request'
3
+ require 'alephant/broker/environment'
4
+ require 'alephant/broker'
3
5
 
4
6
  module Alephant
5
7
  module Broker
6
8
 
7
- def self.handle(config = {})
8
- RequestHandler.new(config).process
9
+ def self.handle(env)
10
+ Request::Handler.process env
9
11
  end
10
- end
11
12
 
13
+ def self.config
14
+ @@configuration
15
+ end
16
+
17
+ def self.config=(c)
18
+ @@configuration = c
19
+ end
20
+
21
+ class Application
22
+ def initialize(c = nil)
23
+ Broker.config = c unless c.nil?
24
+ end
25
+
26
+ def call(env)
27
+ send response_for(environment_for(env))
28
+ end
29
+
30
+ def environment_for(env)
31
+ Environment.new env
32
+ end
33
+
34
+ def response_for(call_environment)
35
+ Broker.handle call_environment
36
+ end
37
+
38
+ def send(response)
39
+ [
40
+ response.status,
41
+ { "Content-Type" => response.content_type },
42
+ [ response.content.to_s ]
43
+ ]
44
+ end
45
+ end
46
+ end
12
47
  end
@@ -0,0 +1,74 @@
1
+ require 'crimp'
2
+ require 'alephant/logger'
3
+ require 'alephant/cache'
4
+ require 'alephant/lookup'
5
+ require 'alephant/broker/errors/invalid_cache_key'
6
+ require 'alephant/sequencer'
7
+
8
+ module Alephant
9
+ module Broker
10
+ class Component
11
+ include Logger
12
+
13
+ attr_reader :id, :batch_id, :options, :content
14
+
15
+ def initialize(id, batch_id, options)
16
+ @id = id
17
+ @batch_id = batch_id
18
+ @options = symbolize(options || {})
19
+ end
20
+
21
+ def load
22
+ @content ||= cache.get(s3_path)
23
+ end
24
+
25
+ def opts_hash
26
+ @opts_hash ||= Crimp.signature(options)
27
+ end
28
+
29
+ def version
30
+ @version ||= sequencer.get_last_seen
31
+ end
32
+
33
+ private
34
+
35
+ def symbolize(hash)
36
+ Hash[hash.map { |k,v| [k.to_sym, v] }]
37
+ end
38
+
39
+ def cache
40
+ @cache ||= Alephant::Cache.new(
41
+ Broker.config[:s3_bucket_id],
42
+ Broker.config[:s3_object_path]
43
+ )
44
+ end
45
+
46
+ def s3_path
47
+ lookup.read(id, options, version).tap do |lookup_object|
48
+ raise InvalidCacheKey if lookup_object.location.nil?
49
+ end.location unless version.nil?
50
+ end
51
+
52
+ def lookup
53
+ @lookup ||= Alephant::Lookup.create(Broker.config[:lookup_table_name])
54
+ end
55
+
56
+ def key
57
+ batch_id.nil? ? component_key : renderer_key
58
+ end
59
+
60
+ def component_key
61
+ "#{id}/#{opts_hash}"
62
+ end
63
+
64
+ def renderer_key
65
+ "#{batch_id}/#{opts_hash}"
66
+ end
67
+
68
+ def sequencer
69
+ @sequencer ||= Alephant::Sequencer.create(Broker.config[:sequencer_table_name], key)
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -1,8 +1,9 @@
1
1
  require 'json'
2
+ require 'alephant/logger'
2
3
 
3
4
  module Alephant
4
5
  module Broker
5
- class CallEnvironment
6
+ class Environment
6
7
  include Logger
7
8
  attr_reader :settings
8
9
 
@@ -23,15 +24,18 @@ module Alephant
23
24
  end
24
25
 
25
26
  def query
26
- settings['QUERY_STRING']
27
+ settings['QUERY_STRING'] || ""
27
28
  end
28
29
 
29
- def path
30
- settings['PATH_INFO']
30
+ def options
31
+ query.split('&').reduce({}) do |object, key_pair|
32
+ key, value = key_pair.split('=')
33
+ object.tap { |o| o.store(key.to_sym, value) }
34
+ end
31
35
  end
32
36
 
33
- def request_type
34
- path.split('/')[1]
37
+ def path
38
+ settings['PATH_INFO']
35
39
  end
36
40
 
37
41
  def data
@@ -41,7 +45,7 @@ module Alephant
41
45
  private
42
46
 
43
47
  def rack_input
44
- (settings['rack.input'].read).tap { settings['rack.input'].rewind } # http://rack.rubyforge.org/doc/SPEC.html
48
+ (settings['rack.input'].read).tap { settings['rack.input'].rewind }
45
49
  end
46
50
 
47
51
  def parse(json)
@@ -0,0 +1,13 @@
1
+ module Alephant
2
+ module Broker
3
+ module Request
4
+ require 'alephant/broker/request/asset'
5
+ require 'alephant/broker/request/batch'
6
+ require 'alephant/broker/request/factory'
7
+ require 'alephant/broker/request/handler'
8
+
9
+ class NotFound; end
10
+ class Status; end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,37 @@
1
+ require 'alephant/logger'
2
+ require 'alephant/broker/component'
3
+ require 'alephant/broker/errors/invalid_asset_id'
4
+
5
+ module Alephant
6
+ module Broker
7
+ module Request
8
+ class Asset
9
+ include Logger
10
+
11
+ attr_reader :component
12
+
13
+ def initialize(env)
14
+ logger.info("Request::Asset#initialize(#{env.settings})")
15
+ component_id = component_id_for env.path
16
+
17
+ @component = Component.new(
18
+ component_id,
19
+ nil,
20
+ env.options
21
+ )
22
+
23
+ logger.info("Request::Asset#initialize: id: #{component_id}")
24
+ raise InvalidAssetId.new("No Asset ID specified") if component_id.nil?
25
+ end
26
+
27
+ private
28
+
29
+ def component_id_for(path)
30
+ path.split('/')[2] || nil
31
+ end
32
+
33
+ end
34
+ end
35
+ end
36
+ end
37
+
@@ -0,0 +1,38 @@
1
+ require 'alephant/logger'
2
+ require 'alephant/broker/component'
3
+
4
+
5
+ module Alephant
6
+ module Broker
7
+ module Request
8
+ class Batch
9
+ include Logger
10
+
11
+ attr_reader :batch_id, :components
12
+
13
+ def initialize(env)
14
+ logger.info("Request::Batch#initialize(#{env.settings})")
15
+
16
+ @batch_id = env.data['batch_id']
17
+ @components = components_for env
18
+
19
+ logger.info("Request::Batch#initialize: id: #{@batch_id}")
20
+ end
21
+
22
+ private
23
+
24
+ def components_for(env)
25
+ env.data['components'].map do |c|
26
+ Component.new(
27
+ c['component'],
28
+ batch_id,
29
+ c['options']
30
+ )
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,24 @@
1
+ require 'alephant/broker/request'
2
+
3
+ module Alephant::Broker::Request
4
+ class Factory
5
+
6
+ def self.request_type_from(env)
7
+ env.path.split('/')[1]
8
+ end
9
+
10
+ def self.request_for(env)
11
+ case request_type_from(env)
12
+ when 'component'
13
+ Asset.new(env)
14
+ when 'components'
15
+ Batch.new(env)
16
+ when 'status'
17
+ Status.new
18
+ else
19
+ NotFound.new
20
+ end
21
+ end
22
+ end
23
+ end
24
+
@@ -0,0 +1,35 @@
1
+ require 'alephant/logger'
2
+
3
+ require 'alephant/broker/request'
4
+ require 'alephant/broker/response'
5
+ require 'alephant/broker/request/factory'
6
+ require 'alephant/broker/response/factory'
7
+
8
+ module Alephant
9
+ module Broker
10
+ module Request
11
+ class Handler
12
+ extend Logger
13
+
14
+ def self.request_for(env)
15
+ Request::Factory.request_for env
16
+ end
17
+
18
+ def self.response_for(request)
19
+ Response::Factory.response_for request
20
+ end
21
+
22
+ def self.process(env)
23
+ begin
24
+ response_for request_for(env)
25
+ rescue Exception => e
26
+ logger.info("Broker.requestHandler.process: Exception raised (#{e.message}, #{e.backtrace.join('\n')})")
27
+ Response::Factory.error
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,23 @@
1
+ module Alephant
2
+ module Broker
3
+ module Response
4
+ require 'alephant/broker/response/base'
5
+ require 'alephant/broker/response/asset'
6
+ require 'alephant/broker/response/batch'
7
+ require 'alephant/broker/response/factory'
8
+
9
+ class NotFound < Base
10
+ def initialize; super(404) end
11
+ end
12
+
13
+ class Status < Base
14
+ def initialize; super(200) end
15
+ end
16
+
17
+ class ServerError < Base
18
+ def initialize; super(500) end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,28 @@
1
+ require 'alephant/broker/errors/invalid_cache_key'
2
+ require 'alephant/logger'
3
+
4
+ module Alephant
5
+ module Broker
6
+ module Response
7
+ class Asset < Base
8
+ include Logger
9
+
10
+ attr_reader :component
11
+
12
+ def initialize(component)
13
+ @component = component
14
+ super()
15
+ end
16
+
17
+ def setup
18
+ result = load(component)
19
+
20
+ @status = result['status']
21
+ @content = result['body']
22
+ end
23
+
24
+ end
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,60 @@
1
+ require 'aws-sdk'
2
+
3
+ module Alephant
4
+ module Broker
5
+ module Response
6
+ class Base
7
+ attr_accessor :status, :content, :content_type
8
+
9
+ STATUS_CODE_MAPPING = {
10
+ 200 => 'ok',
11
+ 404 => 'Not found',
12
+ 500 => 'Error retrieving content'
13
+ }
14
+
15
+ def initialize(status = 200, content_type = "text/html")
16
+ @content_type = content_type
17
+ @status = status
18
+ @content = STATUS_CODE_MAPPING[status]
19
+
20
+ setup
21
+ end
22
+
23
+ protected
24
+
25
+ def setup; end
26
+
27
+ def load(component)
28
+ begin
29
+ body = component.load
30
+ status = 200
31
+ rescue AWS::S3::Errors::NoSuchKey, InvalidCacheKey => e
32
+ body = "#{error_for(e)}"
33
+ status = 404
34
+ rescue StandardError => e
35
+ body = "#{error_for(e)}"
36
+ status = 500
37
+ end
38
+
39
+ log(component, status, e)
40
+
41
+ { 'body' => body, 'status' => status }
42
+ end
43
+
44
+ def log(c, status, e = nil)
45
+ logger.info("Broker: Component loaded: #{details_for(c)} (#{status}) #{error_for(e)}")
46
+ end
47
+
48
+ def details_for(c)
49
+ "#{c.id}/#{c.opts_hash}/#{c.version} #{c.batch_id.nil? ? '' : "batched"} (#{c.options})"
50
+ end
51
+
52
+ def error_for(e)
53
+ e.nil? ? nil : "#{e.message}\n#{e.backtrace.join('\n')}"
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
60
+