dynamo-record 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.dockerignore +15 -0
- data/.gitignore +9 -5
- data/.rspec +1 -0
- data/.rubocop.yml +9 -30
- data/.travis.yml +18 -2
- data/Dockerfile +22 -0
- data/Gemfile +0 -1
- data/LICENSE.txt +21 -0
- data/README.md +75 -17
- data/build.sh +10 -20
- data/docker-compose.override.example.yml +19 -0
- data/docker-compose.yml +7 -2
- data/dynamo-record.gemspec +40 -28
- data/lib/dynamo/record.rb +17 -0
- data/lib/dynamo/record/marshalers.rb +46 -0
- data/lib/dynamo/record/model.rb +127 -0
- data/lib/dynamo/record/model_existence_validator.rb +10 -0
- data/lib/{dynamo-record → dynamo}/record/railtie.rb +1 -3
- data/lib/dynamo/record/table_migration.rb +59 -0
- data/lib/dynamo/record/task_helpers/cleanup.rb +21 -0
- data/lib/dynamo/record/task_helpers/drop_all_tables.rb +19 -0
- data/lib/dynamo/record/task_helpers/drop_table.rb +13 -0
- data/lib/dynamo/record/task_helpers/list_tables.rb +15 -0
- data/lib/dynamo/record/task_helpers/migration_runner.rb +72 -0
- data/lib/dynamo/record/task_helpers/scale.rb +90 -0
- data/lib/dynamo/record/version.rb +5 -0
- data/lib/tasks/dynamo.rake +7 -7
- metadata +96 -37
- data/Dockerfile.test +0 -23
- data/Gemfile.lock +0 -178
- data/doc/testing.md +0 -11
- data/docker-compose.dev.override.yml +0 -6
- data/lib/dynamo-record.rb +0 -4
- data/lib/dynamo-record/marshalers.rb +0 -44
- data/lib/dynamo-record/model.rb +0 -127
- data/lib/dynamo-record/record.rb +0 -7
- data/lib/dynamo-record/record/version.rb +0 -5
- data/lib/dynamo-record/table_migration.rb +0 -58
- data/lib/dynamo-record/task_helpers/cleanup.rb +0 -19
- data/lib/dynamo-record/task_helpers/drop_all_tables.rb +0 -17
- data/lib/dynamo-record/task_helpers/drop_table.rb +0 -11
- data/lib/dynamo-record/task_helpers/list_tables.rb +0 -13
- data/lib/dynamo-record/task_helpers/migration_runner.rb +0 -70
- data/lib/dynamo-record/task_helpers/scale.rb +0 -86
- data/lib/model_existence_validator.rb +0 -7
@@ -1,19 +0,0 @@
|
|
1
|
-
module DynamoRecord
|
2
|
-
module TaskHelpers
|
3
|
-
class Cleanup
|
4
|
-
def self.run
|
5
|
-
raise 'Task not available on production' if Rails.env.production?
|
6
|
-
Dir[Rails.root.join('app/models/*.rb').to_s].each do |filename|
|
7
|
-
delete_by_class(filename)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.delete_by_class(filename)
|
12
|
-
klass = File.basename(filename, '.rb').camelize.constantize
|
13
|
-
return unless klass.included_modules.include? DynamoRecord::Model
|
14
|
-
Rails.logger.info "Deleting all items in table: #{klass}"
|
15
|
-
klass.scan.each(&:delete!)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,17 +0,0 @@
|
|
1
|
-
module DynamoRecord
|
2
|
-
module TaskHelpers
|
3
|
-
class DropAllTables
|
4
|
-
def self.run(override = false)
|
5
|
-
raise 'Task not available on production' if Rails.env.production?
|
6
|
-
env = Rails.env
|
7
|
-
dynamodb = Aws::DynamoDB::Client.new
|
8
|
-
tables = dynamodb.list_tables
|
9
|
-
tables.table_names.map do |t|
|
10
|
-
next unless t.include?(env) || override
|
11
|
-
dt = dynamodb.delete_table(table_name: t)
|
12
|
-
dt ? "Deleted: #{t}" : "Delete failed: #{t}"
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,13 +0,0 @@
|
|
1
|
-
module DynamoRecord
|
2
|
-
module TaskHelpers
|
3
|
-
class ListTables
|
4
|
-
def self.run
|
5
|
-
dynamodb = Aws::DynamoDB::Client.new
|
6
|
-
tables = dynamodb.list_tables
|
7
|
-
tables.table_names.select do |tn|
|
8
|
-
tn.starts_with?(Rails.configuration.dynamo['prefix'])
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,70 +0,0 @@
|
|
1
|
-
module DynamoRecord
|
2
|
-
module TaskHelpers
|
3
|
-
class MigrationRunner
|
4
|
-
def self.run(path = 'db/dynamo_migrate')
|
5
|
-
constants = []
|
6
|
-
filename_regexp = /\A([0-9]+)_([_a-z0-9]*)\.?([_a-z0-9]*)?\.rb\z/
|
7
|
-
|
8
|
-
# Sorts the files located in `db/dynamo_migrate` to ensure order is preserved
|
9
|
-
Dir[Rails.root.join("#{path}/*.rb")].sort.each do |f|
|
10
|
-
migration = migration(f, filename_regexp, constants)
|
11
|
-
|
12
|
-
# starts the migration
|
13
|
-
yield "Migrating: #{migration}"
|
14
|
-
|
15
|
-
begin
|
16
|
-
status = table_config_check(migration)
|
17
|
-
yield status if status
|
18
|
-
|
19
|
-
status = up(migration)
|
20
|
-
yield status if status
|
21
|
-
|
22
|
-
status = update(migration)
|
23
|
-
yield status if status
|
24
|
-
rescue => e
|
25
|
-
yield "Migration failed: #{e}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.migration(f, filename_regexp, constants)
|
31
|
-
raise "Non-numeric prefix: #{f}" if File.basename(f).scan(filename_regexp).first.nil?
|
32
|
-
require f
|
33
|
-
|
34
|
-
# finds the constant that was added on the require statement above
|
35
|
-
migration_sym = (DynamoMigrate.constants - constants).first
|
36
|
-
migration = DynamoMigrate.const_get(migration_sym)
|
37
|
-
constants.push migration_sym
|
38
|
-
migration
|
39
|
-
end
|
40
|
-
|
41
|
-
def self.status_message(status)
|
42
|
-
case status
|
43
|
-
when :exists
|
44
|
-
'Table already exists'
|
45
|
-
when :migrated
|
46
|
-
'Migration successful'
|
47
|
-
else
|
48
|
-
raise 'Migration failed'
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def self.up(migration)
|
53
|
-
return unless migration.respond_to? :up
|
54
|
-
status_message migration.up
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.table_config_check(migration)
|
58
|
-
return unless migration.respond_to? :table_config
|
59
|
-
status_message migration.table_config_check
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.update(migration)
|
63
|
-
return unless migration.respond_to? :update
|
64
|
-
status = migration.update
|
65
|
-
return 'Migration successful' if status == :updated
|
66
|
-
status
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
module DynamoRecord
|
2
|
-
module TaskHelpers
|
3
|
-
class Scale
|
4
|
-
attr_reader :model, :attribute_selector, :new_throughput
|
5
|
-
attr_reader :migration, :existing_throughput, :model_name
|
6
|
-
|
7
|
-
def initialize(model_name, attribute_selector, new_throughput)
|
8
|
-
@model_name = model_name
|
9
|
-
@attribute_selector = attribute_selector
|
10
|
-
@new_throughput = new_throughput
|
11
|
-
end
|
12
|
-
|
13
|
-
def run
|
14
|
-
return description if [model_name, attribute_selector, new_throughput].any?(&:nil?)
|
15
|
-
|
16
|
-
@model = model_name.constantize
|
17
|
-
@migration = Aws::Record::TableMigration.new(model)
|
18
|
-
@existing_throughput = model.provisioned_throughput
|
19
|
-
|
20
|
-
update_throughput
|
21
|
-
success_message
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def success_message
|
27
|
-
"Successfully updated #{model.table_name} throughput to #{update_instructions[:provisioned_throughput]}"
|
28
|
-
end
|
29
|
-
|
30
|
-
def update_throughput
|
31
|
-
raise_attribute_error if !read? && !write?
|
32
|
-
|
33
|
-
migration.update!(update_instructions)
|
34
|
-
end
|
35
|
-
|
36
|
-
def update_instructions
|
37
|
-
{
|
38
|
-
provisioned_throughput: {
|
39
|
-
write_capacity_units: (write? && new_throughput) || existing_write,
|
40
|
-
read_capacity_units: (read? && new_throughput) || existing_read
|
41
|
-
}
|
42
|
-
}
|
43
|
-
end
|
44
|
-
|
45
|
-
def existing_write
|
46
|
-
existing_throughput[:write_capacity_units]
|
47
|
-
end
|
48
|
-
|
49
|
-
def existing_read
|
50
|
-
existing_throughput[:read_capacity_units]
|
51
|
-
end
|
52
|
-
|
53
|
-
def both?
|
54
|
-
attribute_selector.to_sym == :both
|
55
|
-
end
|
56
|
-
|
57
|
-
def read?
|
58
|
-
both? || attribute_selector.to_sym == :read
|
59
|
-
end
|
60
|
-
|
61
|
-
def write?
|
62
|
-
both? || attribute_selector.to_sym == :write
|
63
|
-
end
|
64
|
-
|
65
|
-
def raise_attribute_error
|
66
|
-
raise ArgumentError, 'You didn\'t provide an appropriate attribute selection. We accept [:both, :read, :write]'
|
67
|
-
end
|
68
|
-
|
69
|
-
def description
|
70
|
-
<<~DESCRIPTION
|
71
|
-
--------------------------------------------------------------------------------
|
72
|
-
Here's some usage information:
|
73
|
-
Scale a dynamo table. Requires three inputs.
|
74
|
-
- ModelName
|
75
|
-
ruby class of the model
|
76
|
-
- attribute
|
77
|
-
valid values include "both", "read" and "write"
|
78
|
-
- new_throughput
|
79
|
-
numerical value for the new read/write capacity units
|
80
|
-
Example: `rake dynamo:scale[MySuperDynamoModel,both,50]`
|
81
|
-
--------------------------------------------------------------------------------
|
82
|
-
DESCRIPTION
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,7 +0,0 @@
|
|
1
|
-
require 'active_model'
|
2
|
-
class ModelExistenceValidator < ActiveModel::EachValidator
|
3
|
-
def validate_each(record, attribute, value)
|
4
|
-
return if options[:model].exists? value
|
5
|
-
record.errors[attribute] << (options[:message] || "#{attribute}:#{value} is not a valid #{options[:model]}")
|
6
|
-
end
|
7
|
-
end
|