alephant-broker 3.13.0 → 3.14.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 +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -1
- data/Guardfile +2 -2
- data/Rakefile +5 -5
- data/alephant-broker.gemspec +1 -0
- data/lib/alephant/broker.rb +9 -38
- data/lib/alephant/broker/application.rb +34 -0
- data/lib/alephant/broker/cache.rb +2 -63
- data/lib/alephant/broker/cache/client.rb +57 -0
- data/lib/alephant/broker/cache/null_client.rb +15 -0
- data/lib/alephant/broker/component.rb +1 -1
- data/lib/alephant/broker/component_factory.rb +4 -4
- data/lib/alephant/broker/component_meta.rb +1 -1
- data/lib/alephant/broker/environment.rb +9 -11
- data/lib/alephant/broker/error_component.rb +4 -4
- data/lib/alephant/broker/errors.rb +9 -0
- data/lib/alephant/broker/errors/content_not_found.rb +1 -1
- data/lib/alephant/broker/errors/invalid_asset_id.rb +0 -2
- data/lib/alephant/broker/errors/invalid_cache_key.rb +1 -1
- data/lib/alephant/broker/load_strategy.rb +9 -0
- data/lib/alephant/broker/load_strategy/http.rb +9 -10
- data/lib/alephant/broker/load_strategy/s3/base.rb +6 -6
- data/lib/alephant/broker/load_strategy/s3/sequenced.rb +2 -5
- data/lib/alephant/broker/request.rb +4 -4
- data/lib/alephant/broker/request/asset.rb +3 -4
- data/lib/alephant/broker/request/batch.rb +5 -6
- data/lib/alephant/broker/request/factory.rb +2 -2
- data/lib/alephant/broker/request/handler.rb +4 -7
- data/lib/alephant/broker/response.rb +13 -8
- data/lib/alephant/broker/response/asset.rb +3 -4
- data/lib/alephant/broker/response/base.rb +10 -13
- data/lib/alephant/broker/response/batch.rb +8 -8
- data/lib/alephant/broker/response/factory.rb +1 -2
- data/lib/alephant/broker/version.rb +1 -1
- data/spec/{component_meta_spec.rb → alephant/broker/component_meta_spec.rb} +2 -2
- data/spec/{http_spec.rb → alephant/broker/load_strategy/http_spec.rb} +19 -18
- data/spec/{archive_spec.rb → alephant/broker/load_strategy/s3/archived_spec.rb} +1 -1
- data/spec/fixtures/json/batch_compiled.json +1 -1
- data/spec/integration/not_modified_response_spec.rb +4 -8
- data/spec/integration/rack_spec.rb +4 -4
- data/spec/spec_helper.rb +11 -10
- metadata +27 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a1de9bc629522c3ada2ac0f2ad0c08aa5024a037
|
4
|
+
data.tar.gz: b43733742699f3a88442386e88c4e77c3c782373
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d36de810da755b2210767bdeaf5e1d0230d65e1f43aea5266e19d569665f3b51255200fdb4ab14eafa925735f9b18b43f92c4403e20993b016cf9f4f68f64e3
|
7
|
+
data.tar.gz: 1ff51c8a99183673ba61538b20d9d12c6f1ee9d89091a88057bdad4d8d6c38230cf252242fc4569ea457c73d9cbe76d2ba3f24d5c4e411cdd2cc297de2008901
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Guardfile
CHANGED
data/Rakefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
require "bundler/gem_tasks"
|
5
|
+
require "alephant/broker"
|
6
|
+
require "rake/rspec"
|
7
7
|
|
8
8
|
task :default => :spec
|
data/alephant-broker.gemspec
CHANGED
@@ -30,6 +30,7 @@ Gem::Specification.new do |spec|
|
|
30
30
|
spec.add_development_dependency "bundler", "~> 1.5"
|
31
31
|
spec.add_development_dependency "rake"
|
32
32
|
spec.add_development_dependency "rack-test"
|
33
|
+
spec.add_development_dependency "simplecov"
|
33
34
|
|
34
35
|
spec.add_runtime_dependency "alephant-lookup"
|
35
36
|
spec.add_runtime_dependency "alephant-storage", ">= 1.1.1"
|
data/lib/alephant/broker.rb
CHANGED
@@ -1,52 +1,23 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "alephant/broker/version"
|
2
|
+
require "alephant/broker/request"
|
3
|
+
require "alephant/broker/environment"
|
4
|
+
require "alephant/broker/application"
|
5
|
+
require "alephant/broker/cache"
|
6
|
+
require "alephant/broker/load_strategy"
|
7
|
+
require "alephant/broker/errors"
|
5
8
|
|
6
9
|
module Alephant
|
7
10
|
module Broker
|
8
|
-
|
9
11
|
def self.handle(load_strategy, env)
|
10
12
|
Request::Handler.process(load_strategy, env)
|
11
13
|
end
|
12
14
|
|
13
15
|
def self.config
|
14
|
-
|
16
|
+
@configuration
|
15
17
|
end
|
16
18
|
|
17
19
|
def self.config=(c)
|
18
|
-
|
19
|
-
end
|
20
|
-
|
21
|
-
class Application
|
22
|
-
attr_reader :load_strategy
|
23
|
-
|
24
|
-
def initialize(load_strategy, c = nil)
|
25
|
-
Broker.config = c unless c.nil?
|
26
|
-
@load_strategy = load_strategy
|
27
|
-
end
|
28
|
-
|
29
|
-
def call(env)
|
30
|
-
send response_for(environment_for(env))
|
31
|
-
end
|
32
|
-
|
33
|
-
def environment_for(env)
|
34
|
-
Environment.new env
|
35
|
-
end
|
36
|
-
|
37
|
-
def response_for(call_environment)
|
38
|
-
Broker.handle(load_strategy, call_environment)
|
39
|
-
end
|
40
|
-
|
41
|
-
def send(response)
|
42
|
-
[
|
43
|
-
response.status,
|
44
|
-
response.headers,
|
45
|
-
[
|
46
|
-
response.content.to_s
|
47
|
-
]
|
48
|
-
]
|
49
|
-
end
|
20
|
+
@configuration = c
|
50
21
|
end
|
51
22
|
end
|
52
23
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Alephant
|
2
|
+
module Broker
|
3
|
+
class Application
|
4
|
+
attr_reader :load_strategy
|
5
|
+
|
6
|
+
def initialize(load_strategy, c = nil)
|
7
|
+
Broker.config = c unless c.nil?
|
8
|
+
@load_strategy = load_strategy
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
send response_for(environment_for(env))
|
13
|
+
end
|
14
|
+
|
15
|
+
def environment_for(env)
|
16
|
+
Environment.new env
|
17
|
+
end
|
18
|
+
|
19
|
+
def response_for(call_environment)
|
20
|
+
Broker.handle(load_strategy, call_environment)
|
21
|
+
end
|
22
|
+
|
23
|
+
def send(response)
|
24
|
+
[
|
25
|
+
response.status,
|
26
|
+
response.headers,
|
27
|
+
[
|
28
|
+
response.content.to_s
|
29
|
+
]
|
30
|
+
]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -1,69 +1,8 @@
|
|
1
|
-
require 'dalli-elasticache'
|
2
|
-
require 'alephant/logger'
|
3
|
-
|
4
1
|
module Alephant
|
5
2
|
module Broker
|
6
3
|
module Cache
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
DEFAULT_TTL = 2592000
|
11
|
-
|
12
|
-
def initialize
|
13
|
-
unless config_endpoint.nil?
|
14
|
-
@elasticache ||= ::Dalli::ElastiCache.new(config_endpoint, { :expires_in => ttl })
|
15
|
-
@client ||= @elasticache.client
|
16
|
-
else
|
17
|
-
logger.debug "Broker::Cache::Client#initialize: No config endpoint, NullClient used"
|
18
|
-
logger.metric "NoConfigEndpoint"
|
19
|
-
@client = NullClient.new
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def get(key, &block)
|
24
|
-
begin
|
25
|
-
versioned_key = versioned key
|
26
|
-
result = @client.get versioned_key
|
27
|
-
logger.info "Broker::Cache::Client#get key: #{versioned_key} - #{result ? 'hit' : 'miss'}"
|
28
|
-
logger.metric "GetKeyMiss" unless result
|
29
|
-
result ? result : set(key, block.call)
|
30
|
-
rescue StandardError => e
|
31
|
-
block.call if block_given?
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def set(key, value, ttl = nil)
|
36
|
-
value.tap { |o| @client.set(versioned(key), o, ttl) }
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def config_endpoint
|
42
|
-
Broker.config['elasticache_config_endpoint']
|
43
|
-
end
|
44
|
-
|
45
|
-
def ttl
|
46
|
-
Broker.config['elasticache_ttl'] || DEFAULT_TTL
|
47
|
-
end
|
48
|
-
|
49
|
-
def versioned(key)
|
50
|
-
[key, cache_version].compact.join('_')
|
51
|
-
end
|
52
|
-
|
53
|
-
def cache_version
|
54
|
-
Broker.config['elasticache_cache_version']
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
class NullClient
|
59
|
-
def get(key, &block)
|
60
|
-
yield
|
61
|
-
end
|
62
|
-
|
63
|
-
def set(key, value, ttl = nil)
|
64
|
-
value
|
65
|
-
end
|
66
|
-
end
|
4
|
+
require "alephant/broker/cache/client"
|
5
|
+
require "alephant/broker/cache/null_client"
|
67
6
|
end
|
68
7
|
end
|
69
8
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "dalli-elasticache"
|
2
|
+
require "alephant/logger"
|
3
|
+
|
4
|
+
module Alephant
|
5
|
+
module Broker
|
6
|
+
module Cache
|
7
|
+
class Client
|
8
|
+
include Logger
|
9
|
+
|
10
|
+
DEFAULT_TTL = 2_592_000
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
if config_endpoint.nil?
|
14
|
+
logger.debug "Broker::Cache::Client#initialize: No config endpoint, NullClient used"
|
15
|
+
logger.metric "NoConfigEndpoint"
|
16
|
+
@client = NullClient.new
|
17
|
+
else
|
18
|
+
@elasticache ||= ::Dalli::ElastiCache.new(config_endpoint, :expires_in => ttl)
|
19
|
+
@client ||= @elasticache.client
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def get(key)
|
24
|
+
versioned_key = versioned key
|
25
|
+
result = @client.get versioned_key
|
26
|
+
logger.info "Broker::Cache::Client#get key: #{versioned_key} - #{result ? 'hit' : 'miss'}"
|
27
|
+
logger.metric "GetKeyMiss" unless result
|
28
|
+
result ? result : set(key, block.call)
|
29
|
+
rescue StandardError => e
|
30
|
+
yield if block_given?
|
31
|
+
end
|
32
|
+
|
33
|
+
def set(key, value, ttl = nil)
|
34
|
+
value.tap { |o| @client.set(versioned(key), o, ttl) }
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def config_endpoint
|
40
|
+
Broker.config["elasticache_config_endpoint"]
|
41
|
+
end
|
42
|
+
|
43
|
+
def ttl
|
44
|
+
Broker.config["elasticache_ttl"] || DEFAULT_TTL
|
45
|
+
end
|
46
|
+
|
47
|
+
def versioned(key)
|
48
|
+
[key, cache_version].compact.join("_")
|
49
|
+
end
|
50
|
+
|
51
|
+
def cache_version
|
52
|
+
Broker.config["elasticache_cache_version"]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
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
5
|
|
6
6
|
module Alephant
|
7
7
|
module Broker
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
1
|
+
require "json"
|
2
|
+
require "alephant/logger"
|
3
|
+
require "rack"
|
4
4
|
|
5
5
|
module Alephant
|
6
6
|
module Broker
|
@@ -55,17 +55,15 @@ module Alephant
|
|
55
55
|
private
|
56
56
|
|
57
57
|
def rack_input
|
58
|
-
|
58
|
+
settings["rack.input"].read.tap { settings["rack.input"].rewind }
|
59
59
|
end
|
60
60
|
|
61
61
|
def parse(json)
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
nil
|
68
|
-
end
|
62
|
+
::JSON.parse(json)
|
63
|
+
rescue ::JSON::ParserError => e
|
64
|
+
logger.warn "Broker.environment#data: ParserError"
|
65
|
+
logger.metric "JSONParserError"
|
66
|
+
nil
|
69
67
|
end
|
70
68
|
end
|
71
69
|
end
|
@@ -12,25 +12,25 @@ module Alephant
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def content_type
|
15
|
-
headers[
|
15
|
+
headers["Content-Type"]
|
16
16
|
end
|
17
17
|
|
18
18
|
def headers
|
19
19
|
{
|
20
|
-
|
20
|
+
"Content-Type" => "text/plain"
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def content_for(exception)
|
27
|
-
|
27
|
+
exception.message.to_s.tap do |msg|
|
28
28
|
msg << "\n#{exception.backtrace.join('\n')}" if debug?
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
def debug?
|
33
|
-
Broker.config.fetch(
|
33
|
+
Broker.config.fetch("debug", false)
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require "alephant/broker/cache"
|
2
|
+
require "alephant/broker/errors/content_not_found"
|
3
|
+
require "alephant/logger"
|
4
|
+
require "faraday"
|
5
5
|
|
6
6
|
module Alephant
|
7
7
|
module Broker
|
@@ -41,20 +41,20 @@ module Alephant
|
|
41
41
|
def content(component_meta)
|
42
42
|
resp = request component_meta
|
43
43
|
{
|
44
|
-
:content
|
44
|
+
:content => resp.body,
|
45
45
|
:content_type => extract_content_type_from(resp.env.response_headers)
|
46
46
|
}
|
47
47
|
end
|
48
48
|
|
49
49
|
def extract_content_type_from(headers)
|
50
|
-
headers[
|
50
|
+
headers["content-type"].split(";").first
|
51
51
|
end
|
52
52
|
|
53
53
|
def request(component_meta)
|
54
54
|
before = Time.new
|
55
55
|
component_meta.cached = false
|
56
56
|
|
57
|
-
Faraday.get(url_for
|
57
|
+
Faraday.get(url_for(component_meta)).tap do |r|
|
58
58
|
unless r.success?
|
59
59
|
logger.metric "ContentNotFound"
|
60
60
|
raise Alephant::Broker::Errors::ContentNotFound
|
@@ -62,9 +62,8 @@ module Alephant
|
|
62
62
|
|
63
63
|
request_time = Time.new - before
|
64
64
|
logger.metric("LoadComponentTime",
|
65
|
-
|
66
|
-
|
67
|
-
)
|
65
|
+
:unit => "Seconds",
|
66
|
+
:value => request_time)
|
68
67
|
end
|
69
68
|
end
|
70
69
|
|
@@ -33,7 +33,7 @@ module Alephant
|
|
33
33
|
|
34
34
|
protected
|
35
35
|
|
36
|
-
def headers(
|
36
|
+
def headers(_component_meta)
|
37
37
|
Hash.new
|
38
38
|
end
|
39
39
|
|
@@ -43,8 +43,8 @@ module Alephant
|
|
43
43
|
|
44
44
|
private
|
45
45
|
|
46
|
-
def s3_path(
|
47
|
-
|
46
|
+
def s3_path(_component_meta)
|
47
|
+
raise NotImplementedError
|
48
48
|
end
|
49
49
|
|
50
50
|
def add_s3_headers(component_data, component_meta)
|
@@ -85,10 +85,10 @@ module Alephant
|
|
85
85
|
)
|
86
86
|
end
|
87
87
|
|
88
|
-
def headers(
|
88
|
+
def headers(_component_meta)
|
89
89
|
{
|
90
|
-
|
91
|
-
|
90
|
+
"X-Cache-Version" => Broker.config["elasticache_cache_version"].to_s,
|
91
|
+
"X-Cached" => cached.to_s
|
92
92
|
}
|
93
93
|
end
|
94
94
|
end
|
@@ -15,16 +15,13 @@ module Alephant
|
|
15
15
|
component_meta.options,
|
16
16
|
sequence(component_meta)
|
17
17
|
).tap do |obj|
|
18
|
-
|
18
|
+
raise InvalidCacheKey if obj.location.nil?
|
19
19
|
end.location unless sequence(component_meta).nil?
|
20
20
|
end
|
21
21
|
|
22
22
|
def sequencer
|
23
23
|
@sequencer ||= Alephant::Sequencer.create(
|
24
|
-
Broker.config[:sequencer_table_name],
|
25
|
-
{
|
26
|
-
:config => Broker.config
|
27
|
-
}
|
24
|
+
Broker.config[:sequencer_table_name], :config => Broker.config
|
28
25
|
)
|
29
26
|
end
|
30
27
|
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Alephant
|
2
2
|
module Broker
|
3
3
|
module Request
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
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
8
|
|
9
9
|
class NotFound; end
|
10
10
|
class Status; end
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "alephant/logger"
|
2
|
+
require "alephant/broker/errors/invalid_asset_id"
|
3
3
|
|
4
4
|
module Alephant
|
5
5
|
module Broker
|
@@ -24,10 +24,9 @@ module Alephant
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def component_id(path)
|
27
|
-
path.split(
|
27
|
+
path.split("/")[2] || (raise InvalidAssetId.new "No Asset ID specified")
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
|
-
|
@@ -10,11 +10,11 @@ module Alephant
|
|
10
10
|
attr_reader :batch_id, :components, :load_strategy
|
11
11
|
|
12
12
|
def initialize(component_factory, env)
|
13
|
-
if env.data
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
13
|
+
@batch_id = if env.data
|
14
|
+
env.data["batch_id"]
|
15
|
+
else
|
16
|
+
env.options.fetch("batch_id", nil)
|
17
|
+
end
|
18
18
|
|
19
19
|
logger.info "Request::Batch#initialize: id: #{batch_id}"
|
20
20
|
|
@@ -45,4 +45,3 @@ module Alephant
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
@@ -1,10 +1,8 @@
|
|
1
|
-
require
|
1
|
+
require "alephant/logger"
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'alephant/broker/response/factory'
|
7
|
-
require 'alephant/broker/errors/content_not_found'
|
3
|
+
require "alephant/broker/request"
|
4
|
+
require "alephant/broker/response"
|
5
|
+
require "alephant/broker/errors/content_not_found"
|
8
6
|
|
9
7
|
module Alephant
|
10
8
|
module Broker
|
@@ -27,4 +25,3 @@ module Alephant
|
|
27
25
|
end
|
28
26
|
end
|
29
27
|
end
|
30
|
-
|
@@ -1,23 +1,28 @@
|
|
1
1
|
module Alephant
|
2
2
|
module Broker
|
3
3
|
module Response
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
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
8
|
|
9
9
|
class NotFound < Base
|
10
|
-
def initialize
|
10
|
+
def initialize
|
11
|
+
super(404)
|
12
|
+
end
|
11
13
|
end
|
12
14
|
|
13
15
|
class Status < Base
|
14
|
-
def initialize
|
16
|
+
def initialize
|
17
|
+
super(200)
|
18
|
+
end
|
15
19
|
end
|
16
20
|
|
17
21
|
class ServerError < Base
|
18
|
-
def initialize
|
22
|
+
def initialize
|
23
|
+
super(500)
|
24
|
+
end
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|
22
28
|
end
|
23
|
-
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require
|
1
|
+
require "alephant/logger"
|
2
2
|
|
3
3
|
module Alephant
|
4
4
|
module Broker
|
@@ -17,14 +17,14 @@ module Alephant
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def setup
|
20
|
-
@content
|
20
|
+
@content = @component.content
|
21
21
|
log if @component.is_a? Component
|
22
22
|
end
|
23
23
|
|
24
24
|
private
|
25
25
|
|
26
26
|
def batched
|
27
|
-
@component.batch_id.nil? ?
|
27
|
+
@component.batch_id.nil? ? "" : "batched"
|
28
28
|
end
|
29
29
|
|
30
30
|
def details
|
@@ -40,4 +40,3 @@ module Alephant
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
@@ -19,20 +19,20 @@ module Alephant
|
|
19
19
|
NOT_MODIFIED_STATUS_CODE => "",
|
20
20
|
404 => "Not found",
|
21
21
|
500 => "Error retrieving content"
|
22
|
-
}
|
22
|
+
}.freeze
|
23
23
|
|
24
24
|
def initialize(status = 200, content_type = "text/html", request_env = nil)
|
25
25
|
@content = STATUS_CODE_MAPPING[status]
|
26
26
|
@headers = {
|
27
|
-
"Content-Type"
|
28
|
-
"Access-Control-Allow-Headers"
|
29
|
-
"Access-Control-Allow-Origin"
|
27
|
+
"Content-Type" => content_type,
|
28
|
+
"Access-Control-Allow-Headers" => "If-None-Match, If-Modified-Since",
|
29
|
+
"Access-Control-Allow-Origin" => "*"
|
30
30
|
}
|
31
|
-
headers.merge!(Broker.config[:headers]) if Broker.config.
|
32
|
-
@status
|
31
|
+
headers.merge!(Broker.config[:headers]) if Broker.config.key?(:headers)
|
32
|
+
@status = status
|
33
33
|
|
34
34
|
add_no_cache_headers if should_add_no_cache_headers?(status)
|
35
|
-
add_etag_allow_header if headers.
|
35
|
+
add_etag_allow_header if headers.key?("ETag")
|
36
36
|
setup if status == 200
|
37
37
|
|
38
38
|
@content = "" if self.class.options?(request_env)
|
@@ -58,9 +58,7 @@ module Alephant
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def add_etag_allow_header
|
61
|
-
headers.merge!(
|
62
|
-
"Access-Control-Expose-Headers" => "ETag"
|
63
|
-
})
|
61
|
+
headers.merge!("Access-Control-Expose-Headers" => "ETag")
|
64
62
|
end
|
65
63
|
|
66
64
|
def self.options?(request_env)
|
@@ -74,13 +72,13 @@ module Alephant
|
|
74
72
|
|
75
73
|
last_modified_match = !request_env.if_modified_since.nil? && headers["Last-Modified"] == request_env.if_modified_since
|
76
74
|
etag_match = !request_env.if_none_match.nil? &&
|
77
|
-
|
75
|
+
unquote_etag(headers["ETag"]) == unquote_etag(request_env.if_none_match)
|
78
76
|
|
79
77
|
last_modified_match || etag_match
|
80
78
|
end
|
81
79
|
|
82
80
|
def self.unquote_etag(etag)
|
83
|
-
etag.to_s.gsub(/\A"|"\Z/,
|
81
|
+
etag.to_s.gsub(/\A"|"\Z/, "")
|
84
82
|
end
|
85
83
|
|
86
84
|
def self.allow_not_modified_response_status
|
@@ -90,7 +88,6 @@ module Alephant
|
|
90
88
|
def log
|
91
89
|
logger.metric "BrokerNon200Response#{status}"
|
92
90
|
end
|
93
|
-
|
94
91
|
end
|
95
92
|
end
|
96
93
|
end
|
@@ -20,10 +20,8 @@ module Alephant
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def setup
|
23
|
-
@content = ::JSON.generate(
|
24
|
-
|
25
|
-
'components' => json
|
26
|
-
})
|
23
|
+
@content = ::JSON.generate("batch_id" => batch_id,
|
24
|
+
"components" => json)
|
27
25
|
end
|
28
26
|
|
29
27
|
private
|
@@ -37,11 +35,13 @@ module Alephant
|
|
37
35
|
"status" => component.status,
|
38
36
|
"content_type" => component.content_type,
|
39
37
|
"body" => component.content
|
40
|
-
}
|
41
|
-
|
38
|
+
}.tap do |headers|
|
39
|
+
headers["sequence_id"] = component.headers["X-Sequence"] if component.headers["X-Sequence"]
|
40
|
+
end
|
41
|
+
end.tap do
|
42
42
|
logger.info "Broker: Batch load done (#{batch_id})"
|
43
43
|
logger.metric "BrokerBatchLoadCount"
|
44
|
-
|
44
|
+
end
|
45
45
|
end
|
46
46
|
|
47
47
|
def batch_response_headers
|
@@ -62,7 +62,7 @@ module Alephant
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def batch_response_last_modified
|
65
|
-
last_modifieds
|
65
|
+
last_modifieds = components.map do |component|
|
66
66
|
component.headers["Last-Modified"]
|
67
67
|
end.compact
|
68
68
|
|
@@ -1,11 +1,11 @@
|
|
1
|
-
|
1
|
+
require "spec_helper"
|
2
2
|
|
3
3
|
describe Alephant::Broker::ComponentMeta do
|
4
4
|
let(:id) { "foo" }
|
5
5
|
let(:batch_id) { "bar" }
|
6
6
|
let(:options) do
|
7
7
|
{
|
8
|
-
|
8
|
+
"variant" => "K03000001"
|
9
9
|
}
|
10
10
|
end
|
11
11
|
subject { described_class.new(id, batch_id, options) }
|
@@ -5,19 +5,19 @@ describe Alephant::Broker::LoadStrategy::HTTP do
|
|
5
5
|
|
6
6
|
let(:component_meta) do
|
7
7
|
double(
|
8
|
-
|
9
|
-
cache_key
|
10
|
-
id
|
11
|
-
options
|
8
|
+
"Alephant::Broker::ComponentMeta",
|
9
|
+
:cache_key => "cache_key",
|
10
|
+
:id => "test",
|
11
|
+
:options => {}
|
12
12
|
)
|
13
13
|
end
|
14
|
-
let(:url_generator) { double(generate
|
15
|
-
let(:cache) { double(
|
16
|
-
let(:body) {
|
14
|
+
let(:url_generator) { double(:generate => "http://foo.bar") }
|
15
|
+
let(:cache) { double("Alephant::Broker::Cache::Client") }
|
16
|
+
let(:body) { "<h1>Batman!</h1>" }
|
17
17
|
let(:content) do
|
18
18
|
{
|
19
|
-
:content
|
20
|
-
:content_type =>
|
19
|
+
:content => body,
|
20
|
+
:content_type => "text/html"
|
21
21
|
}
|
22
22
|
end
|
23
23
|
|
@@ -32,7 +32,7 @@ describe Alephant::Broker::LoadStrategy::HTTP do
|
|
32
32
|
end
|
33
33
|
|
34
34
|
it "gets from cache" do
|
35
|
-
expect(subject.load
|
35
|
+
expect(subject.load(component_meta)).to eq content
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -43,21 +43,22 @@ describe Alephant::Broker::LoadStrategy::HTTP do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
context "and available over HTTP" do
|
46
|
-
let(:env) { double(
|
47
|
-
let(:response_headers) { {
|
46
|
+
let(:env) { double("env", :response_headers => response_headers) }
|
47
|
+
let(:response_headers) { { "content-type" => "text/html; test" } }
|
48
48
|
|
49
49
|
before :each do
|
50
50
|
allow(Faraday).to receive(:get) do
|
51
51
|
instance_double(
|
52
|
-
|
53
|
-
body
|
52
|
+
"Faraday::Response",
|
53
|
+
:body => body,
|
54
54
|
:'success?' => true,
|
55
|
-
env
|
55
|
+
:env => env
|
56
|
+
)
|
56
57
|
end
|
57
|
-
|
58
|
+
end
|
58
59
|
|
59
60
|
it "gets from HTTP" do
|
60
|
-
|
61
|
+
expect(subject.load(component_meta)).to eq content
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
@@ -76,7 +77,7 @@ describe Alephant::Broker::LoadStrategy::HTTP do
|
|
76
77
|
context "and HTTP request 404s" do
|
77
78
|
before :each do
|
78
79
|
allow(Faraday).to receive(:get) do
|
79
|
-
instance_double(
|
80
|
+
instance_double("Faraday::Response", :body => body, :'success?' => false)
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
@@ -8,7 +8,7 @@ describe Alephant::Broker::LoadStrategy::S3::Archived do
|
|
8
8
|
let(:component_meta) { double(:id => id) }
|
9
9
|
|
10
10
|
specify do
|
11
|
-
expect(subject.s3_path
|
11
|
+
expect(subject.s3_path(component_meta)).to eq id
|
12
12
|
end
|
13
13
|
|
14
14
|
context "no location associated with component meta" do
|
@@ -1 +1 @@
|
|
1
|
-
{"batch_id":"baz","components":[{"component":"ni_council_results_table","options":{"foo":"bar"},"status":200,"content_type":"test/content","body":"Test"},{"component":"ni_council_results_table","options":{},"status":200,"content_type":"test/content","body":"Test"}]}
|
1
|
+
{"batch_id":"baz","components":[{"component":"ni_council_results_table","options":{"foo":"bar"},"status":200,"content_type":"test/content","body":"Test","sequence_id":"111"},{"component":"ni_council_results_table","options":{},"status":200,"content_type":"test/content","body":"Test","sequence_id":"111"}]}
|
@@ -65,9 +65,7 @@ describe Alephant::Broker::Application do
|
|
65
65
|
get(
|
66
66
|
"/component/test_component",
|
67
67
|
{},
|
68
|
-
|
69
|
-
"HTTP_IF_MODIFIED_SINCE" => "Mon, 11 Apr 2016 10:39:57 GMT"
|
70
|
-
}
|
68
|
+
"HTTP_IF_MODIFIED_SINCE" => "Mon, 11 Apr 2016 10:39:57 GMT"
|
71
69
|
)
|
72
70
|
end
|
73
71
|
|
@@ -123,7 +121,7 @@ describe Alephant::Broker::Application do
|
|
123
121
|
|
124
122
|
before do
|
125
123
|
post(path, batch_json,
|
126
|
-
"CONTENT_TYPE"
|
124
|
+
"CONTENT_TYPE" => content_type,
|
127
125
|
"HTTP_IF_NONE_MATCH" => etag)
|
128
126
|
end
|
129
127
|
|
@@ -196,10 +194,8 @@ describe Alephant::Broker::Application do
|
|
196
194
|
get(
|
197
195
|
path,
|
198
196
|
{},
|
199
|
-
|
200
|
-
|
201
|
-
"HTTP_IF_NONE_MATCH" => etag
|
202
|
-
}
|
197
|
+
"CONTENT_TYPE" => content_type,
|
198
|
+
"HTTP_IF_NONE_MATCH" => etag
|
203
199
|
)
|
204
200
|
end
|
205
201
|
|
@@ -123,11 +123,11 @@ describe Alephant::Broker::Application do
|
|
123
123
|
end
|
124
124
|
|
125
125
|
context "for invalid URL parameters in request" do
|
126
|
-
before
|
126
|
+
before do
|
127
127
|
content[:meta]["status"] = 404
|
128
128
|
allow(Alephant::Storage).to receive(:new) { s3_double }
|
129
129
|
options "/component/invalid_component"
|
130
|
-
|
130
|
+
end
|
131
131
|
specify { expect(last_response.status).to eq 404 }
|
132
132
|
specify { expect(last_response.body).to eq "" }
|
133
133
|
specify { expect(last_response.headers["Content-Type"]).to eq("test/content") }
|
@@ -173,7 +173,7 @@ describe Alephant::Broker::Application do
|
|
173
173
|
describe "response should have headers" do
|
174
174
|
it "should have content headers" do
|
175
175
|
expect(last_response.headers["Content-Type"]).to eq("application/json")
|
176
|
-
expect(last_response.headers["Content-Length"]).to eq("
|
176
|
+
expect(last_response.headers["Content-Length"]).to eq("306")
|
177
177
|
end
|
178
178
|
|
179
179
|
it "should have ETag cache header" do
|
@@ -222,7 +222,7 @@ describe Alephant::Broker::Application do
|
|
222
222
|
describe "response should have headers" do
|
223
223
|
it "should have content headers" do
|
224
224
|
expect(last_response.headers["Content-Type"]).to eq("application/json")
|
225
|
-
expect(last_response.headers["Content-Length"]).to eq("
|
225
|
+
expect(last_response.headers["Content-Length"]).to eq("306")
|
226
226
|
end
|
227
227
|
|
228
228
|
it "should have ETag cache header" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,17 +1,18 @@
|
|
1
|
-
|
1
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), "..", "lib")
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'json'
|
5
|
-
require 'alephant/broker'
|
6
|
-
require 'alephant/broker/load_strategy/s3/sequenced'
|
7
|
-
require 'alephant/broker/load_strategy/s3/archived'
|
8
|
-
require "alephant/broker/load_strategy/http"
|
9
|
-
require "alephant/broker/cache"
|
10
|
-
require "alephant/broker/errors/content_not_found"
|
3
|
+
require "simplecov"
|
11
4
|
|
5
|
+
SimpleCov.start do
|
6
|
+
add_filter "/spec/"
|
7
|
+
end
|
8
|
+
|
9
|
+
require "pry"
|
10
|
+
require "json"
|
12
11
|
require "rack/test"
|
13
12
|
|
14
|
-
|
13
|
+
require "alephant/broker"
|
14
|
+
|
15
|
+
ENV["RACK_ENV"] = "test"
|
15
16
|
|
16
17
|
RSpec.configure do |config|
|
17
18
|
config.order = "random"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alephant-broker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.
|
4
|
+
version: 3.14.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BBC News
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,6 +164,20 @@ dependencies:
|
|
164
164
|
- - '>='
|
165
165
|
- !ruby/object:Gem::Version
|
166
166
|
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
requirement: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - '>='
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0'
|
173
|
+
name: simplecov
|
174
|
+
prerelease: false
|
175
|
+
type: :development
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - '>='
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
167
181
|
- !ruby/object:Gem::Dependency
|
168
182
|
requirement: !ruby/object:Gem::Requirement
|
169
183
|
requirements:
|
@@ -293,15 +307,20 @@ files:
|
|
293
307
|
- Rakefile
|
294
308
|
- alephant-broker.gemspec
|
295
309
|
- lib/alephant/broker.rb
|
310
|
+
- lib/alephant/broker/application.rb
|
296
311
|
- lib/alephant/broker/cache.rb
|
312
|
+
- lib/alephant/broker/cache/client.rb
|
313
|
+
- lib/alephant/broker/cache/null_client.rb
|
297
314
|
- lib/alephant/broker/component.rb
|
298
315
|
- lib/alephant/broker/component_factory.rb
|
299
316
|
- lib/alephant/broker/component_meta.rb
|
300
317
|
- lib/alephant/broker/environment.rb
|
301
318
|
- lib/alephant/broker/error_component.rb
|
319
|
+
- lib/alephant/broker/errors.rb
|
302
320
|
- lib/alephant/broker/errors/content_not_found.rb
|
303
321
|
- lib/alephant/broker/errors/invalid_asset_id.rb
|
304
322
|
- lib/alephant/broker/errors/invalid_cache_key.rb
|
323
|
+
- lib/alephant/broker/load_strategy.rb
|
305
324
|
- lib/alephant/broker/load_strategy/http.rb
|
306
325
|
- lib/alephant/broker/load_strategy/s3/archived.rb
|
307
326
|
- lib/alephant/broker/load_strategy/s3/base.rb
|
@@ -317,11 +336,11 @@ files:
|
|
317
336
|
- lib/alephant/broker/response/batch.rb
|
318
337
|
- lib/alephant/broker/response/factory.rb
|
319
338
|
- lib/alephant/broker/version.rb
|
320
|
-
- spec/
|
321
|
-
- spec/
|
339
|
+
- spec/alephant/broker/component_meta_spec.rb
|
340
|
+
- spec/alephant/broker/load_strategy/http_spec.rb
|
341
|
+
- spec/alephant/broker/load_strategy/s3/archived_spec.rb
|
322
342
|
- spec/fixtures/json/batch.json
|
323
343
|
- spec/fixtures/json/batch_compiled.json
|
324
|
-
- spec/http_spec.rb
|
325
344
|
- spec/integration/not_modified_response_spec.rb
|
326
345
|
- spec/integration/rack_spec.rb
|
327
346
|
- spec/integration/spec_helper.rb
|
@@ -351,11 +370,11 @@ signing_key:
|
|
351
370
|
specification_version: 4
|
352
371
|
summary: Brokers requests for alephant components
|
353
372
|
test_files:
|
354
|
-
- spec/
|
355
|
-
- spec/
|
373
|
+
- spec/alephant/broker/component_meta_spec.rb
|
374
|
+
- spec/alephant/broker/load_strategy/http_spec.rb
|
375
|
+
- spec/alephant/broker/load_strategy/s3/archived_spec.rb
|
356
376
|
- spec/fixtures/json/batch.json
|
357
377
|
- spec/fixtures/json/batch_compiled.json
|
358
|
-
- spec/http_spec.rb
|
359
378
|
- spec/integration/not_modified_response_spec.rb
|
360
379
|
- spec/integration/rack_spec.rb
|
361
380
|
- spec/integration/spec_helper.rb
|