dynamodb_framework 0.1.4 → 1.0.0

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.
@@ -1,16 +1,16 @@
1
- class DynamoDbStore
2
- attr_reader :client
1
+ module DynamoDbFramework
2
+ class Store
3
+ attr_reader :client
4
+
5
+ def initialize(options = {})
6
+
7
+ if options.has_key?(:endpoint)
8
+ @client = Aws::DynamoDB::Client.new(region: options[:aws_region], endpoint: options[:endpoint])
9
+ else
10
+ @client = Aws::DynamoDB::Client.new
11
+ end
3
12
 
4
- def initialize
5
- region = ENV['DYNAMODB_REGION']
6
- endpoint = ENV['DYNAMODB_ENDPOINT']
7
- secret = ENV['DYNAMODB_SECRET']
8
- key = ENV['DYNAMODB_ACCESS_KEY']
9
- if endpoint != nil
10
- @client = Aws::DynamoDB::Client.new(region: region, endpoint: endpoint, secret_access_key: secret, access_key_id: key)
11
- else
12
- @client = Aws::DynamoDB::Client.new(region: region, secret_access_key: secret, access_key_id: key)
13
13
  end
14
- end
15
14
 
16
- end
15
+ end
16
+ end
@@ -1,283 +1,352 @@
1
- class DynamoDbTableManager
1
+ module DynamoDbFramework
2
+ class TableManager
2
3
 
3
- attr_reader :dynamodb
4
+ attr_reader :dynamodb
4
5
 
5
- def initialize
6
- @dynamodb = DynamoDbStore.new
7
- end
6
+ def initialize(store)
7
+ @dynamodb = store
8
+ end
8
9
 
9
- def exists?(table_name)
10
+ def exists?(table_name)
10
11
 
11
- exists = true
12
+ exists = true
12
13
 
13
- begin
14
- dynamodb.client.describe_table(:table_name => table_name)
15
- rescue Aws::DynamoDB::Errors::ResourceNotFoundException
16
- exists = false
17
- end
14
+ begin
15
+ dynamodb.client.describe_table(:table_name => table_name)
16
+ rescue Aws::DynamoDB::Errors::ResourceNotFoundException
17
+ exists = false
18
+ end
18
19
 
19
- return exists
20
+ return exists
20
21
 
21
- end
22
+ end
22
23
 
23
- def has_index?(table_name, index_name)
24
- exists = true
24
+ def has_index?(table_name, index_name)
25
+ exists = true
25
26
 
26
- begin
27
- result = dynamodb.client.describe_table(:table_name => table_name)
27
+ begin
28
+ result = dynamodb.client.describe_table(:table_name => table_name)
28
29
 
29
- if result.table[:global_secondary_indexes] == nil
30
- return false
31
- end
30
+ if result.table[:global_secondary_indexes] == nil
31
+ return false
32
+ end
32
33
 
33
- if result.table[:global_secondary_indexes].select { |i| i[:index_name] == index_name }.length > 0
34
- exists = true
35
- else
34
+ if result.table[:global_secondary_indexes].select { |i| i[:index_name] == index_name }.length > 0
35
+ exists = true
36
+ else
37
+ exists = false
38
+ end
39
+ rescue Aws::DynamoDB::Errors::ResourceNotFoundException
36
40
  exists = false
37
41
  end
38
- rescue Aws::DynamoDB::Errors::ResourceNotFoundException
39
- exists = false
42
+
43
+ return exists
40
44
  end
41
45
 
42
- return exists
43
- end
46
+ def update_throughput(table_name, read_capacity, write_capacity)
44
47
 
45
- def update_throughput(table_name, read_capacity, write_capacity)
48
+ if !exists?(table_name)
49
+ raise "table: #{table_name}, does not exist."
50
+ end
46
51
 
47
- if !exists?(table_name)
48
- raise "table: #{table_name}, does not exist."
49
- end
52
+ table = {
53
+ :table_name => table_name,
54
+ :provisioned_throughput => {
55
+ :read_capacity_units => read_capacity,
56
+ :write_capacity_units => write_capacity
57
+ }
58
+ }
50
59
 
51
- table = {
52
- :table_name => table_name,
53
- :provisioned_throughput => {
54
- :read_capacity_units => read_capacity,
55
- :write_capacity_units => write_capacity
56
- }
57
- }
60
+ dynamodb.client.update_table(table)
58
61
 
59
- dynamodb.client.update_table(table)
62
+ # wait for table to be updated
63
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Waiting for table: [#{table_name}] to be updated."
64
+ wait_until_active(table_name)
65
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Table: [#{table_name}] updated."
60
66
 
61
- # wait for table to be updated
62
- puts "waiting for table: [#{table_name}] to be updated..."
63
- wait_until_active(table_name)
64
- puts "table: [#{table_name}] updated!"
67
+ end
65
68
 
66
- end
69
+ def add_index(table_name, attributes, global_index)
70
+
71
+ attribute_definitions = []
72
+
73
+ attributes.each do |a|
74
+ attribute_definitions.push({ :attribute_name => a[:name], :attribute_type => a[:type] })
75
+ end
67
76
 
68
- def add_index(table_name, attributes, global_index)
77
+ table = {
78
+ :table_name => table_name,
79
+ :attribute_definitions => attribute_definitions,
80
+ :global_secondary_index_updates => [
81
+ :create => global_index
82
+ ]
83
+ }
69
84
 
70
- attribute_definitions = []
85
+ dynamodb.client.update_table(table)
71
86
 
72
- attributes.each do |a|
73
- attribute_definitions.push({ :attribute_name => a[:name], :attribute_type => a[:type] })
87
+ # wait for table to be updated
88
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Adding global index: #{global_index[:index_name]}."
89
+ wait_until_index_active(table_name, global_index[:index_name])
90
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Index added."
74
91
  end
75
92
 
76
- table = {
77
- :table_name => table_name,
78
- :attribute_definitions => attribute_definitions,
79
- :global_secondary_index_updates => [
80
- :create => global_index
81
- ]
82
- }
93
+ def update_index_throughput(table_name, index_name, read_capacity, write_capacity)
94
+ table = {
95
+ :table_name => table_name,
96
+ :global_secondary_index_updates => [
97
+ :update => {
98
+ :index_name => index_name,
99
+ :provisioned_throughput => {
100
+ :read_capacity_units => read_capacity,
101
+ :write_capacity_units => write_capacity
102
+ }
103
+ }
104
+ ]
105
+ }
106
+
107
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Updating throughput for global index: #{index_name}."
108
+
109
+ dynamodb.client.update_table(table)
110
+
111
+ # wait for table to be updated
112
+
113
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Waiting for table: [#{table_name}] to be updated."
114
+ wait_until_active(table_name)
115
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Table: [#{table_name}] updated."
116
+ end
83
117
 
84
- dynamodb.client.update_table(table)
118
+ def drop_index(table_name, index_name)
119
+ table = {
120
+ :table_name => table_name,
121
+ :global_secondary_index_updates => [
122
+ :delete => {
123
+ :index_name => index_name
124
+ }
125
+ ]
126
+ }
127
+
128
+ dynamodb.client.update_table(table)
129
+
130
+ # wait for table to be updated
131
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Deleting global index: #{index_name}."
132
+ wait_until_index_dropped(table_name, index_name)
133
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Index: [#{index_name}] dropped."
134
+ end
85
135
 
86
- # wait for table to be updated
87
- puts "Adding global index: #{global_index[:index_name]}..."
88
- wait_until_index_active(table_name, global_index[:index_name])
89
- puts "Index added!"
90
- end
136
+ def get_status(table_name)
137
+ result = dynamodb.client.describe_table(:table_name => table_name)
138
+ return result.table[:table_status]
139
+ end
91
140
 
92
- def update_index_throughput(table_name, index_name, read_capacity, write_capacity)
93
- table = {
94
- :table_name => table_name,
95
- :global_secondary_index_updates => [
96
- :update => {
97
- :index_name => index_name,
98
- :provisioned_throughput => {
99
- :read_capacity_units => read_capacity,
100
- :write_capacity_units => write_capacity
101
- }
102
- }
103
- ]
104
- }
105
-
106
- dynamodb.client.update_table(table)
107
-
108
- # wait for table to be updated
109
- puts "Updating throughput for global index: #{index_name}..."
110
- puts "waiting for table: [#{table_name}] to be updated..."
111
- wait_until_active(table_name)
112
- puts "table: [#{table_name}] updated!"
113
- end
141
+ def get_index_status(table_name, index_name)
142
+ result = dynamodb.client.describe_table(:table_name => table_name)
114
143
 
115
- def drop_index(table_name, index_name)
116
- table = {
117
- :table_name => table_name,
118
- :global_secondary_index_updates => [
119
- :delete => {
120
- :index_name => index_name
121
- }
122
- ]
123
- }
124
-
125
- dynamodb.client.update_table(table)
126
-
127
- # wait for table to be updated
128
- puts "Deleting global index: #{index_name}..."
129
- wait_until_index_dropped(table_name, index_name)
130
- puts "Index: [#{index_name}] dropped!"
131
- end
144
+ if result.table[:global_secondary_indexes] == nil
145
+ return nil
146
+ end
132
147
 
133
- def get_status(table_name)
134
- result = dynamodb.client.describe_table(:table_name => table_name)
135
- return result.table[:table_status]
136
- end
148
+ index = result.table[:global_secondary_indexes].select { |i| i[:index_name] == index_name }
137
149
 
138
- def get_index_status(table_name, index_name)
139
- result = dynamodb.client.describe_table(:table_name => table_name)
150
+ if index.length > 0
151
+ return index[0][:index_status]
152
+ end
140
153
 
141
- if result.table[:global_secondary_indexes] == nil
142
154
  return nil
143
155
  end
144
156
 
145
- index = result.table[:global_secondary_indexes].select { |i| i[:index_name] == index_name }
157
+ def wait_until_active(table_name)
158
+
159
+ end_time = Time.now + 300
160
+ while Time.now < end_time do
161
+
162
+ status = get_status(table_name)
163
+
164
+ if status == 'ACTIVE'
165
+ return
166
+ end
167
+
168
+ sleep(5)
169
+ end
170
+
171
+ raise "Timeout occured while waiting for table: #{table_name}, to become active."
146
172
 
147
- if index.length > 0
148
- return index[0][:index_status]
149
173
  end
150
174
 
151
- return nil
152
- end
175
+ def wait_until_index_active(table_name, index_name)
153
176
 
154
- def wait_until_active(table_name)
177
+ end_time = Time.now + 300
178
+ while Time.now < end_time do
155
179
 
156
- end_time = Time.now + 5.minutes
157
- while Time.now < end_time do
180
+ status = get_index_status(table_name, index_name)
158
181
 
159
- status = get_status(table_name)
182
+ if status == 'ACTIVE'
183
+ return
184
+ end
160
185
 
161
- if status == 'ACTIVE'
162
- return
186
+ sleep(5)
163
187
  end
164
188
 
165
- sleep(5.seconds)
189
+ raise "Timeout occured while waiting for table: #{table_name}, index: #{index_name}, to become active."
190
+
166
191
  end
167
192
 
168
- raise "Timeout occured while waiting for table: #{table_name}, to become active."
193
+ def wait_until_index_dropped(table_name, index_name)
169
194
 
170
- end
195
+ end_time = Time.now + 300
196
+ while Time.now < end_time do
197
+
198
+ status = get_index_status(table_name, index_name)
199
+
200
+ if status == nil
201
+ return
202
+ end
171
203
 
172
- def wait_until_index_active(table_name, index_name)
204
+ sleep(5)
205
+ end
206
+
207
+ raise "Timeout occured while waiting for table: #{table_name}, index: #{index_name}, to be dropped."
173
208
 
174
- end_time = Time.now + 5.minutes
175
- while Time.now < end_time do
209
+ end
176
210
 
177
- status = get_index_status(table_name, index_name)
211
+ def create(table_name, attributes, partition_key, range_key = nil, read_capacity = 20, write_capacity = 10, global_indexes = nil)
178
212
 
179
- if status == 'ACTIVE'
213
+ if exists?(table_name)
180
214
  return
181
215
  end
182
216
 
183
- sleep(5.seconds)
184
- end
217
+ attribute_definitions = []
185
218
 
186
- raise "Timeout occured while waiting for table: #{table_name}, index: #{index_name}, to become active."
219
+ attributes.each do |a|
220
+ attribute_definitions.push({ :attribute_name => a[:name], :attribute_type => a[:type] })
221
+ end
187
222
 
188
- end
223
+ key_schema = []
224
+ key_schema.push({ :attribute_name => partition_key, :key_type => :HASH })
225
+ if range_key != nil
226
+ key_schema.push({ :attribute_name => range_key, :key_type => :RANGE })
227
+ end
189
228
 
190
- def wait_until_index_dropped(table_name, index_name)
229
+ table = {
230
+ :table_name => table_name,
231
+ :attribute_definitions => attribute_definitions,
232
+ :key_schema => key_schema,
233
+ :provisioned_throughput => {
234
+ :read_capacity_units => read_capacity,
235
+ :write_capacity_units => write_capacity
236
+ }
237
+ }
238
+
239
+ if global_indexes != nil
240
+ table[:global_secondary_indexes] = global_indexes
241
+ end
191
242
 
192
- end_time = Time.now + 5.minutes
193
- while Time.now < end_time do
243
+ dynamodb.client.create_table(table)
244
+
245
+ # wait for table to be created
246
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Waiting for table: [#{table_name}] to be created."
247
+ dynamodb.client.wait_until(:table_exists, table_name: table_name)
248
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Table: [#{table_name}] created."
249
+ end
194
250
 
195
- status = get_index_status(table_name, index_name)
251
+ def create_table(options = {})
196
252
 
197
- if status == nil
253
+ if options[:name] == nil
254
+ raise 'A valid table name must be specified.'
255
+ end
256
+
257
+ if exists?(options[:name])
198
258
  return
199
259
  end
200
260
 
201
- sleep(5.seconds)
202
- end
261
+ options[:read_capacity] ||= 20
262
+ options[:write_capacity] ||= 20
203
263
 
204
- raise "Timeout occured while waiting for table: #{table_name}, index: #{index_name}, to be dropped."
264
+ if !options[:attributes].is_a?(Array)
265
+ raise 'A valid :attributes array must be specified.'
266
+ end
205
267
 
206
- end
268
+ attribute_definitions = options[:attributes].map { |a| { :attribute_name => a[:name], :attribute_type => a[:type] } }
207
269
 
208
- def create(table_name, attributes, partition_key, range_key = nil, read_capacity = 20, write_capacity = 10, global_indexes = nil)
270
+ hash_key = options[:attributes].detect { |a| a[:key] == :hash }
271
+ if hash_key == nil
272
+ raise 'No Hash Key attribute has been specified.'
273
+ end
209
274
 
210
- if exists?(table_name)
211
- return
212
- end
275
+ range_key = options[:attributes].detect { |a| a[:key] == :range }
213
276
 
214
- attribute_definitions = []
277
+ key_schema = []
278
+ key_schema.push({ :attribute_name => hash_key[:name], :key_type => :HASH })
279
+ if range_key != nil
280
+ key_schema.push({ :attribute_name => range_key[:name], :key_type => :RANGE })
281
+ end
215
282
 
216
- attributes.each do |a|
217
- attribute_definitions.push({ :attribute_name => a[:name], :attribute_type => a[:type] })
218
- end
283
+ table = {
284
+ :table_name => options[:name],
285
+ :attribute_definitions => attribute_definitions,
286
+ :key_schema => key_schema,
287
+ :provisioned_throughput => {
288
+ :read_capacity_units => options[:read_capacity],
289
+ :write_capacity_units => options[:write_capacity]
290
+ }
291
+ }
292
+
293
+ if options[:global_indexes] != nil
294
+ table[:global_secondary_indexes] = options[:global_indexes]
295
+ end
219
296
 
220
- key_schema = []
221
- key_schema.push({ :attribute_name => partition_key, :key_type => :HASH })
222
- if range_key != nil
223
- key_schema.push({ :attribute_name => range_key, :key_type => :RANGE })
224
- end
297
+ dynamodb.client.create_table(table)
225
298
 
226
- table = {
227
- :table_name => table_name,
228
- :attribute_definitions => attribute_definitions,
229
- :key_schema => key_schema,
230
- :provisioned_throughput => {
231
- :read_capacity_units => read_capacity,
232
- :write_capacity_units => write_capacity
233
- }
234
- }
235
-
236
- if global_indexes != nil
237
- table[:global_secondary_indexes] = global_indexes
299
+ # wait for table to be created
300
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Waiting for table: [#{options[:name]}] to be created."
301
+ dynamodb.client.wait_until(:table_exists, table_name: options[:name])
302
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Table: [#{options[:name]}] created."
238
303
  end
239
304
 
240
- dynamodb.client.create_table(table)
305
+ def create_global_index(name, partition_key, range_key = nil, read_capacity = 20, write_capacity = 10)
241
306
 
242
- # wait for table to be created
243
- puts "waiting for table: [#{table_name}] to be created..."
244
- dynamodb.client.wait_until(:table_exists, table_name: table_name)
245
- puts "table: [#{table_name}] created!"
246
- end
307
+ key_schema = []
308
+
309
+ key_schema.push({ :attribute_name => partition_key, :key_type => :HASH })
310
+ if range_key != nil
311
+ key_schema.push({ :attribute_name => range_key, :key_type => :RANGE })
312
+ end
313
+
314
+ index = {
315
+ :index_name => name,
316
+ :key_schema => key_schema,
317
+ :projection => {
318
+ :projection_type => :ALL
319
+ },
320
+ :provisioned_throughput => {
321
+ :read_capacity_units => read_capacity,
322
+ :write_capacity_units => write_capacity,
323
+ }
324
+ }
325
+
326
+ return index
327
+ end
247
328
 
248
- def create_global_index(name, partition_key, range_key = nil, read_capacity = 20, write_capacity = 10)
329
+ def drop(table_name)
249
330
 
250
- key_schema = []
331
+ if !exists?(table_name)
332
+ return
333
+ end
251
334
 
252
- key_schema.push({ :attribute_name => partition_key, :key_type => :HASH })
253
- if range_key != nil
254
- key_schema.push({ :attribute_name => range_key, :key_type => :RANGE })
335
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Dropping table: [#{table_name}]."
336
+ dynamodb.client.delete_table({ table_name: table_name })
337
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Table: [#{table_name}] dropped."
255
338
  end
256
339
 
257
- index = {
258
- :index_name => name,
259
- :key_schema => key_schema,
260
- :projection => {
261
- :projection_type => :ALL
262
- },
263
- :provisioned_throughput => {
264
- :read_capacity_units => read_capacity,
265
- :write_capacity_units => write_capacity,
266
- }
267
- }
268
-
269
- return index
270
- end
340
+ def drop_table(table_name)
271
341
 
272
- def drop(table_name)
342
+ if !exists?(table_name)
343
+ return
344
+ end
273
345
 
274
- if !exists?(table_name)
275
- return
346
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Dropping table: [#{table_name}]."
347
+ dynamodb.client.delete_table({ table_name: table_name })
348
+ DynamoDbFramework::LOGGER.info "[DynamoDbFramework] - Table: [#{table_name}] dropped."
276
349
  end
277
350
 
278
- puts "dropping table: [#{table_name}] ..."
279
- dynamodb.client.delete_table({ table_name: table_name })
280
- puts "table: [#{table_name}] dropped!"
281
351
  end
282
-
283
- end
352
+ end