1 | var db = require('../db')
|
2 |
|
3 | module.exports = function updateTable(store, data, cb) {
|
4 |
|
5 | var key = data.TableName, tableDb = store.tableDb
|
6 |
|
7 | tableDb.lock(key, function(release) {
|
8 | cb = release(cb)
|
9 |
|
10 | store.getTable(key, false, function(err, table) {
|
11 | if (err) return cb(err)
|
12 |
|
13 | var updates, i, update, dataThroughput, tableThroughput, readDiff, writeDiff
|
14 |
|
15 | try {
|
16 | updates = getThroughputUpdates(data, table)
|
17 | } catch (err) {
|
18 | return cb(err)
|
19 | }
|
20 |
|
21 | for (i = 0; i < updates.length; i++) {
|
22 | update = updates[i]
|
23 | dataThroughput = update.dataThroughput
|
24 | tableThroughput = update.tableThroughput
|
25 | readDiff = dataThroughput.ReadCapacityUnits - tableThroughput.ReadCapacityUnits
|
26 | writeDiff = dataThroughput.WriteCapacityUnits - tableThroughput.WriteCapacityUnits
|
27 |
|
28 | if (!readDiff && !writeDiff)
|
29 | return cb(db.validationError(
|
30 | 'The provisioned throughput for the table will not change. The requested value equals the current value. ' +
|
31 | 'Current ReadCapacityUnits provisioned for the table: ' + tableThroughput.ReadCapacityUnits +
|
32 | '. Requested ReadCapacityUnits: ' + dataThroughput.ReadCapacityUnits + '. ' +
|
33 | 'Current WriteCapacityUnits provisioned for the table: ' + tableThroughput.WriteCapacityUnits +
|
34 | '. Requested WriteCapacityUnits: ' + dataThroughput.WriteCapacityUnits + '. ' +
|
35 | 'Refer to the Amazon DynamoDB Developer Guide for current limits and how to request higher limits.'))
|
36 |
|
37 | update.setStatus('UPDATING')
|
38 |
|
39 | if (readDiff > 0 || writeDiff > 0) tableThroughput.LastIncreaseDateTime = Date.now() / 1000
|
40 | if (readDiff < 0 || writeDiff < 0) tableThroughput.LastDecreaseDateTime = Date.now() / 1000
|
41 |
|
42 | update.readDiff = readDiff
|
43 | update.writeDiff = writeDiff
|
44 | }
|
45 |
|
46 | tableDb.put(key, table, function(err) {
|
47 | if (err) return cb(err)
|
48 |
|
49 | setTimeout(function() {
|
50 |
|
51 |
|
52 | updates.forEach(function(update) {
|
53 | dataThroughput = update.dataThroughput
|
54 | tableThroughput = update.tableThroughput
|
55 |
|
56 | update.setStatus('ACTIVE')
|
57 |
|
58 | if (update.readDiff > 0 || update.writeDiff > 0) {
|
59 | tableThroughput.LastIncreaseDateTime = Date.now() / 1000
|
60 | } else if (update.readDiff < 0 || update.writeDiff < 0) {
|
61 | tableThroughput.LastDecreaseDateTime = Date.now() / 1000
|
62 | tableThroughput.NumberOfDecreasesToday++
|
63 | }
|
64 |
|
65 | tableThroughput.ReadCapacityUnits = dataThroughput.ReadCapacityUnits
|
66 | tableThroughput.WriteCapacityUnits = dataThroughput.WriteCapacityUnits
|
67 | })
|
68 |
|
69 | tableDb.put(key, table, function(err) {
|
70 |
|
71 | if (err && !/Database is not open/.test(err)) console.error(err.stack || err)
|
72 | })
|
73 |
|
74 | }, store.options.updateTableMs)
|
75 |
|
76 | cb(null, {TableDescription: table})
|
77 | })
|
78 | })
|
79 | })
|
80 |
|
81 | }
|
82 |
|
83 | function getThroughputUpdates(data, table) {
|
84 | var updates = []
|
85 | if (data.ProvisionedThroughput) {
|
86 | updates.push({
|
87 | dataThroughput: data.ProvisionedThroughput,
|
88 | tableThroughput: table.ProvisionedThroughput,
|
89 | setStatus: function(status) { table.TableStatus = status },
|
90 | })
|
91 | }
|
92 | var globalUpdates = data.GlobalSecondaryIndexUpdates || []
|
93 | if (globalUpdates.length > 5) throw db.limitError('Subscriber limit exceeded: Only 1 online index can be created or deleted simultaneously per table')
|
94 | globalUpdates.forEach(function(update) {
|
95 | var dataThroughput = update.Update && update.Update.ProvisionedThroughput
|
96 | if (!dataThroughput) {
|
97 | return
|
98 | }
|
99 | if (dataThroughput.ReadCapacityUnits > 1000000000000 || dataThroughput.WriteCapacityUnits > 1000000000000) {
|
100 | throw db.validationError('This operation cannot be performed with given input values. Please contact DynamoDB service team for more info: Action Blocked: IndexUpdate')
|
101 | }
|
102 | (table.GlobalSecondaryIndexes || []).forEach(function(index) {
|
103 | if (index.IndexName == update.Update.IndexName) {
|
104 | updates.push({
|
105 | dataThroughput: dataThroughput,
|
106 | tableThroughput: index.ProvisionedThroughput,
|
107 | setStatus: function(status) { index.IndexStatus = status },
|
108 | })
|
109 | }
|
110 | })
|
111 | })
|
112 | return updates
|
113 | }
|