alephant-lookup 0.0.1 → 0.0.2
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/Rakefile +9 -1
- data/alephant-lookup.gemspec +4 -1
- data/lib/alephant/lookup.rb +1 -1
- data/lib/alephant/lookup/lookup.rb +9 -4
- data/lib/alephant/lookup/lookup_table.rb +106 -1
- data/lib/alephant/lookup/version.rb +1 -1
- data/spec/lookup_spec.rb +67 -9
- data/spec/spec_helper.rb +1 -0
- metadata +30 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9b8b849a5219c4332391e0d682b6fe6834e434fd
|
4
|
+
data.tar.gz: 2f213c0bb66d5e26e8c5a103aa5be1170582d788
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7511cf718a58673bfb35dff48513b4ed0e6363c47963311325eb96743a4b3a2eaf497567be7248ac166b903ef875b4853d59a5afaf955001e415a8121385e6bd
|
7
|
+
data.tar.gz: 7022d3d8731702584a4c6fda3ffce70826a501fddb33bec119b9f01351ff033af81c5ec8a68ef3bf4facee649d1a52375ab9499702065c3521a74efb596b9498
|
data/.gitignore
CHANGED
data/Rakefile
CHANGED
data/alephant-lookup.gemspec
CHANGED
@@ -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 =
|
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
|
data/lib/alephant/lookup.rb
CHANGED
@@ -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(
|
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
|
-
|
13
|
+
@lookup_table.location_for(@component_id, opts)
|
15
14
|
end
|
16
15
|
|
17
16
|
def write(opts, location)
|
18
|
-
|
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
|
-
|
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
|
data/spec/lookup_spec.rb
CHANGED
@@ -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
|
-
|
22
|
-
|
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
|
-
|
27
|
-
|
28
|
-
|
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
|
-
|
data/spec/spec_helper.rb
CHANGED
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.
|
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-
|
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
|