Trabalhar com itens expirados
Os itens expirados que estão pendentes de exclusão podem ser filtrados das operações de leitura e de gravação. Isso é útil em situações em que os dados expirados não são mais válidos e não devem ser usados. Se não forem filtrados, continuarão sendo exibidos nas operações de leitura e de gravação até serem excluídos pelo processo em segundo plano.
Esses itens ainda contam em relação aos custos de armazenamento e de leitura até serem excluídos.
As exclusões de TTL podem ser identificadas no DynamoDB Streams, mas somente na região em que a exclusão ocorreu. As exclusões de TTL que são replicadas em regiões da tabela global não podem ser identificadas nos fluxos do DynamoDB nas regiões nas quais a exclusão é replicada.
Filtrar itens expirados das operações de leitura
Em relação a operações de leitura, como Scan e Query, uma expressão de filtro pode filtrar itens expirados que estão pendentes de exclusão. Conforme mostrado no trecho de código abaixo, a expressão de filtro pode filtrar itens em que a hora de TTL é igual ou menor que a hora atual. Isso é realizado com uma declaração de atribuição que tem a hora atual como uma variável (now
), que é convertida em int
para o formato de hora de época.
- Python
-
import boto3
from datetime import datetime
def query_dynamodb_items(table_name, partition_key):
"""
:param table_name: Name of the DynamoDB table
:param partition_key:
:return:
"""
try:
# Initialize a DynamoDB resource
dynamodb = boto3.resource('dynamodb',
region_name='us-east-1')
# Specify your table
table = dynamodb.Table(table_name)
# Get the current time in epoch format
current_time = int(datetime.now().timestamp())
# Perform the query operation with a filter expression to exclude expired items
# response = table.query(
# KeyConditionExpression=boto3.dynamodb.conditions.Key('partitionKey').eq(partition_key),
# FilterExpression=boto3.dynamodb.conditions.Attr('expireAt').gt(current_time)
# )
response = table.query(
KeyConditionExpression=dynamodb.conditions.Key('partitionKey').eq(partition_key),
FilterExpression=dynamodb.conditions.Attr('expireAt').gt(current_time)
)
# Print the items that are not expired
for item in response['Items']:
print(item)
except Exception as e:
print(f"Error querying items: {e}")
# Call the function with your values
query_dynamodb_items('Music', 'your-partition-key-value')
A saída da operação de atualização mostra que, embora o horário createdAt
permaneça inalterado, os horários updatedAt
e expireAt
foram atualizados. O horário expireAt
agora está definido como noventa dias desde o momento da última atualização, que é quinta-feira, 19 de outubro de 2023, às 13:27:15.
partition_key |
createdAt |
updatedAt |
expireAt |
attribute_1 |
attribute_2 |
some_value
|
2023-07-17 14:11:05.322323 |
2023-07-19 13:27:15.213423 |
1697722035 |
new_value |
some_value |
- Javascript
-
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
async function queryDynamoDBItems(tableName, region, primaryKey) {
const client = new DynamoDBClient({
region: region,
endpoint: `https://dynamodb.${region}.amazonaws.com`
});
const currentTime = Math.floor(Date.now() / 1000);
const params = {
TableName: tableName,
KeyConditionExpression: "#pk = :pk",
FilterExpression: "#ea > :ea",
ExpressionAttributeNames: {
"#pk": "primaryKey",
"#ea": "expireAt"
},
ExpressionAttributeValues: marshall({
":pk": primaryKey,
":ea": currentTime
})
};
try {
const { Items } = await client.send(new QueryCommand(params));
Items.forEach(item => {
console.log(unmarshall(item))
});
return Items;
} catch (err) {
console.error(`Error querying items: ${err}`);
throw err;
}
}
//enter your own values here
queryDynamoDBItems('your-table-name', 'your-partition-key-value');
Gravar de modo condicional em itens expirados
Uma expressão de condição pode ser usada para evitar gravações em itens expirados. O trecho de código abaixo é uma atualização condicional que confere se o prazo de validade é maior que o horário atual. Se verdadeiro, a operação de gravação continuará.
- Python
-
import boto3
from datetime import datetime, timedelta
from botocore.exceptions import ClientError
def update_dynamodb_item(table_name, region, primary_key, sort_key, ttl_attribute):
"""
Updates an existing record in a DynamoDB table with a new or updated TTL attribute.
:param table_name: Name of the DynamoDB table
:param region: AWS Region of the table - example `us-east-1`
:param primary_key: one attribute known as the partition key.
:param sort_key: Also known as a range attribute.
:param ttl_attribute: name of the TTL attribute in the target DynamoDB table
:return:
"""
try:
dynamodb = boto3.resource('dynamodb', region_name=region)
table = dynamodb.Table(table_name)
# Generate updated TTL in epoch second format
updated_expiration_time = int((datetime.now() + timedelta(days=90)).timestamp())
# Define the update expression for adding/updating a new attribute
update_expression = "SET newAttribute = :val1"
# Define the condition expression for checking if 'ttlExpirationDate' is not expired
condition_expression = "ttlExpirationDate > :val2"
# Define the expression attribute values
expression_attribute_values = {
':val1': ttl_attribute,
':val2': updated_expiration_time
}
response = table.update_item(
Key={
'primaryKey': primary_key,
'sortKey': sort_key
},
UpdateExpression=update_expression,
ConditionExpression=condition_expression,
ExpressionAttributeValues=expression_attribute_values
)
print("Item updated successfully.")
return response['ResponseMetadata']['HTTPStatusCode'] # Ideally a 200 OK
except ClientError as e:
if e.response['Error']['Code'] == "ConditionalCheckFailedException":
print("Condition check failed: Item's 'ttlExpirationDate' is expired.")
else:
print(f"Error updating item: {e}")
except Exception as e:
print(f"Error updating item: {e}")
# replace with your values
update_dynamodb_item('your-table-name', 'us-east-1', 'your-partition-key-value', 'your-sort-key-value',
'your-ttl-attribute-value')
A saída da operação de atualização mostra que, embora o horário createdAt
permaneça inalterado, os horários updatedAt
e expireAt
foram atualizados. O horário expireAt
agora está definido como noventa dias desde o momento da última atualização, que é quinta-feira, 19 de outubro de 2023, às 13:27:15.
partition_key |
createdAt |
updatedAt |
expireAt |
attribute_1 |
attribute_2 |
some_value
|
2023-07-17 14:11:05.322323 |
2023-07-19 13:27:15.213423 |
1697722035 |
new_value |
some_value |
- Javascript
-
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";
// Example function to update an item in a DynamoDB table.
// The function should take the table name, region, partition key, sort key, and new attribute as arguments.
// The function should use the DynamoDB client to update the item.
// The function should return the updated item.
// The function should handle errors and exceptions.
const updateDynamoDBItem = async (tableName, region, partitionKey, sortKey, newAttribute) => {
const client = new DynamoDBClient({
region: region,
endpoint: `https://dynamodb.${region}.amazonaws.com`
});
const currentTime = Math.floor(Date.now() / 1000);
const params = {
TableName: tableName,
Key: marshall({
artist: partitionKey,
album: sortKey
}),
UpdateExpression: "SET newAttribute = :newAttribute",
ConditionExpression: "expireAt > :expiration",
ExpressionAttributeValues: marshall({
':newAttribute': newAttribute,
':expiration': currentTime
}),
ReturnValues: "ALL_NEW"
};
try {
const response = await client.send(new UpdateItemCommand(params));
const responseData = unmarshall(response.Attributes);
console.log("Item updated successfully: ", responseData);
return responseData;
} catch (error) {
if (error.name === "ConditionalCheckFailedException") {
console.log("Condition check failed: Item's 'expireAt' is expired.");
} else {
console.error("Error updating item: ", error);
}
throw error;
}
};
// Enter your values here
updateDynamoDBItem('your-table-name', "us-east-1",'your-partition-key-value', 'your-sort-key-value', 'your-new-attribute-value');
Identificar itens excluídos no DynamoDB Streams
O registro de fluxos contém um campo de identidade do usuário Records[<index>].userIdentity
. Os itens excluídos pelo processo do TTL têm os seguintes campos:
Records[<index>].userIdentity.type
"Service"
Records[<index>].userIdentity.principalId
"dynamodb.amazonaws.com"
O JSON a seguir mostra a parte relevante de um único registro de fluxos.
"Records": [
{
...
"userIdentity": {
"type": "Service",
"principalId": "dynamodb.amazonaws.com"
}
...
}
]