Skip to content

Instantly share code, notes, and snippets.

@aprilmintacpineda
Last active October 28, 2021 22:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aprilmintacpineda/0574d8aa0ee120d69d9bd59d745f6642 to your computer and use it in GitHub Desktop.
Save aprilmintacpineda/0574d8aa0ee120d69d9bd59d745f6642 to your computer and use it in GitHub Desktop.
A script to cleanup (delete all items) your dynamodb tables in appsync

What is this?

THIS SCRIPT WILL DELETE ALL ITEMS OF THE DYNAMODB TABLES OF YOUR APPSYNC APP.

How to use:

  1. Copy-paste the script to your machine.
  2. Run yarn add @aws-sdk/util-dynamodb aws-sd date-fnsk prompt-confirm.
  3. Provide the correct values in the configuration section of the script.
  4. Run the script via nodejs.

Depending on how many items you have, this can take anywhere from a few seconds (when you have only a few thousands) to an entire day (when you have around 50 million items)

require('cross-fetch/polyfill');
const { marshall, unmarshall } = require('@aws-sdk/util-dynamodb');
const AWS = require('aws-sdk');
const { differenceInHours } = require('date-fns');
const PromptConfirm = require('prompt-confirm');
/**
* Configuration
* make sure to add the values for the following constants
*/
// aws region where the appsync lives
const region = 'ap-southeast-2';
// aws profile that you want to use, defined in ~/.aws/config
const profile = 'mb-wrg';
// api id from AppSync
const apiId = '';
// names of tables you want to clean up, set to `null` to clean all tables
const whiteList = [];
//////////// END CONFIGURATION STUFF
const credentials = new AWS.SharedIniFileCredentials({ profile });
const updatedAt = new Date().toISOString();
const dynamodb = new AWS.DynamoDB({
apiVersion: '2012-08-10',
region,
credentials
});
async function getAllItems(tableName, limit, nextToken) {
return new Promise((resolve, reject) => {
dynamodb.scan(
{
TableName: tableName,
Limit: limit,
ExclusiveStartKey: nextToken
},
(error, data) => {
if (error) {
reject(error);
} else {
resolve({
items: data.Items.map(item => unmarshall(item)),
nextToken: data.LastEvaluatedKey
});
}
}
);
});
}
async function deleteItem(tableName, key) {
return new Promise((resolve, reject) => {
dynamodb.deleteItem(
{
Key: marshall(key),
TableName: tableName
},
(error, data) => {
if (error) reject(error);
else resolve(data);
}
);
});
}
async function getDynamoDBTables() {
const appsync = new AWS.AppSync({
apiVersion: '2017-07-25',
region,
credentials
});
let nextToken = null;
const tables = [];
do {
const result = await new Promise((resolve, reject) => {
appsync.listDataSources(
{
apiId,
maxResults: 25,
nextToken
},
(error, data) => {
if (error) reject(error);
else resolve(data);
}
);
});
result.dataSources.forEach(({ dynamodbConfig }) => {
if (!dynamodbConfig) return;
const table = dynamodbConfig.tableName;
const isWhitelisted = Boolean(
!whiteList ||
whiteList.find(whiteListedTable => {
const regex = new RegExp(`${whiteListedTable}-`, 'gim');
return regex.test(table);
})
);
if (isWhitelisted) {
tables.push(dynamodbConfig.tableName);
console.log(`Will cleanup ${table}`);
}
});
nextToken = result.nextToken;
} while (nextToken);
return tables;
}
async function cleanTable(tableName) {
let nextToken = null;
let numUpdated = 0;
do {
const result = await getAllItems(tableName);
await Promise.all(
result.items.map(item =>
deleteItem(tableName, { id: item.id }, { updatedAt })
)
);
numUpdated += result.items.length;
nextToken = result.nextToken;
} while (nextToken);
console.log(
`deleted ${numUpdated.toLocaleString()} item/s for ${tableName}`
);
}
(async () => {
const start = new Date();
const tables = await getDynamoDBTables();
if (!tables.length) {
console.log('Nothing to clean');
return;
}
const shouldProceed = await new PromptConfirm(
'Would you like to proceed?'
).run();
if (!shouldProceed) {
console.log('Operation aborted.');
return;
}
await Promise.all(tables.map(table => cleanTable(table)));
console.log(
`Done in ${differenceInHours(start, new Date())} hours`
);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment