alephant-broker 3.13.0 → 3.14.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|