dynamo-record 1.4.1 → 1.4.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.
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