dynamo-record 1.4.1 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dynamo/record/version.rb +1 -1
  3. data/{Gemfile → spec/gemfiles/rails-5.2.gemfile} +3 -1
  4. data/spec/gemfiles/rails-6.0.gemfile +7 -0
  5. data/spec/gemfiles/rails-6.1.gemfile +7 -0
  6. data/spec/internal/app/models/model1.rb +9 -0
  7. data/spec/internal/app/models/model2.rb +9 -0
  8. data/spec/internal/config/database.yml +3 -0
  9. data/spec/internal/db/dynamo_migrate/20170402163638_create_model_1.rb +13 -0
  10. data/spec/internal/db/dynamo_migrate/20170402163639_create_model_2.rb +9 -0
  11. data/spec/internal/db/invalid_dynamo_migrate/add_model_1_stream.rb +9 -0
  12. data/spec/lib/dynamo/record/batch_get_spec.rb +85 -0
  13. data/spec/lib/dynamo/record/batch_write_spec.rb +90 -0
  14. data/spec/lib/dynamo/record/model_existence_vaildator_spec.rb +43 -0
  15. data/spec/lib/dynamo/record/model_spec.rb +120 -0
  16. data/spec/lib/dynamo/record/table_migration_spec.rb +68 -0
  17. data/spec/lib/dynamo/record/task_helpers/cleanup_spec.rb +28 -0
  18. data/spec/lib/dynamo/record/task_helpers/drop_all_tables_spec.rb +21 -0
  19. data/spec/lib/dynamo/record/task_helpers/drop_table_spec.rb +27 -0
  20. data/spec/lib/dynamo/record/task_helpers/list_tables_spec.rb +12 -0
  21. data/spec/lib/dynamo/record/task_helpers/migration_runner_spec.rb +54 -0
  22. data/spec/lib/dynamo/record/task_helpers/scale_spec.rb +64 -0
  23. data/spec/lib/dynamo/record/version_spec.rb +7 -0
  24. data/spec/spec_helper.rb +38 -0
  25. data/spec/support/shared_contexts/with_dummy_model.rb +28 -0
  26. metadata +52 -30
  27. data/.dockerignore +0 -17
  28. data/.gitignore +0 -16
  29. data/.rspec +0 -2
  30. data/.rubocop.yml +0 -61
  31. data/.travis.yml +0 -28
  32. data/Dockerfile +0 -24
  33. data/Jenkinsfile +0 -45
  34. data/LICENSE.txt +0 -21
  35. data/docker-compose.override.example.yml +0 -19
  36. data/docker-compose.yml +0 -20
  37. data/dynamo-record.gemspec +0 -55
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6857b86e979ddf3e3d53a3139fa678eadef1d0bf5ab241075ac20f5d4206b194
4
- data.tar.gz: f9e86c87793994a47fb1000710b857d51927e772de7104d2042dcf7043d59a38
3
+ metadata.gz: 193614a73977889190f759bb367f89d72ea36965a093488dc2203be83f28e37e
4
+ data.tar.gz: cc792d8f2d367b0fd14b7af1578d6f0a3f249b589fd8e7e880d9f40e9715b383
5
5
  SHA512:
6
- metadata.gz: 4e81ce3a97bfee043a9bff671d195eb5095a12020b1f32407dd6f3f1fcd2dcfde0d83ff458b5395925d30406e39bac1b4dbce653e1ae216e357f8934b04884d3
7
- data.tar.gz: fc921695c59df2a111685f7be35cc412af95c4c9429ef149b12b0518f4db2d65593415ac8835f7998f06064fe3b4294b16d0abadd8d204738b3f11278671fa69
6
+ metadata.gz: 9d2e98eeafd27be2c4e00e861515cd03c222de15a8eff4196377113d7791fa311b873b389037c8834cd039ab3df3590ff1e6bbdcf9c99ba09f8f567c8040acc4
7
+ data.tar.gz: 8250e400b5c6a63dd0d33daedf9f5d1bba2ba8f5fdba1326543075dbc2c90a91bf4c7530a1edea2b4112ee2c8f56bba8c33e115efdc6d94177c11833a784245b
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Dynamo
4
4
  module Record
5
- VERSION = '1.4.1'
5
+ VERSION = '1.4.2'
6
6
  end
7
7
  end
@@ -2,4 +2,6 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gemspec
5
+ gemspec path: '../../'
6
+
7
+ gem 'rails', '~> 5.2.0'
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec path: '../../'
6
+
7
+ gem 'rails', '~> 6.0.0'
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec path: '../../'
6
+
7
+ gem 'rails', '~> 6.1.0'
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Model1
4
+ include Dynamo::Record::Model
5
+ composite_string_attr(
6
+ :model1_key,
7
+ hash_key: true
8
+ )
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Model2
4
+ include Dynamo::Record::Model
5
+ composite_string_attr(
6
+ :model2_key,
7
+ hash_key: true
8
+ )
9
+ end
@@ -0,0 +1,3 @@
1
+ test:
2
+ adapter: sqlite3
3
+ database: db/combustion_test.sqlite
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamoMigrate
4
+ class CreateModel1 < Dynamo::Record::TableMigration
5
+ def self.table_config
6
+ Aws::Record::TableConfig.define do |config|
7
+ config.model_class Model1
8
+ config.read_capacity_units 1
9
+ config.write_capacity_units 1
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamoMigrate
4
+ class CreateModel2 < Dynamo::Record::TableMigration
5
+ def self.up
6
+ migrate(Model2, &:create!)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamoMigrate
4
+ class AddModel1Stream < Dynamo::Record::TableMigration
5
+ def self.update
6
+ add_stream(Model1)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::BatchGet do
4
+ include_context 'with dummy model'
5
+
6
+ table_name = DynamoDummyModel.table_name
7
+
8
+ let(:records) { (1..5).map { |id| DynamoDummyModel.new(id: id, name: (64 + id).chr) } }
9
+ let(:keys) { (1..5).map { |id| { id: id } } }
10
+
11
+ before(:each) do
12
+ DynamoDummyModel.batch_save!(records)
13
+ expect(DynamoDummyModel.scan.count).to eq 5
14
+ end
15
+
16
+ # Overrides sleep everywhere to speed up specs.
17
+ before { allow_any_instance_of(Object).to receive(:sleep) }
18
+
19
+ it 'gets all at once' do
20
+ result = DynamoDummyModel.batch_get(keys)
21
+ expect(result.map(&:name).sort).to eq %w[A B C D E]
22
+ end
23
+
24
+ it 'handles empty array' do
25
+ result = DynamoDummyModel.batch_get([])
26
+ expect(result.count).to eq 0
27
+ end
28
+
29
+ it 'gets all items if item queue is larger than possible in one batch get' do
30
+ stub_const('Dynamo::Record::BatchGet::BATCH_SIZE', 3)
31
+ result = DynamoDummyModel.batch_get(keys)
32
+ expect(result.map(&:name).sort).to eq %w[A B C D E]
33
+ end
34
+
35
+ it 'raises when attempts are unsuccessful' do
36
+ allow(DynamoDummyModel).to receive(:max_retries).and_return(1)
37
+ dynamodb_client_stub = double
38
+ allow(DynamoDummyModel).to receive(:dynamodb_client).and_return(dynamodb_client_stub)
39
+ expect(dynamodb_client_stub).to receive(:batch_get_item) do |opts|
40
+ items = opts[:request_items][table_name][:keys]
41
+ Aws::DynamoDB::Types::BatchGetItemOutput.new(
42
+ responses: { table_name => [] },
43
+ unprocessed_keys: { table_name => Aws::DynamoDB::Types::KeysAndAttributes.new(keys: items) }
44
+ )
45
+ end
46
+ expect do
47
+ DynamoDummyModel.batch_get(keys)
48
+ end.to raise_error(Dynamo::Record::BatchGet::NumberOfRetriesExceeded)
49
+ end
50
+
51
+ it 'reprocesses unprocessed items' do
52
+ dynamodb_client_stub = double
53
+ original_batch_get_item = DynamoDummyModel.dynamodb_client.method(:batch_get_item)
54
+ allow(DynamoDummyModel).to receive(:dynamodb_client).and_return(dynamodb_client_stub)
55
+ expect(dynamodb_client_stub).to receive(:batch_get_item) do |opts|
56
+ # Pick two successful items, return the remaining keys
57
+ items = opts[:request_items][table_name][:keys]
58
+ success = items.sample(2)
59
+ response = original_batch_get_item.call(opts)
60
+ pr, = response.responses[table_name].partition { |r| success.map { |i| i['id'] }.include? r['id'] }
61
+ unpr = items - success
62
+ Aws::DynamoDB::Types::BatchGetItemOutput.new(
63
+ responses: { table_name => pr },
64
+ unprocessed_keys: { table_name => Aws::DynamoDB::Types::KeysAndAttributes.new(keys: unpr) }
65
+ )
66
+ end.exactly(3).times
67
+ result = DynamoDummyModel.batch_get(keys)
68
+ expect(result.map(&:name).sort).to eq %w[A B C D E]
69
+ end
70
+
71
+ it 'retries if provisioned throughput is exceeded' do
72
+ stub_const('Dynamo::Record::BatchGet::BATCH_SIZE', 3)
73
+ call_count = 0
74
+ original_batch_get_item = DynamoDummyModel.dynamodb_client.method(:batch_get_item)
75
+ expect(DynamoDummyModel.dynamodb_client).to receive(:batch_get_item) do |opts|
76
+ call_count += 1
77
+ raise Aws::DynamoDB::Errors::ProvisionedThroughputExceededException.new(nil, nil) if call_count == 1
78
+
79
+ original_batch_get_item.call(opts)
80
+ end.exactly(3).times
81
+
82
+ result = DynamoDummyModel.batch_get(keys)
83
+ expect(result.map(&:name).sort).to eq %w[A B C D E]
84
+ end
85
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::BatchWrite do
4
+ include_context 'with dummy model'
5
+
6
+ shared_examples_for 'a batch write' do |method|
7
+ # Overrides sleep everywhere to speed up specs.
8
+ before { allow_any_instance_of(Object).to receive(:sleep) }
9
+
10
+ it 'writes all at once' do
11
+ DynamoDummyModel.send(method, records)
12
+ expect(DynamoDummyModel.scan.count).to eq expected_count
13
+ end
14
+
15
+ it 'handles empty array' do
16
+ DynamoDummyModel.send(method, [])
17
+ expect(DynamoDummyModel.scan.count).to eq num_records
18
+ end
19
+
20
+ it 'writes all items if item queue is larger than possible in one batch write' do
21
+ stub_const('Dynamo::Record::BatchWrite::BATCH_SIZE', 3)
22
+ DynamoDummyModel.send(method, records)
23
+ expect(DynamoDummyModel.scan.count).to eq expected_count
24
+ end
25
+
26
+ it 'writes all items if payload size would be exceeded in a single write' do
27
+ stub_const('Dynamo::Record::BatchWrite::MAX_PAYLOAD_SIZE', 50)
28
+ records = (1..5).map { |id| DynamoDummyModel.new(id: id) }
29
+ DynamoDummyModel.send(method, records)
30
+ expect(DynamoDummyModel.scan.count).to eq expected_count
31
+ end
32
+
33
+ it 'reprocesses unprocessed items' do
34
+ records = [DynamoDummyModel.new(id: 1)]
35
+ dynamodb_client_stub = double
36
+ expect(DynamoDummyModel).to receive(:max_retries).and_return(1).exactly(2).times
37
+ expect(DynamoDummyModel).to receive(:dynamodb_client).and_return(dynamodb_client_stub).exactly(2).times
38
+ allow(dynamodb_client_stub).to receive(:batch_write_item) do |opts|
39
+ items = opts[:request_items][DynamoDummyModel.table_name].map { |ri| Aws::DynamoDB::Types::WriteRequest.new ri }
40
+ double(unprocessed_items: { DynamoDummyModel.table_name => items })
41
+ end
42
+ expect do
43
+ DynamoDummyModel.send(method, records)
44
+ end.to raise_error(Dynamo::Record::BatchWrite::NumberOfRetriesExceeded)
45
+ end
46
+
47
+ it 'fails if a record is too large' do
48
+ stub_const('Dynamo::Record::BatchRequest::MAX_RECORD_SIZE', 5)
49
+ expect do
50
+ DynamoDummyModel.send(method, records)
51
+ end.to raise_error(Dynamo::Record::RecordTooLargeError)
52
+ end
53
+
54
+ it 'retries if provisioned throughput is exceeded' do
55
+ stub_const('Dynamo::Record::BatchWrite::BATCH_SIZE', 3)
56
+ call_count = 0
57
+ original_batch_write_item = DynamoDummyModel.dynamodb_client.method(:batch_write_item)
58
+ expect(DynamoDummyModel.dynamodb_client).to receive(:batch_write_item) do |opts|
59
+ call_count += 1
60
+ raise Aws::DynamoDB::Errors::ProvisionedThroughputExceededException.new(nil, nil) if call_count == 1
61
+
62
+ original_batch_write_item.call(opts)
63
+ end.exactly(3).times
64
+
65
+ DynamoDummyModel.send(method, records)
66
+ expect(DynamoDummyModel.scan.count).to eq expected_count
67
+ end
68
+ end
69
+
70
+ describe '.batch_save!' do
71
+ let(:records) { (1..5).map { |id| DynamoDummyModel.new(id: id) } }
72
+ let(:expected_count) { 5 }
73
+ let(:num_records) { 0 }
74
+
75
+ it_behaves_like 'a batch write', :batch_save!
76
+ end
77
+
78
+ describe '.batch_delete!' do
79
+ let(:records) { (1..5).map { |id| DynamoDummyModel.new(id: id) } }
80
+ let(:expected_count) { 0 }
81
+ let(:num_records) { 5 }
82
+
83
+ before(:each) do
84
+ DynamoDummyModel.batch_save!(records)
85
+ expect(DynamoDummyModel.scan.count).to eq 5
86
+ end
87
+
88
+ it_behaves_like 'a batch write', :batch_delete!
89
+ end
90
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::ModelExistenceValidator do
4
+ class TestModel
5
+ def self.exists?(id)
6
+ id == 1
7
+ end
8
+ end
9
+
10
+ describe '#validate_each' do
11
+ before(:each) do
12
+ validator.validate_each(record, :test_model_id, value)
13
+ end
14
+
15
+ let(:record) do
16
+ Class.new do
17
+ attr_accessor :errors
18
+
19
+ def initialize
20
+ @errors = { test_model_id: [] }
21
+ end
22
+ end.new
23
+ end
24
+
25
+ let(:validator) { described_class.new(attributes: [:test_model_id], model: TestModel) }
26
+
27
+ context 'valid record' do
28
+ let(:value) { 1 }
29
+
30
+ it 'has no errors' do
31
+ expect(record.errors[:test_model_id]).to be_empty
32
+ end
33
+ end
34
+
35
+ context 'invalid record' do
36
+ let(:value) { 2 }
37
+
38
+ it 'has errors' do
39
+ expect(record.errors[:test_model_id]).not_to be_empty
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::Model do
4
+ class TestDynamoModel
5
+ include Dynamo::Record::Model
6
+
7
+ integer_attr :test_id_1, hash_key: true
8
+ integer_attr :test_id_2, range_key: true
9
+ integer_attr :test_id_3
10
+ composite_integer_attr(
11
+ :test_id_4,
12
+ parts: %i[test_id_4_1 test_id_4_2]
13
+ )
14
+
15
+ global_secondary_index(
16
+ :gsi_1,
17
+ hash_key: :test_id_3,
18
+ range_key: :test_id_2,
19
+ projection: {
20
+ projection_type: 'ALL'
21
+ }
22
+ )
23
+
24
+ local_secondary_index(
25
+ :lsi_1,
26
+ range_key: :test_id_3,
27
+ projection: {
28
+ projection_type: 'ALL'
29
+ }
30
+ )
31
+ end
32
+
33
+ describe '.table_name' do
34
+ it 'should have correct table name' do
35
+ expect(TestDynamoModel.table_name).to eq 'test-test_dynamo_models'
36
+ end
37
+ end
38
+
39
+ context 'composite keys' do
40
+ before do
41
+ @d_1 = 'data_1'
42
+ @d_2 = 'data_2'
43
+ @key = TestDynamoModel.composite_key(@d_1, @d_2)
44
+ end
45
+
46
+ describe '.split_composite' do
47
+ it 'returns the input from composite_key' do
48
+ r_1, r_2 = TestDynamoModel.split_composite(@key)
49
+ expect(r_1).to eq @d_1
50
+ expect(r_2).to eq @d_2
51
+ end
52
+ end
53
+
54
+ describe '.composite_key' do
55
+ it 'returns the composite key' do
56
+ expect(@key).to eq "#{@d_1}|#{@d_2}"
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '.find' do
62
+ it 'raises Aws::Record::Errors::NotFound if no record matches' do
63
+ resp = Aws::DynamoDB::Types::GetItemOutput.new
64
+ expect(TestDynamoModel.dynamodb_client).to receive(:get_item).once.and_return(resp)
65
+ expect { TestDynamoModel.find(test_id_1: 'omg', test_id_2: 'pls') }.to raise_error(Aws::Record::Errors::NotFound)
66
+ end
67
+ end
68
+
69
+ context 'find queries' do
70
+ before do
71
+ expect(TestDynamoModel).to receive(:query).once
72
+ end
73
+
74
+ describe '.find_all_by_hash_key' do
75
+ it 'queries by hash key' do
76
+ TestDynamoModel.find_all_by_hash_key(1)
77
+ end
78
+ end
79
+
80
+ describe '.find_all_by_gsi_hash_key' do
81
+ it 'queries the gsi' do
82
+ TestDynamoModel.find_all_by_gsi_hash_key('gsi_1', 1)
83
+ end
84
+ end
85
+
86
+ describe '.find_all_by_gsi_hash_and_range_keys' do
87
+ it 'queries the gsi' do
88
+ TestDynamoModel.find_all_by_gsi_hash_and_range_keys('gsi_1', 1, 5)
89
+ end
90
+ end
91
+
92
+ describe '.find_all_by_lsi_hash_key' do
93
+ it 'queries the lsi' do
94
+ TestDynamoModel.find_all_by_lsi_hash_key('lsi_1', 1)
95
+ end
96
+ end
97
+
98
+ describe '.find_all_by_lsi_hash_and_range_keys' do
99
+ it 'queries the lsi' do
100
+ TestDynamoModel.find_all_by_lsi_hash_and_range_keys('lsi_1', 1, 3)
101
+ end
102
+ end
103
+
104
+ describe '.find_all_by_index_hash_and_range_keys' do
105
+ it 'can fetch item ranges' do
106
+ hash = { name: 'test_id_1', value: 2 }
107
+ range = { expression: 'test_id_2 > :rkv', value: 10 }
108
+ TestDynamoModel.find_all_by_index_hash_and_range_keys(hash_config: hash, range_config: range)
109
+ end
110
+ end
111
+ end
112
+
113
+ describe '#read_attribute_for_serialization' do
114
+ it 'generates an attribute hash' do
115
+ key = TestDynamoModel.composite_key(4, 5)
116
+ m = TestDynamoModel.new(test_id_1: 1, test_id_2: 2, test_id_3: 3, test_id_4: key)
117
+ expect(m.attribute_hash).to eq(test_id_1: 1, test_id_2: 2, test_id_3: 3, test_id_4: key)
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::TableMigration do
4
+ class TestDynamoTableMigration
5
+ include Aws::Record
6
+
7
+ integer_attr :test_id_1, hash_key: true
8
+ integer_attr :test_id_2, range_key: true
9
+ end
10
+
11
+ class CreateTestDynamoTableMigration < Dynamo::Record::TableMigration
12
+ def self.up
13
+ migrate(TestDynamoTableMigration) do |migration|
14
+ migration.create!(
15
+ provisioned_throughput: {
16
+ read_capacity_units: 1,
17
+ write_capacity_units: 1
18
+ }
19
+ )
20
+ end
21
+ end
22
+ end
23
+
24
+ let(:client) { double(describe_table: true) }
25
+
26
+ describe '.migrate' do
27
+ it 'returns `:migrated` if successful' do
28
+ expect_any_instance_of(Aws::Record::TableMigration).to receive(:client).and_return(client)
29
+ expect(client).to receive(:describe_table).and_raise(
30
+ Aws::DynamoDB::Errors::ResourceNotFoundException.new(nil, '')
31
+ )
32
+
33
+ expect_any_instance_of(Aws::Record::TableMigration).to receive(:create!).once
34
+ expect_any_instance_of(Aws::Record::TableMigration).to receive(:wait_until_available).once
35
+
36
+ expect(CreateTestDynamoTableMigration.up).to eq :migrated
37
+ end
38
+
39
+ it 'returns `:exists` if table already exists' do
40
+ expect_any_instance_of(Aws::Record::TableMigration).to receive(:client).and_return(client)
41
+
42
+ expect(CreateTestDynamoTableMigration.up).to eq :exists
43
+ end
44
+ end
45
+
46
+ describe '.add_stream' do
47
+ it 'raises an error if ValidationException raised' do
48
+ allow_any_instance_of(Aws::Record::TableMigration).to(
49
+ receive(:update!).and_raise(Aws::DynamoDB::Errors::ValidationException.new(nil, nil))
50
+ )
51
+ expect { CreateTestDynamoTableMigration.add_stream(TestDynamoTableMigration) }.to(
52
+ raise_error Aws::DynamoDB::Errors::ValidationException
53
+ )
54
+ end
55
+
56
+ it 'does not raise an excetion if stream already enabled' do
57
+ message = 'Table already has an enabled stream'
58
+ expect_any_instance_of(Aws::DynamoDB::Errors::ValidationException).to(
59
+ receive(:message).at_least(:once).and_return(message)
60
+ )
61
+ allow_any_instance_of(Aws::Record::TableMigration).to(
62
+ receive(:update!).and_raise(Aws::DynamoDB::Errors::ValidationException.new(nil, ''))
63
+ )
64
+ expect { CreateTestDynamoTableMigration.add_stream(TestDynamoTableMigration) }.to_not raise_error
65
+ expect(CreateTestDynamoTableMigration.add_stream(TestDynamoTableMigration)).to eq message
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::TaskHelpers::Cleanup do
4
+ describe '.run' do
5
+ it 'raises error if rails is in production' do
6
+ allow(Rails).to receive(:env).and_return(
7
+ ActiveSupport::StringInquirer.new('production')
8
+ )
9
+ expect do
10
+ Dynamo::Record::TaskHelpers::Cleanup.run
11
+ end.to raise_error('Task not available on production')
12
+ end
13
+
14
+ it 'deletes records in all DynamoDB tables' do
15
+ Dir[Rails.root.join('app/models/*.rb').to_s].each do |filename|
16
+ klass = File.basename(filename, '.rb').camelize.constantize
17
+ next unless klass.included_modules.include? Dynamo::Record::Model
18
+
19
+ object = double.as_null_object
20
+ list = [object]
21
+ expect(klass).to receive(:scan).and_return(list)
22
+ expect(object).to receive(:delete!)
23
+ end
24
+
25
+ described_class.run
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::TaskHelpers::DropAllTables do
4
+ describe '.run' do
5
+ it 'raises error if rails is in production' do
6
+ allow(Rails).to receive(:env).and_return(
7
+ ActiveSupport::StringInquirer.new('production')
8
+ )
9
+ expect do
10
+ Dynamo::Record::TaskHelpers::DropAllTables.run
11
+ end.to raise_error('Task not available on production')
12
+ end
13
+
14
+ it 'drops all dynamo tables' do
15
+ expect_any_instance_of(Aws::DynamoDB::Client).to receive(:list_tables)
16
+ .and_return double(table_names: %w[test_t1 test_t2 test_t3])
17
+ expect_any_instance_of(Aws::DynamoDB::Client).to receive(:delete_table).at_least(3).times
18
+ Dynamo::Record::TaskHelpers::DropAllTables.run
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::TaskHelpers::DropTable do
4
+ include_context 'with dummy model'
5
+
6
+ class BadDummyModel; end # rubocop:disable Lint/EmptyClass
7
+
8
+ describe '#run' do
9
+ it 'raises error if specified class does not include Aws::Record' do
10
+ expect do
11
+ Dynamo::Record::TaskHelpers::DropTable.run('BadDummyModel')
12
+ end.to raise_error('Cannot do operations on a non-existent table')
13
+ end
14
+
15
+ it 'drops dynamo table' do
16
+ dynamodb = Aws::DynamoDB::Client.new
17
+ table = dynamodb.describe_table(table_name: DynamoDummyModel.table_name)
18
+ expect(table).not_to be_empty
19
+
20
+ Dynamo::Record::TaskHelpers::DropTable.run DynamoDummyModel.table_name
21
+
22
+ expect do
23
+ dynamodb.describe_table(table_name: DynamoDummyModel.table_name)
24
+ end.to raise_error(Aws::DynamoDB::Errors::ResourceNotFoundException)
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::TaskHelpers::ListTables do
4
+ describe '#run' do
5
+ include_context 'with dummy model'
6
+ it 'lists all dynamo tables' do
7
+ list = Dynamo::Record::TaskHelpers::ListTables.run
8
+
9
+ expect(list).to include DynamoDummyModel.table_name
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::TaskHelpers::MigrationRunner do
4
+ describe '.run' do
5
+ it 'runs migration for each dynamo table' do
6
+ allow_any_instance_of(Aws::Record::TableMigration).to(
7
+ receive(:client).and_raise(
8
+ Aws::DynamoDB::Errors::ResourceNotFoundException.new(nil, '')
9
+ )
10
+ )
11
+
12
+ allow_any_instance_of(Aws::Record::TableMigration).to receive(:create!)
13
+ allow_any_instance_of(Aws::Record::TableConfig).to receive(:migrate!)
14
+ allow_any_instance_of(Aws::Record::TableMigration).to receive(:update!)
15
+ allow_any_instance_of(Aws::Record::TableMigration).to receive(:wait_until_available)
16
+ messages = []
17
+
18
+ Dynamo::Record::TaskHelpers::MigrationRunner.run do |thing|
19
+ messages << thing
20
+ end
21
+
22
+ switch = true
23
+ messages.each do |message|
24
+ expect(message).to include(switch ? 'Migrating:' : 'Migration successful')
25
+ switch = !switch
26
+ end
27
+ end
28
+
29
+ it 'displays failed migrations' do
30
+ allow_any_instance_of(Aws::Record::TableConfig).to(
31
+ receive(:migrate!).and_raise(
32
+ StandardError.new('')
33
+ )
34
+ )
35
+ messages = []
36
+
37
+ Dynamo::Record::TaskHelpers::MigrationRunner.run do |thing|
38
+ messages << thing
39
+ end
40
+
41
+ switch = true
42
+ messages.each do |message|
43
+ expect(message).to include(switch ? 'Migrating:' : 'Migration failed')
44
+ switch = !switch
45
+ end
46
+ end
47
+
48
+ it 'raises on non-numeric prefixes' do
49
+ expect do
50
+ Dynamo::Record::TaskHelpers::MigrationRunner.run('db/invalid_dynamo_migrate')
51
+ end.to raise_error(/Non-numeric prefix/)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record::TaskHelpers::Scale do
4
+ include_context 'with dummy model'
5
+
6
+ describe '.run' do
7
+ it 'changes both throughputs on the table' do
8
+ migration = Aws::Record::TableMigration.new(DynamoDummyModel)
9
+ current_settings = migration.client.describe_table(table_name: DynamoDummyModel.table_name).table
10
+
11
+ # configure unique throughput settings so ordering doesn't matter
12
+ new_throughput = current_settings.provisioned_throughput.read_capacity_units == 50 ? 49 : 50
13
+
14
+ # Run the scaling
15
+ scale = Dynamo::Record::TaskHelpers::Scale.new 'DynamoDummyModel', 'both', new_throughput
16
+ scale.run
17
+ throughput = migration.client.describe_table(table_name: DynamoDummyModel.table_name).table.provisioned_throughput
18
+ expect(throughput.read_capacity_units).to eq(new_throughput)
19
+ expect(throughput.write_capacity_units).to eq(new_throughput)
20
+ end
21
+
22
+ it 'changes the write throughput on the table' do
23
+ migration = Aws::Record::TableMigration.new(DynamoDummyModel)
24
+ current_settings = migration.client.describe_table(table_name: DynamoDummyModel.table_name).table
25
+
26
+ # configure unique throughput settings so ordering doesn't matter
27
+ new_write_throughput = current_settings.provisioned_throughput.write_capacity_units == 20 ? 19 : 20
28
+
29
+ # Run the scaling
30
+ scale = Dynamo::Record::TaskHelpers::Scale.new 'DynamoDummyModel', 'write', new_write_throughput
31
+ scale.run
32
+
33
+ throughput = migration.client.describe_table(table_name: DynamoDummyModel.table_name).table.provisioned_throughput
34
+ expect(throughput.write_capacity_units).to eq(new_write_throughput)
35
+ end
36
+
37
+ it 'changes the read throughput on the table' do
38
+ migration = Aws::Record::TableMigration.new(DynamoDummyModel)
39
+ current_settings = migration.client.describe_table(table_name: DynamoDummyModel.table_name).table
40
+
41
+ # configure unique throughput settings so ordering doesn't matter
42
+ new_read_throughput = current_settings.provisioned_throughput.read_capacity_units == 20 ? 19 : 20
43
+
44
+ # Run the scaling
45
+ scale = Dynamo::Record::TaskHelpers::Scale.new 'DynamoDummyModel', 'read', new_read_throughput
46
+ scale.run
47
+
48
+ throughput = migration.client.describe_table(table_name: DynamoDummyModel.table_name).table.provisioned_throughput
49
+ expect(throughput.read_capacity_units).to eq(new_read_throughput)
50
+ end
51
+
52
+ it 'prints description if any param is blank' do
53
+ message = Dynamo::Record::TaskHelpers::Scale.new('DynamoDummyModel', 'read', nil).run
54
+ expect(message).to include('Here\'s some usage information:')
55
+ end
56
+
57
+ it 'raises exception if attribute selection is invalid' do
58
+ scale = Dynamo::Record::TaskHelpers::Scale.new('DynamoDummyModel', 'invalid_selection', 20)
59
+ expect { scale.run }.to raise_error(
60
+ /provide an appropriate attribute selection/
61
+ )
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Dynamo::Record do
4
+ it 'has a version number' do
5
+ expect(Dynamo::Record::VERSION).not_to be nil
6
+ end
7
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Limit coverage reporting to one build:
4
+ if /^2\.6/ =~ RUBY_VERSION && /6\.0/ =~ ENV['BUNDLE_GEMFILE']
5
+ require 'simplecov'
6
+
7
+ SimpleCov.start do
8
+ add_filter 'lib/dynamo/record/version.rb'
9
+ add_filter 'spec'
10
+ track_files 'lib/**/*.rb'
11
+ end
12
+
13
+ SimpleCov.minimum_coverage(94)
14
+ end
15
+
16
+ require 'bundler'
17
+ Bundler.require :default, :development
18
+
19
+ Combustion.initialize! do
20
+ config.dynamo = { 'prefix' => 'test' }
21
+ end
22
+
23
+ Dir['./spec/support/**/*.rb'].sort.each { |f| require f }
24
+
25
+ RSpec.configure do |config|
26
+ # Enable flags like --only-failures and --next-failure
27
+ config.example_status_persistence_file_path = '.rspec_status'
28
+
29
+ config.expect_with :rspec do |c|
30
+ c.syntax = :expect
31
+ end
32
+ end
33
+
34
+ Aws.config.update(
35
+ dynamodb: { endpoint: ENV['DYNAMO_ENDPOINT'] }
36
+ )
37
+
38
+ WebMock.disable_net_connect!(allow: ['dynamo:8000'])
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.shared_context 'with dummy model' do
4
+ class DynamoDummyModel
5
+ include Aws::Record
6
+ include Dynamo::Record::Model
7
+
8
+ integer_attr :id, hash_key: true
9
+ string_attr :name
10
+ end
11
+
12
+ before do
13
+ migration = Aws::Record::TableMigration.new(DynamoDummyModel)
14
+ migration.create!(
15
+ provisioned_throughput: {
16
+ read_capacity_units: 1,
17
+ write_capacity_units: 1
18
+ }
19
+ )
20
+ end
21
+
22
+ after do
23
+ dynamodb = Aws::DynamoDB::Client.new
24
+ dynamodb.delete_table table_name: DynamoDummyModel.table_name
25
+ rescue Aws::DynamoDB::Errors::ResourceNotFoundException
26
+ # some tests will drop this table
27
+ end
28
+ end
metadata CHANGED
@@ -1,20 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamo-record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 1.4.2
5
5
  platform: ruby
6
6
  authors:
7
- - Davis McClellan
8
- - Ryan Taylor
9
- - Bryan Petty
10
- - Michael Brewer-Davis
11
- - Marc Phillips
12
- - Augusto Callejas
13
- - Frank Murphy
7
+ - Alex Slaughter
14
8
  autorequire:
15
9
  bindir: bin
16
10
  cert_chain: []
17
- date: 2022-01-03 00:00:00.000000000 Z
11
+ date: 2023-08-22 00:00:00.000000000 Z
18
12
  dependencies:
19
13
  - !ruby/object:Gem::Dependency
20
14
  name: activemodel
@@ -232,30 +226,12 @@ dependencies:
232
226
  version: '1.3'
233
227
  description:
234
228
  email:
235
- - dmcclellan@instructure.com
236
- - rtaylor@instructure.com
237
- - bpetty@instructure.com
238
- - mbd@instructure.com
239
- - mphillips@instructure.com
240
- - acallejas@instructure.com
241
- - fmurphy@instructure.com
229
+ - aslaughter@instructure.com
242
230
  executables: []
243
231
  extensions: []
244
232
  extra_rdoc_files: []
245
233
  files:
246
- - ".dockerignore"
247
- - ".gitignore"
248
- - ".rspec"
249
- - ".rubocop.yml"
250
- - ".travis.yml"
251
- - Dockerfile
252
- - Gemfile
253
- - Jenkinsfile
254
- - LICENSE.txt
255
234
  - README.md
256
- - docker-compose.override.example.yml
257
- - docker-compose.yml
258
- - dynamo-record.gemspec
259
235
  - lib/dynamo/record.rb
260
236
  - lib/dynamo/record/batch_get.rb
261
237
  - lib/dynamo/record/batch_request.rb
@@ -273,6 +249,29 @@ files:
273
249
  - lib/dynamo/record/task_helpers/scale.rb
274
250
  - lib/dynamo/record/version.rb
275
251
  - lib/tasks/dynamo.rake
252
+ - spec/gemfiles/rails-5.2.gemfile
253
+ - spec/gemfiles/rails-6.0.gemfile
254
+ - spec/gemfiles/rails-6.1.gemfile
255
+ - spec/internal/app/models/model1.rb
256
+ - spec/internal/app/models/model2.rb
257
+ - spec/internal/config/database.yml
258
+ - spec/internal/db/dynamo_migrate/20170402163638_create_model_1.rb
259
+ - spec/internal/db/dynamo_migrate/20170402163639_create_model_2.rb
260
+ - spec/internal/db/invalid_dynamo_migrate/add_model_1_stream.rb
261
+ - spec/lib/dynamo/record/batch_get_spec.rb
262
+ - spec/lib/dynamo/record/batch_write_spec.rb
263
+ - spec/lib/dynamo/record/model_existence_vaildator_spec.rb
264
+ - spec/lib/dynamo/record/model_spec.rb
265
+ - spec/lib/dynamo/record/table_migration_spec.rb
266
+ - spec/lib/dynamo/record/task_helpers/cleanup_spec.rb
267
+ - spec/lib/dynamo/record/task_helpers/drop_all_tables_spec.rb
268
+ - spec/lib/dynamo/record/task_helpers/drop_table_spec.rb
269
+ - spec/lib/dynamo/record/task_helpers/list_tables_spec.rb
270
+ - spec/lib/dynamo/record/task_helpers/migration_runner_spec.rb
271
+ - spec/lib/dynamo/record/task_helpers/scale_spec.rb
272
+ - spec/lib/dynamo/record/version_spec.rb
273
+ - spec/spec_helper.rb
274
+ - spec/support/shared_contexts/with_dummy_model.rb
276
275
  homepage: https://github.com/instructure/dynamo-record
277
276
  licenses:
278
277
  - MIT
@@ -292,8 +291,31 @@ required_rubygems_version: !ruby/object:Gem::Requirement
292
291
  - !ruby/object:Gem::Version
293
292
  version: '0'
294
293
  requirements: []
295
- rubygems_version: 3.0.3
294
+ rubygems_version: 3.4.10
296
295
  signing_key:
297
296
  specification_version: 4
298
297
  summary: Extensions to Aws::Record for working with DynamoDB.
299
- test_files: []
298
+ test_files:
299
+ - spec/gemfiles/rails-5.2.gemfile
300
+ - spec/gemfiles/rails-6.0.gemfile
301
+ - spec/gemfiles/rails-6.1.gemfile
302
+ - spec/internal/app/models/model1.rb
303
+ - spec/internal/app/models/model2.rb
304
+ - spec/internal/config/database.yml
305
+ - spec/internal/db/dynamo_migrate/20170402163638_create_model_1.rb
306
+ - spec/internal/db/dynamo_migrate/20170402163639_create_model_2.rb
307
+ - spec/internal/db/invalid_dynamo_migrate/add_model_1_stream.rb
308
+ - spec/lib/dynamo/record/batch_get_spec.rb
309
+ - spec/lib/dynamo/record/batch_write_spec.rb
310
+ - spec/lib/dynamo/record/model_existence_vaildator_spec.rb
311
+ - spec/lib/dynamo/record/model_spec.rb
312
+ - spec/lib/dynamo/record/table_migration_spec.rb
313
+ - spec/lib/dynamo/record/task_helpers/cleanup_spec.rb
314
+ - spec/lib/dynamo/record/task_helpers/drop_all_tables_spec.rb
315
+ - spec/lib/dynamo/record/task_helpers/drop_table_spec.rb
316
+ - spec/lib/dynamo/record/task_helpers/list_tables_spec.rb
317
+ - spec/lib/dynamo/record/task_helpers/migration_runner_spec.rb
318
+ - spec/lib/dynamo/record/task_helpers/scale_spec.rb
319
+ - spec/lib/dynamo/record/version_spec.rb
320
+ - spec/spec_helper.rb
321
+ - spec/support/shared_contexts/with_dummy_model.rb
data/.dockerignore DELETED
@@ -1,17 +0,0 @@
1
- /.gitignore
2
- /.rspec_status
3
- /.ruby-version
4
- /coverage/
5
- /doc/
6
- /Dockerfile
7
- /docker-compose.yml
8
- /docker-compose.override.example.yml
9
- /docker-compose.override.yml
10
- /dynamo-record-*.gem
11
- /Gemfile.lock
12
- /log/
13
- /pkg/
14
- /spec/gemfiles/.bundle/
15
- /spec/gemfiles/*.gemfile.lock
16
- /switchman-inst-jobs-*.gem
17
- /tmp/
data/.gitignore DELETED
@@ -1,16 +0,0 @@
1
- /.bundle/
2
- /.rspec_status
3
- /.ruby-version
4
- /.yardoc
5
- /_yardoc/
6
- /coverage/
7
- /docker-compose.override.yml
8
- /dynamo-record-*.gem
9
- /Gemfile.lock
10
- /pkg/
11
- /spec/gemfiles/.bundle/
12
- /spec/dummy/log/
13
- /spec/dummy/tmp/
14
- /spec/gemfiles/*.gemfile.lock
15
- /spec/reports/
16
- /tmp/
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require spec_helper
data/.rubocop.yml DELETED
@@ -1,61 +0,0 @@
1
- require:
2
- - rubocop-rails
3
-
4
- AllCops:
5
- NewCops: enable
6
- SuggestExtensions: false
7
- TargetRailsVersion: 5.2
8
- TargetRubyVersion: 2.6
9
-
10
- Metrics/AbcSize:
11
- Max: 20 # Default: 15
12
-
13
- Metrics/ClassLength:
14
- Max: 200 # Default: 100
15
-
16
- Metrics/MethodLength:
17
- Max: 20 # Default: 10
18
-
19
- Metrics/BlockLength:
20
- Max: 30
21
- Exclude:
22
- - dynamo-record.gemspec
23
- - spec/**/*.rb
24
-
25
- Layout/EndAlignment:
26
- EnforcedStyleAlignWith: variable
27
-
28
- Layout/LineLength:
29
- Max: 120 # Default: 80
30
-
31
- Layout/ParameterAlignment:
32
- # Alignment of parameters in multi-line method calls.
33
- #
34
- # The `with_fixed_indentation` style aligns the following lines with one
35
- # level of indentation relative to the start of the line with the method call.
36
- #
37
- # method_call(a,
38
- # b)
39
- EnforcedStyle: with_fixed_indentation
40
-
41
- Lint/ConstantDefinitionInBlock:
42
- Exclude:
43
- - spec/**/*.rb
44
-
45
- Naming/FileName:
46
- Exclude:
47
- - spec/gemfiles/*
48
-
49
- Naming/VariableNumber:
50
- EnforcedStyle: snake_case
51
-
52
- Style/Documentation:
53
- # This cop checks for missing top-level documentation of classes and modules.
54
- # Classes with no body and namespace modules are exempt from the check.
55
- # Namespace modules are modules that have nothing in their bodies except
56
- # classes or other modules.
57
- Enabled: false
58
-
59
- Style/NumericPredicate:
60
- Exclude:
61
- - spec/**/*.rb
data/.travis.yml DELETED
@@ -1,28 +0,0 @@
1
- dist: trusty
2
- sudo: false
3
- language: ruby
4
- cache: bundler
5
-
6
- rvm:
7
- - 2.6
8
- - 2.7
9
- - 3.0
10
-
11
- gemfile:
12
- - spec/gemfiles/rails-5.2.gemfile
13
- - spec/gemfiles/rails-6.0.gemfile
14
- - spec/gemfiles/rails-6.1.gemfile
15
-
16
- # Rails 5.2 doesn't support Ruby 3.0, so don't try
17
- matrix:
18
- exclude:
19
- - rvm: 3.0
20
- gemfile: spec/gemfiles/rails-5.2.gemfile
21
-
22
- before_install: gem update bundler
23
- bundler_args: --jobs 3
24
- install: bundle install --jobs 3
25
-
26
- script:
27
- - bash -c "if [ '$TRAVIS_RUBY_VERSION' = '3.0' ] && [[ '$BUNDLE_GEMFILE' == *'rails-6.1'* ]]; then bundle exec rubocop --fail-level autocorrect; fi"
28
- - bundle exec rspec
data/Dockerfile DELETED
@@ -1,24 +0,0 @@
1
- FROM instructure/rvm
2
-
3
- WORKDIR /app
4
- USER root
5
- RUN chown -R docker:docker /app
6
- RUN apt-get update
7
- RUN apt-get install -y git
8
-
9
- USER docker
10
-
11
- COPY --chown=docker:docker dynamo-record.gemspec Gemfile /app/
12
- COPY --chown=docker:docker lib/dynamo/record/version.rb /app/lib/dynamo/record/version.rb
13
-
14
- RUN mkdir -p coverage \
15
- spec/gemfiles/.bundle \
16
- spec/internal/log
17
-
18
- RUN bash -lc "rvm 2.6,2.7,3.0 do gem install --no-document bundler -v '~> 2.2'"
19
- RUN bash -lc "cd /app && rvm-exec 2.6 bundle install --jobs 5"
20
- RUN bash -lc "cd /app && rvm-exec 2.7 bundle install --jobs 5"
21
- RUN bash -lc "cd /app && rvm-exec 3.0 bundle install --jobs 5"
22
- COPY --chown=docker:docker . /app
23
-
24
- CMD /bin/bash -lc "rvm-exec 3.0 bundle exec wwtd"
data/Jenkinsfile DELETED
@@ -1,45 +0,0 @@
1
- #!/usr/bin/env groovy
2
-
3
- pipeline {
4
- agent {
5
- label 'docker'
6
- }
7
- options {
8
- ansiColor("xterm")
9
- buildDiscarder(logRotator(numToKeepStr: '50'))
10
- timeout(time: 20, unit: 'MINUTES')
11
- }
12
- stages {
13
- stage('Build') {
14
- steps {
15
- sh 'docker-compose pull dynamo'
16
- sh 'docker-compose up -d dynamo'
17
- sh 'docker-compose build --pull app'
18
- }
19
- }
20
- stage('Test') {
21
- steps {
22
- sh '''
23
- docker-compose run --rm app /bin/bash -l -c \
24
- "rvm-exec 3.0 bundle exec rubocop --fail-level autocorrect"
25
- docker-compose run --name coverage app
26
- '''
27
- }
28
- post {
29
- always {
30
- sh 'docker cp coverage:/app/coverage .'
31
- sh 'docker-compose down --rmi=all --volumes --remove-orphans'
32
-
33
- publishHTML target: [
34
- allowMissing: false,
35
- alwaysLinkToLastBuild: false,
36
- keepAll: true,
37
- reportDir: "coverage",
38
- reportFiles: 'index.html',
39
- reportName: 'Coverage Report'
40
- ]
41
- }
42
- }
43
- }
44
- }
45
- }
data/LICENSE.txt DELETED
@@ -1,21 +0,0 @@
1
- The MIT License (MIT)
2
-
3
- Copyright (c) 2017 Instructure, Inc.
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in
13
- all copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
- THE SOFTWARE.
@@ -1,19 +0,0 @@
1
- version: '2'
2
-
3
- services:
4
- app:
5
- volumes:
6
- - .:/app
7
- - gems:/home/docker/.rvm/gems
8
- # Disable the rest of these volumes if the container can safely write to
9
- # your host filesystem mount named above. You might want to use the rest
10
- # of these unless you're using dinghy on OSX (usually needed for linux).
11
- - coverage:/app/coverage
12
- - bundle-config:/app/spec/gemfiles/.bundle
13
- - internal-log:/app/spec/internal/log
14
-
15
- volumes:
16
- coverage: {}
17
- bundle-config: {}
18
- gems: {}
19
- internal-log: {}
data/docker-compose.yml DELETED
@@ -1,20 +0,0 @@
1
- version: '2'
2
-
3
- services:
4
- app:
5
- build: .
6
- environment:
7
- AWS_ACCESS_KEY_ID: x
8
- AWS_SECRET_ACCESS_KEY: x
9
- AWS_REGION: us-west-2
10
- DYNAMO_ENDPOINT: http://dynamo:8000
11
- RAILS_ENV: test
12
- logging:
13
- options:
14
- max-file: '1'
15
- max-size: 5m
16
- links:
17
- - dynamo
18
-
19
- dynamo:
20
- image: instructure/dynamodb
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'dynamo/record/version'
6
-
7
- Gem::Specification.new do |s|
8
- s.name = 'dynamo-record'
9
- s.version = Dynamo::Record::VERSION
10
- s.summary = 'Extensions to Aws::Record for working with DynamoDB.'
11
- s.homepage = 'https://github.com/instructure/dynamo-record'
12
- s.license = 'MIT'
13
-
14
- s.authors = [
15
- 'Davis McClellan',
16
- 'Ryan Taylor',
17
- 'Bryan Petty',
18
- 'Michael Brewer-Davis',
19
- 'Marc Phillips',
20
- 'Augusto Callejas',
21
- 'Frank Murphy'
22
- ]
23
- s.email = [
24
- 'dmcclellan@instructure.com',
25
- 'rtaylor@instructure.com',
26
- 'bpetty@instructure.com',
27
- 'mbd@instructure.com',
28
- 'mphillips@instructure.com',
29
- 'acallejas@instructure.com',
30
- 'fmurphy@instructure.com'
31
- ]
32
-
33
- s.files = `git ls-files -z`.split("\x0").reject do |f|
34
- f.match(%r{^(test|spec|features)/})
35
- end
36
- s.require_paths = ['lib']
37
-
38
- s.required_ruby_version = '>= 2.6'
39
-
40
- s.add_dependency 'activemodel', '>= 5.2', '< 6.2'
41
- s.add_dependency 'aws-record', '~> 2.0'
42
- s.add_dependency 'railties', '>= 5.2', '< 6.2'
43
-
44
- s.add_development_dependency 'activesupport', '>= 5.2', '< 6.2'
45
- s.add_development_dependency 'bundler', '~> 2.2'
46
- s.add_development_dependency 'byebug', '~> 11.0'
47
- s.add_development_dependency 'combustion', '~> 1.3'
48
- s.add_development_dependency 'rake', '~> 13.0'
49
- s.add_development_dependency 'rspec', '~> 3.6'
50
- s.add_development_dependency 'rubocop', '~> 1.8.1'
51
- s.add_development_dependency 'rubocop-rails', '~> 2.9.1'
52
- s.add_development_dependency 'simplecov', '~> 0.16'
53
- s.add_development_dependency 'webmock', '~> 3.3'
54
- s.add_development_dependency 'wwtd', '~> 1.3'
55
- end