alephant-lookup 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2de5b13682fc9400af295b28c3aacbc41f2c1203
4
- data.tar.gz: ea8aac19dd9a080ffcc84dc4f81b8ade317a0dc5
3
+ metadata.gz: 9b8b849a5219c4332391e0d682b6fe6834e434fd
4
+ data.tar.gz: 2f213c0bb66d5e26e8c5a103aa5be1170582d788
5
5
  SHA512:
6
- metadata.gz: f8a73612df87c017cb80d98f9ff8769aff507fc8f7f832d397179b763cb9a621c6edd16e63b7ed77b1553a827a08449a91076dfeeb40de161130d23ec90e3c64
7
- data.tar.gz: 76be4d525cf258d70d0192917df0353a5a53801b5ffe933c93dd671ab434e2e834916b8136f1c691597b604f2a2fa4977d51c5946298886c5881a1ea328784e4
6
+ metadata.gz: 7511cf718a58673bfb35dff48513b4ed0e6363c47963311325eb96743a4b3a2eaf497567be7248ac166b903ef875b4853d59a5afaf955001e415a8121385e6bd
7
+ data.tar.gz: 7022d3d8731702584a4c6fda3ffce70826a501fddb33bec119b9f01351ff033af81c5ec8a68ef3bf4facee649d1a52375ab9499702065c3521a74efb596b9498
data/.gitignore CHANGED
@@ -8,3 +8,4 @@ Gemfile.lock
8
8
  /tmp
9
9
  /components
10
10
 
11
+ *.swp
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
- require "bundler/gem_tasks"
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+
3
+ require 'rspec/core/rake_task'
4
+ require 'bundler/gem_tasks'
5
+ require 'alephant/lookup'
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ task :default => :spec
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Alephant::Lookup::VERSION
9
9
  spec.authors = ["Robert Kenny"]
10
10
  spec.email = ["kenoir@gmail.com"]
11
- spec.summary = %q{Lookup a location in S3 using DynamoDB.}
11
+ spec.summary = "Lookup a location in S3 using DynamoDB."
12
12
  spec.homepage = "https://github.com/BBC-News/alephant-lookup"
13
13
  spec.license = "MIT"
14
14
 
@@ -27,4 +27,7 @@ Gem::Specification.new do |spec|
27
27
 
28
28
  spec.add_development_dependency "bundler", "~> 1.5"
29
29
  spec.add_development_dependency "rake"
30
+
31
+ spec.add_runtime_dependency 'aws-sdk', '~> 1.0'
32
+ spec.add_runtime_dependency "crimp"
30
33
  end
@@ -7,7 +7,7 @@ module Alephant
7
7
  @@lookup_tables = {}
8
8
 
9
9
  def self.create(table_name, component_id)
10
- @@lookup_tables[table_name] ||= LookupTable.new('table_name')
10
+ @@lookup_tables[table_name] ||= LookupTable.new(table_name)
11
11
  Lookup.new(@@lookup_tables[table_name], component_id)
12
12
  end
13
13
  end
@@ -6,16 +6,21 @@ module Alephant
6
6
  def initialize(lookup_table, component_id)
7
7
  @lookup_table = lookup_table
8
8
  @component_id = component_id
9
-
10
- @lookup_table.create
9
+ create_lookup_table
11
10
  end
12
11
 
13
12
  def read(opts)
14
- fail
13
+ @lookup_table.location_for(@component_id, opts)
15
14
  end
16
15
 
17
16
  def write(opts, location)
18
- fail
17
+ @lookup_table.write_location_for(@component_id, opts, location)
18
+ end
19
+
20
+ private
21
+
22
+ def create_lookup_table
23
+ @lookup_table.create
19
24
  end
20
25
 
21
26
  end
@@ -1,12 +1,117 @@
1
+ require 'aws-sdk'
2
+ require 'thread'
3
+ require 'timeout'
4
+ require 'crimp'
5
+
1
6
  module Alephant
2
7
  module Lookup
3
8
  class LookupTable
4
- def initialize(table_name)
9
+ attr_reader :table_name
10
+
11
+ TIMEOUT = 120
12
+ DEFAULT_CONFIG = {
13
+ :write_units => 5,
14
+ :read_units => 10
15
+ }
16
+ SCHEMA = {
17
+ :hash_key => {
18
+ :id => :string
19
+ },
20
+ :range_key => {
21
+ :location => :string
22
+ }
23
+ }
24
+
25
+ S3_LOCATION_FIELD = 's3_location'
5
26
 
27
+ def initialize(table_name, config = DEFAULT_CONFIG)
28
+ @mutex = Mutex.new
29
+ @dynamo_db = AWS::DynamoDB.new
30
+ @client = AWS::DynamoDB::Client::V20120810.new
31
+ @table_name = table_name
32
+ @config = config
6
33
  end
7
34
 
8
35
  def create
36
+ @mutex.synchronize do
37
+ ensure_table_exists
38
+ ensure_table_active
39
+ end
40
+ end
41
+
42
+ def table
43
+ @table ||= @dynamo_db.tables[@table_name]
44
+ end
45
+
46
+
47
+ def location_for(component_id, opts)
48
+ result = @client.query({
49
+ :table_name => @table_name,
50
+ :consistent_read => true,
51
+ :select => 'SPECIFIC_ATTRIBUTES',
52
+ :attributes_to_get => [S3_LOCATION_FIELD],
53
+ :key_conditions => {
54
+ 'component_id' => {
55
+ :comparison_operator => 'EQ',
56
+ :attribute_value_list => [
57
+ { 's' => component_id.to_s }
58
+ ],
59
+ },
60
+ 'opts_hash' => {
61
+ :comparison_operator => 'EQ',
62
+ :attribute_value_list => [
63
+ { 's' => hash_for(opts) }
64
+ ]
65
+ }
66
+ }
67
+ })
68
+ result[:count] == 1 ? result[:member].first[S3_LOCATION_FIELD][:s] : nil
69
+ end
70
+
71
+ def write_location_for(component_id, opts, location)
72
+
73
+ @table.batch_put([
74
+ {
75
+ :component_id => component_id,
76
+ :opts_hash => hash_for(opts),
77
+ :s3_location => location
78
+ }
79
+ ])
80
+ end
81
+
82
+ private
83
+
84
+ def hash_for(opts)
85
+ Crimp.signature opts
86
+ end
87
+
88
+ def ensure_table_exists
89
+ create_dynamodb_table unless table.exists?
90
+ end
91
+
92
+ def ensure_table_active
93
+ sleep_until_table_active unless table_active?
94
+ end
95
+
96
+ def create_dynamodb_table
97
+ @table = @dynamo_db.tables.create(
98
+ @table_name,
99
+ @config[:read_units],
100
+ @config[:write_units],
101
+ SCHEMA
102
+ )
103
+ end
104
+
105
+ def table_active?
106
+ table.status == :active
107
+ end
9
108
 
109
+ def sleep_until_table_active
110
+ begin
111
+ Timeout::timeout(TIMEOUT) do
112
+ sleep 1 until table_active?
113
+ end
114
+ end
10
115
  end
11
116
  end
12
117
  end
@@ -1,5 +1,5 @@
1
1
  module Alephant
2
2
  module Lookup
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
@@ -3,32 +3,90 @@ require 'spec_helper'
3
3
  describe Alephant::Lookup do
4
4
  describe '.create(table_name, component_id)' do
5
5
  it 'returns a lookup' do
6
+ Alephant::Lookup::Lookup
7
+ .any_instance
8
+ .stub(:initialize)
9
+ .and_return(double())
10
+
6
11
  expect(subject.create(:table_name, :component_id)).to be_a Alephant::Lookup::Lookup
7
12
  end
8
13
  end
9
14
 
10
15
  describe Alephant::Lookup::Lookup do
16
+ subject { Alephant::Lookup::Lookup }
17
+
11
18
  describe '#initialize(table_name)' do
12
19
  it 'calls create on lookup_table' do
13
20
  table = double()
14
21
  table.should_receive(:create)
15
-
16
- Alephant::Lookup::Lookup.new(table, :component_id)
22
+ subject.new(table, :component_id)
17
23
  end
18
24
  end
19
25
 
20
26
  describe '#read(opts)' do
21
- it 'returns lookup_table.location_for(component_id, opts_hash)' do
22
- fail
27
+ let (:lookup_table) { Alephant::Lookup::LookupTable }
28
+ let (:s3_location) { '/s3-render-example/test/html/england_council_election_results/responsive' }
29
+
30
+ it 'returns lookup_table.location_for(component_id, opts)' do
31
+ subject
32
+ .any_instance
33
+ .stub(:create_lookup_table)
34
+
35
+ lookup_table
36
+ .any_instance
37
+ .stub(:initialize)
38
+
39
+ lookup_table
40
+ .any_instance
41
+ .stub(:location_for)
42
+ .and_return(s3_location)
43
+
44
+ pal_opts = {
45
+ :id => :england_council_election_results,
46
+ :env => :test,
47
+ :type => :responsive
48
+ }
49
+
50
+ instance = subject.new(lookup_table.new, pal_opts[:id])
51
+ read_location = instance.read(pal_opts)
52
+
53
+ expect(read_location).to eq(s3_location)
23
54
  end
24
55
  end
25
56
 
26
- describe '#write(opts, location)' do
27
- it 'calls lookup_table.location_for(component_id, opts_hash, data)' do
28
- fail
57
+ describe '#write(opts, location)' do
58
+
59
+ let (:lookup_table) { Alephant::Lookup::LookupTable }
60
+ let (:s3_location) { '/s3-render-example/test/html/england_council_election_results/responsive' }
61
+
62
+ it 'returns lookup_table.update_location_for(component_id, opts_hash, data)' do
63
+
64
+ subject
65
+ .any_instance
66
+ .stub(:create_lookup_table)
67
+
68
+ lookup_table
69
+ .any_instance
70
+ .stub(:initialize)
71
+
72
+ pal_opts = {
73
+ :id => :england_council_election_results,
74
+ :env => :test,
75
+ :type => :responsive
76
+ }
77
+
78
+ lookup_table
79
+ .any_instance
80
+ .stub(:write_location_for)
81
+ .with(pal_opts[:id], pal_opts, :s3_location)
82
+ .and_return(nil)
83
+
84
+ instance = subject.new(lookup_table.new, pal_opts[:id])
85
+ write_return = instance.write(pal_opts, :s3_location)
86
+
87
+ expect(write_return).to eq(nil)
88
+
29
89
  end
30
90
  end
31
-
32
91
  end
33
92
  end
34
-
@@ -2,4 +2,5 @@ $: << File.join(File.dirname(__FILE__),"..", "lib")
2
2
 
3
3
  require 'pry'
4
4
  require 'alephant/lookup'
5
+ require 'crimp'
5
6
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alephant-lookup
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Kenny
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-13 00:00:00.000000000 Z
11
+ date: 2014-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -136,6 +136,34 @@ dependencies:
136
136
  version: '0'
137
137
  prerelease: false
138
138
  type: :development
139
+ - !ruby/object:Gem::Dependency
140
+ name: aws-sdk
141
+ version_requirements: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ~>
144
+ - !ruby/object:Gem::Version
145
+ version: '1.0'
146
+ requirement: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ~>
149
+ - !ruby/object:Gem::Version
150
+ version: '1.0'
151
+ prerelease: false
152
+ type: :runtime
153
+ - !ruby/object:Gem::Dependency
154
+ name: crimp
155
+ version_requirements: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ requirement: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - '>='
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ prerelease: false
166
+ type: :runtime
139
167
  description:
140
168
  email:
141
169
  - kenoir@gmail.com