alephant-broker 1.2.1 → 1.3.1
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 +4 -4
- data/Rakefile +1 -2
- data/alephant-broker.gemspec +2 -2
- data/lib/alephant/broker.rb +11 -11
- data/lib/alephant/broker/component.rb +20 -67
- data/lib/alephant/broker/component_factory.rb +30 -0
- data/lib/alephant/broker/component_meta.rb +51 -0
- data/lib/alephant/broker/error_component.rb +42 -0
- data/lib/alephant/broker/errors/content_not_found.rb +7 -0
- data/lib/alephant/broker/errors/invalid_cache_key.rb +1 -3
- data/lib/alephant/broker/load_strategy/s3.rb +88 -0
- data/lib/alephant/broker/request/asset.rb +2 -3
- data/lib/alephant/broker/request/batch.rb +4 -5
- data/lib/alephant/broker/request/factory.rb +23 -18
- data/lib/alephant/broker/request/handler.rb +5 -10
- data/lib/alephant/broker/response/asset.rb +17 -10
- data/lib/alephant/broker/response/base.rb +5 -53
- data/lib/alephant/broker/response/batch.rb +12 -9
- data/lib/alephant/broker/response/factory.rb +4 -0
- data/lib/alephant/broker/version.rb +1 -1
- data/spec/fixtures/json/batch.json +1 -0
- data/spec/fixtures/json/batch_compiled.json +1 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/rack_spec.rb +97 -96
- data/spec/spec_helper.rb +4 -0
- metadata +57 -46
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54b3da006e03b9b1bb3a4697ef59e5472a872481
|
4
|
+
data.tar.gz: b6fb65f722c3cb34f5589327dc1478244d1367fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc7a8957b4a78a63681e211df68fb18a8bd27c48093a858afab1a394bcc07809666c36f3ac5e711e2726372c306385fb53e1099bc274753a6b7b74e3e562554c
|
7
|
+
data.tar.gz: 6b16b372746c156f6ec2a93c7f906985f88e25e5445df00d4539b1d0567c3408889d2b6f85ab85c99194a820af74c0f187649cb5e4b6341215cb5ae41cd6134a
|
data/Rakefile
CHANGED
data/alephant-broker.gemspec
CHANGED
@@ -25,16 +25,16 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency "pry"
|
26
26
|
spec.add_development_dependency "pry-remote"
|
27
27
|
spec.add_development_dependency "pry-nav"
|
28
|
+
spec.add_development_dependency "rake-rspec", ">= 0.0.2"
|
28
29
|
|
29
30
|
spec.add_development_dependency "bundler", "~> 1.5"
|
30
31
|
spec.add_development_dependency "rake"
|
31
32
|
spec.add_development_dependency "rack-test"
|
32
33
|
|
33
|
-
spec.add_runtime_dependency "request_store"
|
34
|
-
spec.add_runtime_dependency "peach"
|
35
34
|
spec.add_runtime_dependency "alephant-lookup"
|
36
35
|
spec.add_runtime_dependency "alephant-cache"
|
37
36
|
spec.add_runtime_dependency 'alephant-logger'
|
38
37
|
spec.add_runtime_dependency 'alephant-sequencer'
|
39
38
|
spec.add_runtime_dependency "dalli-elasticache"
|
39
|
+
spec.add_runtime_dependency 'pmap'
|
40
40
|
end
|
data/lib/alephant/broker.rb
CHANGED
@@ -8,8 +8,8 @@ module Alephant
|
|
8
8
|
module Broker
|
9
9
|
@@poll = true
|
10
10
|
|
11
|
-
def self.handle(env)
|
12
|
-
Request::Handler.process env
|
11
|
+
def self.handle(load_strategy, env)
|
12
|
+
Request::Handler.process(load_strategy, env)
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.config
|
@@ -29,8 +29,11 @@ module Alephant
|
|
29
29
|
end
|
30
30
|
|
31
31
|
class Application
|
32
|
-
|
32
|
+
attr_reader :load_strategy
|
33
|
+
|
34
|
+
def initialize(load_strategy, c = nil)
|
33
35
|
Broker.config = c unless c.nil?
|
36
|
+
@load_strategy = load_strategy
|
34
37
|
end
|
35
38
|
|
36
39
|
def call(env)
|
@@ -46,19 +49,16 @@ module Alephant
|
|
46
49
|
end
|
47
50
|
|
48
51
|
def response_for(call_environment)
|
49
|
-
Broker.handle call_environment
|
52
|
+
Broker.handle(load_strategy, call_environment)
|
50
53
|
end
|
51
54
|
|
52
55
|
def send(response)
|
53
56
|
[
|
54
57
|
response.status,
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
"X-Cached" => response.cached.to_s
|
60
|
-
}.merge(response.headers),
|
61
|
-
[ response.content.to_s ]
|
58
|
+
response.headers,
|
59
|
+
[
|
60
|
+
response.content.to_s
|
61
|
+
]
|
62
62
|
]
|
63
63
|
end
|
64
64
|
|
@@ -8,89 +8,42 @@ require 'alephant/broker/cache'
|
|
8
8
|
|
9
9
|
module Alephant
|
10
10
|
module Broker
|
11
|
-
|
12
11
|
class Component
|
13
|
-
|
14
|
-
|
15
|
-
attr_reader :id, :batch_id, :options, :content, :content_type, :cached
|
12
|
+
attr_reader :id, :batch_id, :options, :content, :opts_hash
|
16
13
|
|
17
|
-
def initialize(
|
18
|
-
@id
|
19
|
-
@batch_id
|
20
|
-
@
|
21
|
-
@
|
22
|
-
@
|
14
|
+
def initialize(meta, data)
|
15
|
+
@id = meta.id
|
16
|
+
@batch_id = meta.batch_id
|
17
|
+
@options = symbolize(meta.options || {})
|
18
|
+
@content = data[:content].force_encoding 'UTF-8'
|
19
|
+
@opts_hash = meta.opts_hash
|
20
|
+
@data = data
|
21
|
+
@meta = meta
|
23
22
|
end
|
24
23
|
|
25
|
-
def
|
26
|
-
|
27
|
-
@content = cache_object[:content]
|
28
|
-
rescue
|
29
|
-
content_hash = @cache.set(cache_key, retrieve_object)
|
30
|
-
@content_type = content_hash[:content_type]
|
31
|
-
@content = content_hash[:content]
|
24
|
+
def content_type
|
25
|
+
headers['Content-Type']
|
32
26
|
end
|
33
27
|
|
34
|
-
def
|
35
|
-
|
28
|
+
def headers
|
29
|
+
{
|
30
|
+
'Content-Type' => data[:content_type].to_s,
|
31
|
+
'X-Version' => meta.version.to_s,
|
32
|
+
'X-Cached' => meta.cached.to_s
|
33
|
+
}.merge(data[:headers] || {})
|
36
34
|
end
|
37
35
|
|
38
|
-
def
|
39
|
-
|
36
|
+
def status
|
37
|
+
200
|
40
38
|
end
|
41
39
|
|
42
40
|
private
|
43
41
|
|
44
|
-
|
45
|
-
@cache_object ||= @cache.get(cache_key) { retrieve_object }
|
46
|
-
end
|
47
|
-
|
48
|
-
def retrieve_object
|
49
|
-
@cached = false
|
50
|
-
s3.get(s3_path)
|
51
|
-
end
|
52
|
-
|
53
|
-
def cache_key
|
54
|
-
@cache_key ||= "#{id}/#{opts_hash}/#{version}"
|
55
|
-
end
|
42
|
+
attr_reader :meta, :data
|
56
43
|
|
57
44
|
def symbolize(hash)
|
58
45
|
Hash[hash.map { |k,v| [k.to_sym, v] }]
|
59
46
|
end
|
60
|
-
|
61
|
-
def s3
|
62
|
-
@s3_cache ||= Alephant::Cache.new(
|
63
|
-
Broker.config[:s3_bucket_id],
|
64
|
-
Broker.config[:s3_object_path]
|
65
|
-
)
|
66
|
-
end
|
67
|
-
|
68
|
-
def s3_path
|
69
|
-
lookup.read(id, options, version).tap do |lookup_object|
|
70
|
-
raise InvalidCacheKey if lookup_object.location.nil?
|
71
|
-
end.location unless version.nil?
|
72
|
-
end
|
73
|
-
|
74
|
-
def lookup
|
75
|
-
@lookup ||= Alephant::Lookup.create(Broker.config[:lookup_table_name])
|
76
|
-
end
|
77
|
-
|
78
|
-
def key
|
79
|
-
batch_id.nil? ? component_key : renderer_key
|
80
|
-
end
|
81
|
-
|
82
|
-
def component_key
|
83
|
-
"#{id}/#{opts_hash}"
|
84
|
-
end
|
85
|
-
|
86
|
-
def renderer_key
|
87
|
-
"#{batch_id}/#{opts_hash}"
|
88
|
-
end
|
89
|
-
|
90
|
-
def sequencer
|
91
|
-
@sequencer ||= Alephant::Sequencer.create(Broker.config[:sequencer_table_name], key)
|
92
|
-
end
|
93
|
-
|
94
47
|
end
|
95
48
|
end
|
96
49
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'alephant/broker/component_meta'
|
2
|
+
require 'alephant/broker/errors/content_not_found'
|
3
|
+
require 'alephant/broker/error_component'
|
4
|
+
require 'alephant/logger'
|
5
|
+
|
6
|
+
module Alephant
|
7
|
+
module Broker
|
8
|
+
class ComponentFactory
|
9
|
+
include Logger
|
10
|
+
|
11
|
+
def initialize(load_strategy)
|
12
|
+
@load_strategy = load_strategy
|
13
|
+
end
|
14
|
+
|
15
|
+
def create(id, batch_id, options)
|
16
|
+
component_meta = ComponentMeta.new(id, batch_id, options)
|
17
|
+
Component.new(
|
18
|
+
component_meta,
|
19
|
+
@load_strategy.load(component_meta)
|
20
|
+
)
|
21
|
+
rescue Alephant::Broker::Errors::ContentNotFound
|
22
|
+
logger.warn 'Broker.ComponentFactory.create: Exception raised (ContentNotFound)'
|
23
|
+
ErrorComponent.new(component_meta, 404)
|
24
|
+
rescue => e
|
25
|
+
logger.warn("Broker.ComponentFactory.create: Exception raised (#{e.message}, #{e.backtrace.join('\n')})")
|
26
|
+
ErrorComponent.new(component_meta, 500, e)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Alephant
|
2
|
+
module Broker
|
3
|
+
class ComponentMeta
|
4
|
+
attr_reader :id, :options, :batch_id
|
5
|
+
attr_accessor :cached
|
6
|
+
|
7
|
+
def initialize(id, batch_id, options)
|
8
|
+
@id = id
|
9
|
+
@batch_id = batch_id
|
10
|
+
@options = options
|
11
|
+
@cached = true
|
12
|
+
end
|
13
|
+
|
14
|
+
def cache_key
|
15
|
+
"#{id}/#{opts_hash}/#{version}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def version
|
19
|
+
Broker.config.fetch(
|
20
|
+
'elasticache_cache_version', 'not available'
|
21
|
+
).to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def key
|
25
|
+
batch_id.nil? ? component_key : renderer_key
|
26
|
+
end
|
27
|
+
|
28
|
+
def opts_hash
|
29
|
+
Crimp.signature options
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def component_key
|
35
|
+
"#{id}/#{opts_hash}"
|
36
|
+
end
|
37
|
+
|
38
|
+
def renderer_key
|
39
|
+
"#{batch_id}/#{opts_hash}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def headers(data)
|
43
|
+
{
|
44
|
+
'Content-Type' => data[:content_type].to_s,
|
45
|
+
'X-Version' => version.to_s,
|
46
|
+
'X-Cached' => cached.to_s
|
47
|
+
}.merge(data[:headers] || {})
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Alephant
|
2
|
+
module Broker
|
3
|
+
class ErrorComponent
|
4
|
+
attr_reader :batch_id, :content, :id, :options, :status
|
5
|
+
|
6
|
+
def initialize(meta, status, body = nil)
|
7
|
+
@batch_id = meta.batch_id
|
8
|
+
@status = status
|
9
|
+
@content = content_for body
|
10
|
+
@id = meta.id
|
11
|
+
@options = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def content_type
|
15
|
+
headers['Content-Type']
|
16
|
+
end
|
17
|
+
|
18
|
+
def headers
|
19
|
+
{
|
20
|
+
'Content-Type' => 'text/plain'
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
STATUS_CODE_MAPPING = {
|
27
|
+
404 => 'Not found',
|
28
|
+
500 => 'Error retrieving content'
|
29
|
+
}
|
30
|
+
|
31
|
+
def content_for(body)
|
32
|
+
body.nil? ? STATUS_CODE_MAPPING[status]
|
33
|
+
: format_content_for(body)
|
34
|
+
end
|
35
|
+
|
36
|
+
def format_content_for(body)
|
37
|
+
body.is_a? Exception ? "#{e.message}\n#{e.backtrace.join('\n')}"
|
38
|
+
: body
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -1,11 +1,9 @@
|
|
1
1
|
module Alephant
|
2
2
|
module Broker
|
3
3
|
class InvalidCacheKey < Exception
|
4
|
-
|
5
4
|
def initialize
|
6
|
-
super
|
5
|
+
super 'Cache key not found based on component_id and options combination'
|
7
6
|
end
|
8
|
-
|
9
7
|
end
|
10
8
|
end
|
11
9
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require "alephant/broker/cache"
|
2
|
+
require 'alephant/broker/errors/content_not_found'
|
3
|
+
require 'alephant/broker/errors/invalid_cache_key'
|
4
|
+
|
5
|
+
module Alephant
|
6
|
+
module Broker
|
7
|
+
module LoadStrategy
|
8
|
+
class S3
|
9
|
+
def load(component_meta)
|
10
|
+
add_s3_headers(
|
11
|
+
cache_object(component_meta),
|
12
|
+
component_meta
|
13
|
+
)
|
14
|
+
rescue
|
15
|
+
add_s3_headers(
|
16
|
+
cache.set(
|
17
|
+
component_meta.cache_key,
|
18
|
+
retrieve_object(component_meta)
|
19
|
+
),
|
20
|
+
component_meta
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def add_s3_headers(component_data, component_meta)
|
27
|
+
component_data.merge(
|
28
|
+
{ headers: headers(component_meta) }
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def cache
|
33
|
+
@cache ||= Cache::Client.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def headers(component_meta)
|
37
|
+
{ 'X-Sequence' => sequence(component_meta).to_s }
|
38
|
+
end
|
39
|
+
|
40
|
+
def sequence(component_meta)
|
41
|
+
sequencer(component_meta).get_last_seen
|
42
|
+
end
|
43
|
+
|
44
|
+
def retrieve_object(component_meta)
|
45
|
+
component_meta.cached = false
|
46
|
+
s3.get s3_path(component_meta)
|
47
|
+
rescue AWS::S3::Errors::NoSuchKey, InvalidCacheKey
|
48
|
+
raise Alephant::Broker::Errors::ContentNotFound
|
49
|
+
end
|
50
|
+
|
51
|
+
def cache_object(component_meta)
|
52
|
+
cache.get(component_meta.cache_key) do
|
53
|
+
retrieve_object component_meta
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def s3
|
58
|
+
@s3 ||= Alephant::Cache.new(
|
59
|
+
Broker.config[:s3_bucket_id],
|
60
|
+
Broker.config[:s3_object_path]
|
61
|
+
)
|
62
|
+
end
|
63
|
+
|
64
|
+
def s3_path(component_meta)
|
65
|
+
lookup.read(
|
66
|
+
component_meta.id,
|
67
|
+
component_meta.options,
|
68
|
+
sequence(component_meta)
|
69
|
+
).tap do |obj|
|
70
|
+
raise InvalidCacheKey if obj.location.nil?
|
71
|
+
end.location unless sequence(component_meta).nil?
|
72
|
+
end
|
73
|
+
|
74
|
+
def lookup
|
75
|
+
@lookup ||= Alephant::Lookup.create(
|
76
|
+
Broker.config[:lookup_table_name]
|
77
|
+
)
|
78
|
+
end
|
79
|
+
|
80
|
+
def sequencer(component_meta)
|
81
|
+
Alephant::Sequencer.create(
|
82
|
+
Broker.config[:sequencer_table_name], component_meta.key
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -10,7 +10,7 @@ module Alephant
|
|
10
10
|
|
11
11
|
attr_accessor :component
|
12
12
|
|
13
|
-
def initialize(env = nil)
|
13
|
+
def initialize(component_factory, env = nil)
|
14
14
|
return if env.nil?
|
15
15
|
|
16
16
|
component_id = env.path.split('/')[2] || nil
|
@@ -18,9 +18,8 @@ module Alephant
|
|
18
18
|
|
19
19
|
raise InvalidAssetId.new("No Asset ID specified") if component_id.nil?
|
20
20
|
|
21
|
-
@component =
|
21
|
+
@component = component_factory.create(component_id, nil, options)
|
22
22
|
end
|
23
|
-
|
24
23
|
end
|
25
24
|
end
|
26
25
|
end
|