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 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