alephant-broker 0.1.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88c15819c22cfcde769e9b1b1406d9563ddd11f8
4
- data.tar.gz: f1ed322acae0dc5740f6a965e3d790e1fca99dfd
3
+ metadata.gz: 8b93740e5628e1841d3f296c5675304678cc0be7
4
+ data.tar.gz: 9412546f75f2f95a77c3b2cbfa3b53e98a296f9d
5
5
  SHA512:
6
- metadata.gz: c3360481c1f7707c893d55635660cf3a5c56894c71aba9d87d80e73c549338ed47b9cede9a36233dbe5f0459b8405d7dbd39824819b4f2d42fcfc06aba0448c8
7
- data.tar.gz: 2192c4157e16662cf51d26645d9cb0e9c1f859d487669926a87ab68bba3a78046de9eb49cc1cf8fa2dba60db5e579baf7c5e265b8cf2a3a5944119baa5913600
6
+ metadata.gz: 34c3356dc0bab54c046bf2d8c269a07ea08c60ebfa9077d9f3eadd46a3df6fb48e1dd01d0bab710022607228629f98b6a4b91448153ed125cc38340e7a6e3626
7
+ data.tar.gz: 9414facbf42866a0eba6e903ec71ba365f0f342c183edb13a8710125c9fba411b08067a6493551bd1fb8223c64f3a5ef58722404fcf796c7faed88fae2ed56bd
@@ -34,4 +34,5 @@ Gem::Specification.new do |spec|
34
34
  spec.add_runtime_dependency "alephant-lookup"
35
35
  spec.add_runtime_dependency "alephant-cache"
36
36
  spec.add_runtime_dependency 'alephant-logger'
37
+ spec.add_runtime_dependency 'alephant-sequencer'
37
38
  end
@@ -1,3 +1,5 @@
1
+ require 'json'
2
+
1
3
  module Alephant
2
4
  module Broker
3
5
  class CallEnvironment
@@ -9,23 +11,27 @@ module Alephant
9
11
  end
10
12
 
11
13
  def method
12
- @settings['REQUEST_METHOD']
14
+ settings['REQUEST_METHOD']
13
15
  end
14
16
 
15
17
  def post?
16
- @settings['REQUEST_METHOD'] == 'POST'
18
+ settings['REQUEST_METHOD'] == 'POST'
17
19
  end
18
20
 
19
21
  def get?
20
- @settings['REQUEST_METHOD'] == 'GET'
22
+ settings['REQUEST_METHOD'] == 'GET'
21
23
  end
22
24
 
23
25
  def query
24
- @settings['QUERY_STRING']
26
+ settings['QUERY_STRING']
25
27
  end
26
28
 
27
29
  def path
28
- @settings['PATH_INFO']
30
+ settings['PATH_INFO']
31
+ end
32
+
33
+ def request_type
34
+ path.split('/')[1]
29
35
  end
30
36
 
31
37
  def data
@@ -35,7 +41,7 @@ module Alephant
35
41
  private
36
42
 
37
43
  def rack_input
38
- (@settings['rack.input'].read).tap { @settings['rack.input'].rewind } # http://rack.rubyforge.org/doc/SPEC.html
44
+ (settings['rack.input'].read).tap { settings['rack.input'].rewind } # http://rack.rubyforge.org/doc/SPEC.html
39
45
  end
40
46
 
41
47
  def parse(json)
@@ -3,16 +3,16 @@ require 'alephant/broker/models/request'
3
3
  module Alephant
4
4
  module Broker
5
5
  class PostRequest < Request
6
- attr_reader :type, :component_id, :options, :content_type
6
+ attr_reader :type, :renderer_id, :component_id, :options, :content_type
7
7
 
8
8
  def initialize
9
- @env = RequestStore.store[:env]
9
+ @renderer_id = batch_id
10
10
  @content_type = 'application/json'
11
11
  super(:batch)
12
12
  end
13
13
 
14
14
  def components
15
- @requested_components ||= components_for @env.path
15
+ @requested_components ||= components_for env.path
16
16
  end
17
17
 
18
18
  def set_component(id, options)
@@ -22,6 +22,10 @@ module Alephant
22
22
 
23
23
  private
24
24
 
25
+ def env
26
+ @env ||= RequestStore.store[:env]
27
+ end
28
+
25
29
  def components_for(path)
26
30
  request_parts = path.split('/')
27
31
 
@@ -33,11 +37,11 @@ module Alephant
33
37
  end
34
38
 
35
39
  def batch_id
36
- @env.data['batch_id']
40
+ env.data['batch_id']
37
41
  end
38
42
 
39
43
  def batched
40
- @env.data['components'].reduce({ :components => [] }) do |obj, component|
44
+ env.data['components'].reduce({ :components => [] }) do |obj, component|
41
45
  obj.tap { |o| o[:components].push(component) }
42
46
  end
43
47
  end
@@ -7,24 +7,30 @@ module Alephant
7
7
  include Logger
8
8
 
9
9
  def initialize(config)
10
- @env = RequestStore.store[:env]
11
- @request = RequestFactory.process(request_type)
12
- @response_factory = ResponseFactory.new(config)
10
+ @config = config
13
11
  end
14
12
 
15
13
  def process
16
14
  begin
17
- @response_factory.response_from(@request)
15
+ response_factory.response_from(request)
18
16
  rescue Exception => e
19
17
  logger.info("Broker.requestHandler.process: Exception raised (#{e.message})")
20
- @response_factory.response(500)
18
+ response_factory.response(500)
21
19
  end
22
20
  end
23
21
 
24
22
  private
25
23
 
24
+ def request
25
+ @request ||= RequestFactory.process(request_type)
26
+ end
27
+
28
+ def response_factory
29
+ @response_factory ||= ResponseFactory.new(@config)
30
+ end
31
+
26
32
  def request_type
27
- case @env.path.split('/')[1]
33
+ case env.request_type
28
34
  when 'components'
29
35
  component_type
30
36
  when 'status'
@@ -35,13 +41,17 @@ module Alephant
35
41
  end
36
42
 
37
43
  def component_type
38
- case @env.method
44
+ case env.method
39
45
  when 'POST'
40
46
  :component_batch
41
47
  when 'GET'
42
48
  :component
43
49
  end
44
50
  end
51
+
52
+ def env
53
+ @env ||= RequestStore.store[:env]
54
+ end
45
55
  end
46
56
  end
47
57
  end
@@ -22,7 +22,6 @@ module Alephant
22
22
  end
23
23
 
24
24
  def setup; end
25
-
26
25
  end
27
26
  end
28
27
  end
@@ -1,6 +1,8 @@
1
+ require 'crimp'
1
2
  require 'alephant/cache'
2
3
  require 'alephant/lookup'
3
4
  require 'alephant/broker/errors/invalid_cache_key'
5
+ require 'alephant/sequencer'
4
6
 
5
7
  module Alephant
6
8
  module Broker
@@ -11,15 +13,14 @@ module Alephant
11
13
 
12
14
  def initialize(request, config)
13
15
  @request = request
14
- @lookup = Alephant::Lookup.create(config[:lookup_table_name], request.component_id)
15
- @cache = Cache.new(config[:bucket_id], config[:path])
16
+ @config = config
16
17
  super()
17
18
  end
18
19
 
19
20
  def setup
20
21
  begin
21
22
  self.content_type = request.content_type
22
- self.content = @cache.get cache_id
23
+ self.content = cache.get(s3_path)
23
24
  rescue AWS::S3::Errors::NoSuchKey, InvalidCacheKey => e
24
25
  set_error_for(e, 404)
25
26
  rescue Exception => e
@@ -29,14 +30,66 @@ module Alephant
29
30
 
30
31
  private
31
32
 
33
+ def cache
34
+ @cache ||= Alephant::Cache.new(config[:bucket_id], config[:path])
35
+ end
36
+
32
37
  def set_error_for(exception, status)
33
38
  logger.info("Broker.assetResponse.set_error_for: #{status} exception raised (#{exception.message})")
34
39
  self.status = status
35
40
  self.content = exception.message
36
41
  end
37
42
 
38
- def cache_id
39
- @lookup.read(request.options).tap { |cache_id| raise InvalidCacheKey if cache_id.nil? }
43
+ def s3_path
44
+ lookup.read(id, request.options, version).tap { |cache_id| raise InvalidCacheKey if cache_id.nil? }
45
+ end
46
+
47
+ def lookup
48
+ @lookup ||= Alephant::Lookup.create(config[:lookup_table_name])
49
+ end
50
+
51
+ def asset?
52
+ request.type == :asset
53
+ end
54
+
55
+ def key
56
+ asset? ? component_key : renderer_key
57
+ end
58
+
59
+ def component_key
60
+ "#{component_id}/#{opts_hash}"
61
+ end
62
+
63
+ def renderer_key
64
+ "#{renderer_id}/#{opts_hash}"
65
+ end
66
+
67
+ def id
68
+ asset? ? component_id : renderer_id
69
+ end
70
+
71
+ def component_id
72
+ request.component_id
73
+ end
74
+
75
+ def renderer_id
76
+ request.renderer_id
77
+ end
78
+
79
+ def opts_hash
80
+ @opts_hash ||= Crimp.signature(request.options)
81
+ end
82
+
83
+ def version
84
+ @version ||= sequencer.get_last_seen
85
+ end
86
+
87
+ def sequencer
88
+ @sequencer ||= Alephant::Sequencer.create(config[:sequencer_table_name], key)
89
+ end
90
+
91
+ def config
92
+ @config
40
93
  end
41
94
  end
42
95
  end
@@ -13,9 +13,9 @@ module Alephant
13
13
  def response_from(request)
14
14
  case request.type
15
15
  when :asset
16
- AssetResponse.new(request, @config)
16
+ AssetResponse.new(request, config)
17
17
  when :batch
18
- BatchResponse.new(request, @config).process
18
+ BatchResponse.new(request, config).process
19
19
  when :status
20
20
  response(200)
21
21
  when :notfound
@@ -25,6 +25,12 @@ module Alephant
25
25
  end
26
26
  end
27
27
 
28
+ private
29
+
30
+ def config
31
+ @config
32
+ end
33
+
28
34
  def response(status)
29
35
  Response.new(status)
30
36
  end
@@ -1,5 +1,5 @@
1
1
  module Alephant
2
2
  module Broker
3
- VERSION = "0.1.0"
3
+ VERSION = "0.1.1"
4
4
  end
5
5
  end
@@ -1,73 +1,75 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Alephant::Broker::AssetResponse do
4
+ subject { Alephant::Broker::AssetResponse }
5
+
4
6
  describe "#initialize(request, config)" do
5
7
  let(:location) { 'test_location' }
8
+
6
9
  let(:config) {{
7
10
  :lookup_table_name => 'test_table',
8
11
  :bucket_id => 'test_bucket',
9
12
  :path => 'test_path'
10
13
  }}
14
+
11
15
  let(:request) { double(
12
16
  "Alephant::Broker::Request",
13
17
  :component_id => 'test',
14
18
  :content_type => 'text/html',
19
+ :type => :asset,
15
20
  :options => { :variant => 'test_variant' }
16
21
  )
17
22
  }
18
23
 
19
24
  before do
20
- @lookup_table = double('Alephant::Lookup::LookupTable')
21
- Alephant::Lookup.stub(:create).and_return(@lookup_table)
22
- end
23
-
24
- it "Should return the content from a successful cache lookup" do
25
- allow(@lookup_table)
26
- .to receive(:read)
27
- .with(request.options)
28
- .and_return(location)
29
-
30
- Alephant::Cache
31
- .any_instance
32
- .stub(:initialize)
33
-
34
- Alephant::Cache
25
+ subject
35
26
  .any_instance
36
- .stub(:get)
37
- .with(location)
38
- .and_return('Test cache content')
39
-
40
- instance = Alephant::Broker::AssetResponse.new(request, config)
41
-
42
- expect(instance.content).to eq('Test cache content')
43
- expect(instance.status).to eq(200)
27
+ .stub(:s3_path)
28
+ .and_return(:foo)
44
29
  end
45
30
 
46
- it "should return a 404 if lookup can't find a valid location" do
47
- allow(@lookup_table)
48
- .to receive(:read)
49
- .with(request.options)
50
- .and_return(nil)
31
+ context "successful" do
32
+ before(:each) do
33
+ subject
34
+ .any_instance
35
+ .stub(:cache)
36
+ .and_return(double(:get => 'Test'))
37
+ end
51
38
 
52
- Alephant::Cache
53
- .any_instance
54
- .stub(:initialize)
39
+ it "Should return the content from a successful cache lookup" do
40
+ instance = subject.new(request, config)
55
41
 
56
- instance = Alephant::Broker::AssetResponse.new(request, config)
57
-
58
- expect(instance.content).to eq('Cache key not found based on component_id and options combination')
59
- expect(instance.status).to eq(404)
42
+ expect(instance.content).to eq('Test')
43
+ expect(instance.status).to eq(200)
44
+ end
60
45
  end
61
46
 
62
- it "should return a 500 for any other exceptions" do
63
- allow(@lookup_table)
64
- .to receive(:read)
65
- .with(request.options)
66
- .and_raise(Exception)
67
-
68
- instance = Alephant::Broker::AssetResponse.new(request, config)
47
+ context "client failure" do
48
+ before(:each) do
49
+ subject
50
+ .any_instance
51
+ .stub(:cache)
52
+ .and_raise(Alephant::Broker::InvalidCacheKey)
53
+ end
54
+
55
+ it "should return a 404 if lookup can't find a valid location" do
56
+ instance = subject.new(request, config)
57
+ expect(instance.status).to eq(404)
58
+ end
59
+ end
69
60
 
70
- expect(instance.status).to eq(500)
61
+ context "server failure" do
62
+ before(:each) do
63
+ subject
64
+ .any_instance
65
+ .stub(:cache)
66
+ .and_raise(Exception)
67
+ end
68
+
69
+ it "should return a 500 for any other exceptions" do
70
+ instance = subject.new(request, config)
71
+ expect(instance.status).to eq(500)
72
+ end
71
73
  end
72
74
  end
73
75
  end
@@ -1,6 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Alephant::Broker::BatchResponse do
4
+ subject { Alephant::Broker::BatchResponse }
5
+
4
6
  let (:config) {{
5
7
  :lookup_table_name => 'test_table',
6
8
  :bucket_id => 'test_bucket',
@@ -15,6 +17,7 @@ describe Alephant::Broker::BatchResponse do
15
17
  :content_type => 'application/json',
16
18
  :set_component => nil,
17
19
  :component_id => nil,
20
+ :renderer_id => nil,
18
21
  :components => {
19
22
  :batch_id => :baz,
20
23
  :components => [
@@ -25,31 +28,20 @@ describe Alephant::Broker::BatchResponse do
25
28
  }
26
29
 
27
30
  before do
28
- @lookup_table = double('Alephant::Lookup::LookupTable', :read => 'test_location')
29
-
30
- Alephant::Lookup
31
- .stub(:create)
32
- .and_return(@lookup_table)
33
-
34
- Alephant::Cache
31
+ Alephant::Broker::AssetResponse
35
32
  .any_instance
36
33
  .stub(:initialize)
37
-
38
- Alephant::Cache
39
- .any_instance
40
- .stub(:get)
41
- .and_return('Test response')
42
34
  end
43
35
 
44
36
  describe "#process" do
45
37
  context "if a component is unrecognised" do
46
38
  before(:each) do
47
- Alephant::Cache
39
+ Alephant::Broker::AssetResponse
48
40
  .any_instance
49
- .stub(:get)
50
- .and_raise(Alephant::Broker::InvalidCacheKey)
41
+ .stub(:status)
42
+ .and_return(404)
51
43
 
52
- instance = Alephant::Broker::BatchResponse.new(post_request, config)
44
+ instance = subject.new(post_request, config)
53
45
  json = JSON.parse(instance.process.content)
54
46
  @bad_component = json.fetch('components')[1]
55
47
  end
@@ -65,7 +57,17 @@ describe Alephant::Broker::BatchResponse do
65
57
 
66
58
  context "if a component is recognised" do
67
59
  before(:each) do
68
- @instance = Alephant::Broker::BatchResponse.new(post_request, config)
60
+ Alephant::Broker::AssetResponse
61
+ .any_instance
62
+ .stub(:status)
63
+ .and_return(200)
64
+
65
+ Alephant::Broker::AssetResponse
66
+ .any_instance
67
+ .stub(:content)
68
+ .and_return('Test')
69
+
70
+ @instance = subject.new(post_request, config)
69
71
  @content = @instance.process.content
70
72
  @json = JSON.parse(@content)
71
73
  end
@@ -77,7 +79,7 @@ describe Alephant::Broker::BatchResponse do
77
79
  end
78
80
 
79
81
  it "set @content to be JSON string containing retrieved components" do
80
- compiled_json = '{"batch_id":"baz","components":[{"component":"foo1","options":{"variant":"bar1"},"status":200,"body":"Test response"},{"component":"foo2","options":{"variant":"bar2"},"status":200,"body":"Test response"}]}'
82
+ compiled_json = '{"batch_id":"baz","components":[{"component":"foo1","options":{"variant":"bar1"},"status":200,"body":"Test"},{"component":"foo2","options":{"variant":"bar2"},"status":200,"body":"Test"}]}'
81
83
  expect(@content).to eq(compiled_json)
82
84
  end
83
85
  end
data/spec/rack_spec.rb CHANGED
@@ -12,11 +12,19 @@ describe 'Broker Rack Application' do
12
12
  before do
13
13
  RequestStore.store[:env] = nil
14
14
 
15
- @lookup_table = double('Alephant::Lookup::LookupTable')
16
- Alephant::Lookup.stub(:create).and_return(@lookup_table)
17
-
18
- Alephant::Cache.any_instance.stub(:initialize)
19
- Alephant::Cache.any_instance.stub(:get).and_return('Test response')
15
+ Alephant::Broker::AssetResponse
16
+ .any_instance
17
+ .stub(:initialize)
18
+
19
+ Alephant::Broker::AssetResponse
20
+ .any_instance
21
+ .stub(:status)
22
+ .and_return(200)
23
+
24
+ Alephant::Broker::AssetResponse
25
+ .any_instance
26
+ .stub(:content)
27
+ .and_return('Test')
20
28
  end
21
29
 
22
30
  def app
@@ -40,41 +48,44 @@ describe 'Broker Rack Application' do
40
48
  end
41
49
 
42
50
  it "Test asset data is returned" do
43
- allow(@lookup_table).to receive(:read).and_return('some_location')
44
-
45
51
  get '/components/test_component'
52
+
46
53
  expect(last_response).to be_ok
47
- expect(last_response.body).to eq('Test response')
54
+ expect(last_response.body).to eq('Test')
48
55
  end
49
56
 
50
57
  it "Tests query string parameters are passed correctly to lookup" do
51
- variant = {:variant => 'test_variant'}
52
- allow(@lookup_table).to receive(:read).with(variant).and_return('some_location')
53
-
54
58
  get '/components/test_component?variant=test_variant'
59
+
55
60
  expect(last_response).to be_ok
56
- expect(last_response.body).to eq('Test response')
61
+ expect(last_response.body).to eq('Test')
57
62
  end
58
63
 
59
64
  it "Tests 404 when lookup doesn't return a valid location" do
60
- allow(@lookup_table).to receive(:read).and_return(nil)
65
+ Alephant::Broker::AssetResponse
66
+ .any_instance
67
+ .stub(:status)
68
+ .and_return(404)
61
69
 
62
70
  get '/components/test_component'
71
+
63
72
  expect(last_response.status).to eq(404)
64
73
  end
65
74
 
66
75
  it "Tests 500 when exception is raised in application" do
67
- allow(@lookup_table).to receive(:read).and_raise(Exception)
76
+ Alephant::Broker::AssetResponse
77
+ .any_instance
78
+ .stub(:status)
79
+ .and_return(500)
68
80
 
69
81
  get '/components/test_component'
82
+
70
83
  expect(last_response.status).to eq(500)
71
84
  end
72
85
 
73
86
  it "Test batch asset data is returned" do
74
- allow(@lookup_table).to receive(:read).and_return('some_location')
75
-
76
87
  json = '{"batch_id":"baz","components":[{"component":"ni_council_results_table"},{"component":"ni_council_results_table"}]}'
77
- compiled_json = '{"batch_id":"baz","components":[{"component":"ni_council_results_table","status":200,"body":"Test response"},{"component":"ni_council_results_table","status":200,"body":"Test response"}]}'
88
+ compiled_json = '{"batch_id":"baz","components":[{"component":"ni_council_results_table","status":200,"body":"Test"},{"component":"ni_council_results_table","status":200,"body":"Test"}]}'
78
89
 
79
90
  post '/components/batch', json, "CONTENT_TYPE" => "application/json"
80
91
 
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
2
 
3
3
  require 'pry'
4
+ require 'json'
4
5
  require 'alephant/broker'
5
6
  require 'request_store'
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: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Jack
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-14 00:00:00.000000000 Z
11
+ date: 2014-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -206,6 +206,20 @@ dependencies:
206
206
  version: '0'
207
207
  prerelease: false
208
208
  type: :runtime
209
+ - !ruby/object:Gem::Dependency
210
+ name: alephant-sequencer
211
+ version_requirements: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - '>='
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ requirement: !ruby/object:Gem::Requirement
217
+ requirements:
218
+ - - '>='
219
+ - !ruby/object:Gem::Version
220
+ version: '0'
221
+ prerelease: false
222
+ type: :runtime
209
223
  description: Brokers requests for alephant components
210
224
  email:
211
225
  - stevenmajack@gmail.com