

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Utilizzo del Time to Live in DynamoDB
<a name="TTL"></a>

Il Time to Live (TTL) per DynamoDB è un metodo conveniente per eliminare elementi che non sono più pertinenti. Il TTL consente di definire un timestamp per elemento in modo da indicare quando un elemento non è più necessario. DynamoDB elimina automaticamente gli elementi scaduti entro pochi giorni dalla data di scadenza, senza utilizzare il throughput di scrittura. 

Per utilizzare il TTL, è necessario prima abilitarlo su una tabella e poi definire un attributo specifico per archiviare il timestamp di scadenza del TTL. Il timestamp deve essere archiviato come tipo [di dati Number](HowItWorks.NamingRulesDataTypes.md#HowItWorks.DataTypes) nel [formato Unix epoch time](https://en.wikipedia.org/wiki/Unix_time) con la granularità dei secondi. Gli elementi con un attributo TTL diverso da un tipo Number vengono ignorati dal processo TTL. Ogni volta che un elemento viene creato o aggiornato, è possibile calcolare l’ora di scadenza e salvarla nell’attributo TTL.

Gli articoli con attributi TTL validi e scaduti possono essere eliminati dal sistema in qualsiasi momento, in genere entro pochi giorni dalla scadenza. È comunque possibile aggiornare gli elementi scaduti in attesa di eliminazione, come anche modificare o rimuovere i relativi attributi TTL. Durante l’aggiornamento di un elemento scaduto, si consiglia di utilizzare un’espressione condizionale per assicurarsi che l’elemento non sia stato successivamente eliminato. Utilizza le espressioni di filtro per rimuovere gli elementi scaduti dai risultati di [Scan](Scan.md#Scan.FilterExpression) e [Query](Query.FilterExpression.md).

Gli elementi eliminati funzionano in modo simile a quelli eliminati tramite le tipiche operazioni di eliminazione. Una volta eliminati, gli elementi entrano nei flussi DynamoDB come eliminazioni da parte del servizio anziché degli utenti e vengono rimossi dagli indici secondari locali e dagli indici secondari globali proprio come con le altre operazioni di eliminazione. 

Se si utilizzano le [Tabelle globali versione 2019.11.21 (Corrente)](GlobalTables.md) e si utilizza anche la funzionalità TTL, DynamoDB replica le eliminazioni TTL in tutte le tabelle di replica. L’eliminazione TTL iniziale non consuma unità di capacità di scrittura (WCU, Write Capacity Units) nella Regione in cui si verifica la scadenza del TTL. Tuttavia, l’eliminazione TTL replicata nelle tabelle di replica consuma una WCU replicata quando si utilizza la capacità con provisioning o la scrittura replicata quando si utilizza la modalità con capacità on demand in ciascuna delle Regioni di replica e verranno addebitati i costi applicabili.

Per ulteriori informazioni su TTL, consulta i seguenti argomenti:

**Topics**
+ [Abilitazione del Time to Live in DynamoDB](time-to-live-ttl-how-to.md)
+ [Calcolo del Time to Live (TTL) in DynamoDB](time-to-live-ttl-before-you-start.md)
+ [Utilizzo di elementi scaduti e Time to Live](ttl-expired-items.md)

# Abilitazione del Time to Live in DynamoDB
<a name="time-to-live-ttl-how-to"></a>

**Nota**  
Per facilitare il debug e la verifica del corretto funzionamento della funzionalità del TTL, i valori forniti per l’elemento TTL vengono registrati in testo semplice nei log di diagnostica di DynamoDB.

Puoi abilitare il TTL nella console Amazon DynamoDB AWS Command Line Interface ,AWS CLI in () o utilizzando Amazon [DynamoDB API Reference con uno qualsiasi dei presunti](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/). AWS SDKs È necessaria circa un’ora per abilitare il TTL su tutte le partizioni.

## Abilita DynamoDB TTL utilizzando la console AWS
<a name="time-to-live-ttl-how-to-enable-console"></a>

1. Accedi Console di gestione AWS e apri la console DynamoDB all'indirizzo. [https://console.aws.amazon.com/dynamodb/](https://console.aws.amazon.com/dynamodb/)

1. Scegli **Tables (Tabelle)** e quindi seleziona la tabella da modificare.

1. Nella scheda **Impostazioni aggiuntive**, nella sezione **Time to Live (TTL)** seleziona **Attiva**.

1. Quando abiliti TTL su una tabella, DynamoDB richiede di indicare un determinato nome attributo ricercato dal servizio per determinare se un item è idoneo per la scadenza. Il nome dell’attributo TTL, mostrato di seguito, fa distinzione tra maiuscole e minuscole e deve corrispondere all’attributo definito nelle operazioni di lettura e scrittura. In caso di mancata corrispondenza, gli elementi scaduti non verranno eliminati. La ridenominazione dell’attributo TTL richiede di disabilitare il TTL, per poi riabilitarlo con il nuovo attributo. Una volta disabilitato, il TTL continuerà a elaborare le eliminazioni per circa 30 minuti. Il TTL deve essere riconfigurato sulle tabelle ripristinate.  
![\[Nome dell’attributo TTL con distinzione tra maiuscole e minuscole utilizzato da DynamoDB per determinare l’idoneità di un elemento alla scadenza.\]](http://docs.aws.amazon.com/it_it/amazondynamodb/latest/developerguide/images/EnableTTL-Settings.png)

1. (Facoltativo) È possibile eseguire un test simulando la data e l’ora della scadenza con la corrispondenza di alcuni elementi. Questo fornisce un elenco di esempio di elementi e conferma che esistono elementi contenenti il nome dell’attributo TTL fornito insieme alla scadenza.

Una volta abilitato il TTL, l’attributo TTL viene contrassegnato come **TTL** quando si visualizzano gli elementi nella console DynamoDB. Puoi visualizzare la data e l'ora di scadenza di un item passando il puntatore del mouse sull'attributo. 

## Abilitazione del TTL di DynamoDB tramite l’API
<a name="time-to-live-ttl-how-to-enable-api"></a>

------
#### [ Python ]

È possibile abilitare il TTL con codice, utilizzando l'operazione. [UpdateTimeToLive](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/update_time_to_live.html)

```
import boto3


def enable_ttl(table_name, ttl_attribute_name):
    """
    Enables TTL on DynamoDB table for a given attribute name
        on success, returns a status code of 200
        on error, throws an exception

    :param table_name: Name of the DynamoDB table
    :param ttl_attribute_name: The name of the TTL attribute being provided to the table.
    """
    try:
        dynamodb = boto3.client('dynamodb')

        # Enable TTL on an existing DynamoDB table
        response = dynamodb.update_time_to_live(
            TableName=table_name,
            TimeToLiveSpecification={
                'Enabled': True,
                'AttributeName': ttl_attribute_name
            }
        )

        # In the returned response, check for a successful status code.
        if response['ResponseMetadata']['HTTPStatusCode'] == 200:
            print("TTL has been enabled successfully.")
        else:
            print(f"Failed to enable TTL, status code {response['ResponseMetadata']['HTTPStatusCode']}")
    except Exception as ex:
        print("Couldn't enable TTL in table %s. Here's why: %s" % (table_name, ex))
        raise


# your values
enable_ttl('your-table-name', 'expirationDate')
```

È possibile confermare che il TTL è abilitato utilizzando l'[DescribeTimeToLive](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb/client/describe_time_to_live.html)operazione, che descrive lo stato TTL su una tabella. Lo stato di `TimeToLive` è `ENABLED` o `DISABLED`.

```
# create a DynamoDB client
dynamodb = boto3.client('dynamodb')

# set the table name
table_name = 'YourTable'

# describe TTL
response = dynamodb.describe_time_to_live(TableName=table_name)
```

------
#### [ JavaScript ]

È possibile abilitare il TTL con codice utilizzando l'operazione. [UpdateTimeToLiveCommand](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-dynamodb/Class/UpdateTimeToLiveCommand/)

```
import { DynamoDBClient, UpdateTimeToLiveCommand } from "@aws-sdk/client-dynamodb";

const enableTTL = async (tableName, ttlAttribute) => {

    const client = new DynamoDBClient({});

    const params = {
        TableName: tableName,
        TimeToLiveSpecification: {
            Enabled: true,
            AttributeName: ttlAttribute
        }
    };

    try {
        const response = await client.send(new UpdateTimeToLiveCommand(params));
        if (response.$metadata.httpStatusCode === 200) {
            console.log(`TTL enabled successfully for table ${tableName}, using attribute name ${ttlAttribute}.`);
        } else {
            console.log(`Failed to enable TTL for table ${tableName}, response object: ${response}`);
        }
        return response;
    } catch (e) {
        console.error(`Error enabling TTL: ${e}`);
        throw e;
    }
};

// call with your own values
enableTTL('ExampleTable', 'exampleTtlAttribute');
```

------

## Abilita Time to Live utilizzando il AWS CLI
<a name="time-to-live-ttl-how-to-enable-cli-sdk"></a>

1. Abilita TTL nella tabella `TTLExample`.

   ```
   aws dynamodb update-time-to-live --table-name TTLExample --time-to-live-specification "Enabled=true, AttributeName=ttl"
   ```

1. Descrivi TTL nella tabella `TTLExample`.

   ```
   aws dynamodb describe-time-to-live --table-name TTLExample
   {
       "TimeToLiveDescription": {
           "AttributeName": "ttl",
           "TimeToLiveStatus": "ENABLED"
       }
   }
   ```

1. Aggiungi un elemento alla tabella `TTLExample` con l'attributo Time to Live (TTL) impostato usando la shell BASH e la AWS CLI. 

   ```
   EXP=`date -d '+5 days' +%s`
   aws dynamodb put-item --table-name "TTLExample" --item '{"id": {"N": "1"}, "ttl": {"N": "'$EXP'"}}'
   ```

Questo esempio inizia con la data corrente e aggiunge 5 giorni per creare un periodo di scadenza. Il periodo di scadenza viene quindi convertito nel formato temporale epoch Unix per aggiungere infine un item nella tabella `TTLExample`. 

**Nota**  
 Un modo per impostare i valori di scadenza per il Time to Live (TTL) consiste nel calcolare il numero di secondi da aggiungere al periodo di scadenza. Ad esempio, 5 giorni sono 432.000 secondi. È tuttavia in genere preferibile scegliere come punto di partenza una data.

Ottenere l'ora corrente in formato epoch Unix è piuttosto semplice, come negli esempi seguenti.
+ Terminale Linux: `date +%s`
+ Python: `import time; int(time.time())`
+ Java: `System.currentTimeMillis() / 1000L`
+ JavaScript: `Math.floor(Date.now() / 1000)`

## Abilita DynamoDB TTL utilizzando CloudFormation
<a name="time-to-live-ttl-how-to-enable-cf"></a>

```
AWSTemplateFormatVersion: "2010-09-09"
Resources:
  TTLExampleTable:
    Type: AWS::DynamoDB::Table
    Description: "A DynamoDB table with TTL Specification enabled"
    Properties:
      AttributeDefinitions:
        - AttributeName: "Album"
          AttributeType: "S"
        - AttributeName: "Artist"
          AttributeType: "S"
      KeySchema:
        - AttributeName: "Album"
          KeyType: "HASH"
        - AttributeName: "Artist"
          KeyType: "RANGE"
      ProvisionedThroughput:
        ReadCapacityUnits: "5"
        WriteCapacityUnits: "5"
      TimeToLiveSpecification:
        AttributeName: "TTLExampleAttribute"
        Enabled: true
```

[Ulteriori dettagli sull'utilizzo del TTL all'interno dei CloudFormation modelli sono disponibili qui.](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-timetolivespecification.html)

# Calcolo del Time to Live (TTL) in DynamoDB
<a name="time-to-live-ttl-before-you-start"></a>

Un modo comune per implementare il TTL consiste nell’impostare una scadenza per gli elementi in base a quando sono stati creati o aggiornati l’ultima volta. Questa operazione è fattibile aggiungendo la scadenza ai timestamp `createdAt` e `updatedAt`. Ad esempio, il TTL per gli elementi appena creati può essere impostato su `createdAt` \$1 90 giorni. Quando l’elemento viene aggiornato, il TTL può essere ricalcolato a `updatedAt` \$1 90 giorni.

La scadenza calcolata deve essere in formato epoch, in secondi. Per essere considerato valido per la scadenza e l’eliminazione, il TTL non può essere passato da più di cinque anni. Se si utilizza un altro formato, i processi TTL ignorano l'item. Se imposti l'ora di scadenza su un periodo futuro in cui desideri che l'articolo scada, l'articolo scadrà dopo tale periodo. Ad esempio, supponiamo di aver impostato l'ora di scadenza su 1724241326 (ovvero lunedì 21 agosto 2024 11:55:26 (UTC)). L'articolo scade dopo l'ora specificata. Non esiste una durata TTL minima. È possibile impostare l'ora di scadenza su qualsiasi ora futura, ad esempio a 5 minuti dall'ora corrente. Tuttavia, DynamoDB in genere elimina gli articoli scaduti entro 48 ore dalla data di scadenza, non immediatamente dopo la scadenza dell'articolo.

**Topics**
+ [Creazione di un oggetto e impostazione del Time to Live](#time-to-live-ttl-before-you-start-create)
+ [Aggiornamento di un elemento e del Time to Live](#time-to-live-ttl-before-you-start-update)

## Creazione di un oggetto e impostazione del Time to Live
<a name="time-to-live-ttl-before-you-start-create"></a>

L’esempio seguente mostra come calcolare la scadenza durante la creazione di un nuovo elemento, utilizzando `expireAt` come nome dell’attributo TTL. Un’istruzione di assegnazione ottiene il momento corrente come variabile. Nell’esempio, la scadenza viene calcolata come a 90 giorni dal momento corrente. La scadenza viene quindi convertita in formato epoch e salvata come tipo di dati intero nell’attributo TTL.

Gli esempi di codice seguenti mostrano come creare un elemento con un valore TTL.

------
#### [ Java ]

**SDK per Java 2.x**  

```
package com.amazon.samplelib.ttl;

import com.amazon.samplelib.CodeSampleUtils;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.PutItemRequest;
import software.amazon.awssdk.services.dynamodb.model.PutItemResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * Creates an item in a DynamoDB table with TTL attributes.
 * This class demonstrates how to add TTL expiration timestamps to DynamoDB items.
 */
public class CreateTTL {

    private static final String USAGE =
        """
            Usage:
                <tableName> <primaryKey> <sortKey> <region>
            Where:
                tableName - The Amazon DynamoDB table being queried.
                primaryKey - The name of the primary key. Also known as the hash or partition key.
                sortKey - The name of the sort key. Also known as the range attribute.
                region (optional) - The AWS region that the Amazon DynamoDB table is located in. (Default: us-east-1)
            """;
    private static final int DAYS_TO_EXPIRE = 90;
    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
    private static final String PRIMARY_KEY_ATTR = "primaryKey";
    private static final String SORT_KEY_ATTR = "sortKey";
    private static final String CREATION_DATE_ATTR = "creationDate";
    private static final String EXPIRE_AT_ATTR = "expireAt";
    private static final String SUCCESS_MESSAGE = "%s PutItem operation with TTL successful.";
    private static final String TABLE_NOT_FOUND_ERROR = "Error: The Amazon DynamoDB table \"%s\" can't be found.";

    private final DynamoDbClient dynamoDbClient;

    /**
     * Constructs a CreateTTL instance with the specified DynamoDB client.
     *
     * @param dynamoDbClient The DynamoDB client to use
     */
    public CreateTTL(final DynamoDbClient dynamoDbClient) {
        this.dynamoDbClient = dynamoDbClient;
    }

    /**
     * Constructs a CreateTTL with a default DynamoDB client.
     */
    public CreateTTL() {
        this.dynamoDbClient = null;
    }

    /**
     * Main method to demonstrate creating an item with TTL.
     *
     * @param args Command line arguments
     */
    public static void main(final String[] args) {
        try {
            int result = new CreateTTL().processArgs(args);
            System.exit(result);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

    /**
     * Process command line arguments and create an item with TTL.
     *
     * @param args Command line arguments
     * @return 0 if successful, non-zero otherwise
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     * @throws IllegalArgumentException If arguments are invalid
     */
    public int processArgs(final String[] args) {
        // Argument validation (remove or replace this line when reusing this code)
        CodeSampleUtils.validateArgs(args, new int[] {3, 4}, USAGE);

        final String tableName = args[0];
        final String primaryKey = args[1];
        final String sortKey = args[2];
        final Region region = Optional.ofNullable(args.length > 3 ? args[3] : null)
            .map(Region::of)
            .orElse(Region.US_EAST_1);

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final CreateTTL createTTL = new CreateTTL(ddb);
            createTTL.createItemWithTTL(tableName, primaryKey, sortKey);
            return 0;
        } catch (Exception e) {
            throw e;
        }
    }

    /**
     * Creates an item in the specified table with TTL attributes.
     *
     * @param tableName The name of the table
     * @param primaryKeyValue The value for the primary key
     * @param sortKeyValue The value for the sort key
     * @return The response from the PutItem operation
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     */
    public PutItemResponse createItemWithTTL(
        final String tableName, final String primaryKeyValue, final String sortKeyValue) {
        // Get current time in epoch second format
        final long createDate = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = createDate + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        final Map<String, AttributeValue> itemMap = new HashMap<>();
        itemMap.put(
            PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKeyValue).build());
        itemMap.put(SORT_KEY_ATTR, AttributeValue.builder().s(sortKeyValue).build());
        itemMap.put(
            CREATION_DATE_ATTR,
            AttributeValue.builder().n(String.valueOf(createDate)).build());
        itemMap.put(
            EXPIRE_AT_ATTR,
            AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final PutItemRequest request =
            PutItemRequest.builder().tableName(tableName).item(itemMap).build();

        try {
            final PutItemResponse response = dynamoDbClient.putItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return response;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
}
```
+  *Per i dettagli sull'API, consulta la sezione API Reference. [PutItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/PutItem)AWS SDK for Java 2.x * 

------
#### [ JavaScript ]

**SDK per JavaScript (v3)**  

```
import { DynamoDBClient, PutItemCommand } from "@aws-sdk/client-dynamodb";

export function createDynamoDBItem(table_name, region, partition_key, sort_key) {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    // Get the current time in epoch second format
    const current_time = Math.floor(new Date().getTime() / 1000);

    // Calculate the expireAt time (90 days from now) in epoch second format
    const expire_at = Math.floor((new Date().getTime() + 90 * 24 * 60 * 60 * 1000) / 1000);

    // Create DynamoDB item
    const item = {
        'partitionKey': {'S': partition_key},
        'sortKey': {'S': sort_key},
        'createdAt': {'N': current_time.toString()},
        'expireAt': {'N': expire_at.toString()}
    };

    const putItemCommand = new PutItemCommand({
        TableName: table_name,
        Item: item,
        ProvisionedThroughput: {
            ReadCapacityUnits: 1,
            WriteCapacityUnits: 1,
        },
    });

    client.send(putItemCommand, function(err, data) {
        if (err) {
            console.log("Exception encountered when creating item %s, here's what happened: ", data, err);
            throw err;
        } else {
            console.log("Item created successfully: %s.", data);
            return data;
        }
    });
}

// Example usage (commented out for testing)
// createDynamoDBItem('your-table-name', 'us-east-1', 'your-partition-key-value', 'your-sort-key-value');
```
+  Per i dettagli sull'API, consulta la sezione *AWS SDK per JavaScript API [PutItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/PutItemCommand)Reference*. 

------
#### [ Python ]

**SDK per Python (Boto3)**  

```
from datetime import datetime, timedelta

import boto3


def create_dynamodb_item(table_name, region, primary_key, sort_key):
    """
    Creates a DynamoDB item with an attached expiry attribute.

    :param table_name: Table name for the boto3 resource to target when creating an item
    :param region: string representing the AWS region. Example: `us-east-1`
    :param primary_key: one attribute known as the partition key.
    :param sort_key: Also known as a range attribute.
    :return: Void (nothing)
    """
    try:
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Get the current time in epoch second format
        current_time = int(datetime.now().timestamp())

        # Calculate the expiration time (90 days from now) in epoch second format
        expiration_time = int((datetime.now() + timedelta(days=90)).timestamp())

        item = {
            "primaryKey": primary_key,
            "sortKey": sort_key,
            "creationDate": current_time,
            "expireAt": expiration_time,
        }
        response = table.put_item(Item=item)

        print("Item created successfully.")
        return response
    except Exception as e:
        print(f"Error creating item: {e}")
        raise e


# Use your own values
create_dynamodb_item(
    "your-table-name", "us-west-2", "your-partition-key-value", "your-sort-key-value"
)
```
+  Per i dettagli sull'API, consulta [PutItem AWS](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/PutItem)*SDK for Python (Boto3) API Reference*. 

------

## Aggiornamento di un elemento e del Time to Live
<a name="time-to-live-ttl-before-you-start-update"></a>

Questo esempio è una continuazione di quello della sezione [precedente](#time-to-live-ttl-before-you-start-create). La scadenza può essere ricalcolata se l’elemento viene aggiornato. L’esempio seguente ricalcola il timestamp `expireAt` in modo che corrisponda a 90 giorni dal momento corrente.

Gli esempi di codice seguenti mostrano come aggiornare il valore TTL di un elemento.

------
#### [ Java ]

**SDK per Java 2.x**  
Aggiorna il TTL di un elemento DynamoDB esistente in una tabella.  

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

    public UpdateItemResponse updateItemWithTTL(
        final String tableName, final String primaryKeyValue, final String sortKeyValue) {
        // Get current time in epoch second format
        final long currentTime = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = currentTime + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        // Create the key map for the item to update
        final Map<String, AttributeValue> keyMap = new HashMap<>();
        keyMap.put(PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKeyValue).build());
        keyMap.put(SORT_KEY_ATTR, AttributeValue.builder().s(sortKeyValue).build());

        // Create the expression attribute values
        final Map<String, AttributeValue> expressionAttributeValues = new HashMap<>();
        expressionAttributeValues.put(
            ":c", AttributeValue.builder().n(String.valueOf(currentTime)).build());
        expressionAttributeValues.put(
            ":e", AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final UpdateItemRequest request = UpdateItemRequest.builder()
            .tableName(tableName)
            .key(keyMap)
            .updateExpression(UPDATE_EXPRESSION)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try {
            final UpdateItemResponse response = dynamoDbClient.updateItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return response;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
```
+  *Per i dettagli sulle API, consulta [UpdateItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)la sezione API Reference.AWS SDK for Java 2.x * 

------
#### [ JavaScript ]

**SDK per JavaScript (v3)**  

```
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const updateItem = async (tableName, partitionKey, sortKey, region = 'us-east-1') => {
    const client = new DynamoDBClient({
        region: region,
        endpoint: `https://dynamodb.${region}.amazonaws.com`
    });

    const currentTime = Math.floor(Date.now() / 1000);
    const expireAt = Math.floor((Date.now() + 90 * 24 * 60 * 60 * 1000) / 1000);

    const params = {
        TableName: tableName,
        Key: marshall({
            partitionKey: partitionKey,
            sortKey: sortKey
        }),
        UpdateExpression: "SET updatedAt = :c, expireAt = :e",
        ExpressionAttributeValues: marshall({
            ":c": currentTime,
            ":e": expireAt
        }),
    };

    try {
        const data = await client.send(new UpdateItemCommand(params));
        const responseData = unmarshall(data.Attributes);
        console.log("Item updated successfully: %s", responseData);
        return responseData;
    } catch (err) {
        console.error("Error updating item:", err);
        throw err;
    }
}

// Example usage (commented out for testing)
// updateItem('your-table-name', 'your-partition-key-value', 'your-sort-key-value');
```
+  Per i dettagli sull'API, consulta la sezione *AWS SDK per JavaScript API [UpdateItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/UpdateItemCommand)Reference*. 

------
#### [ Python ]

**SDK per Python (Boto3)**  

```
from datetime import datetime, timedelta

import boto3


def update_dynamodb_item(table_name, region, primary_key, sort_key):
    """
    Update an existing DynamoDB item with a TTL.
    :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.
    :return: Void (nothing)
    """
    try:
        # Create the DynamoDB resource.
        dynamodb = boto3.resource("dynamodb", region_name=region)
        table = dynamodb.Table(table_name)

        # Get the current time in epoch second format
        current_time = int(datetime.now().timestamp())

        # Calculate the expireAt time (90 days from now) in epoch second format
        expire_at = int((datetime.now() + timedelta(days=90)).timestamp())

        table.update_item(
            Key={"partitionKey": primary_key, "sortKey": sort_key},
            UpdateExpression="set updatedAt=:c, expireAt=:e",
            ExpressionAttributeValues={":c": current_time, ":e": expire_at},
        )

        print("Item updated successfully.")
    except Exception as e:
        print(f"Error updating item: {e}")


# Replace with your own values
update_dynamodb_item(
    "your-table-name", "us-west-2", "your-partition-key-value", "your-sort-key-value"
)
```
+  Per i dettagli sull'API, consulta [UpdateItem AWS](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/UpdateItem)*SDK for Python (Boto3) API Reference*. 

------

Gli esempi del TTL discussi in questa introduzione dimostrano un metodo per garantire che in una tabella vengano conservati solo gli elementi aggiornati di recente. Gli elementi aggiornati hanno una durata prolungata, mentre gli elementi non aggiornati dopo la creazione scadono e vengono eliminati gratuitamente, liberando spazio di archiviazione e mantenendo le tabelle pulite.

# Utilizzo di elementi scaduti e Time to Live
<a name="ttl-expired-items"></a>

Gli elementi scaduti in attesa di eliminazione possono essere filtrati dalle operazioni di lettura e scrittura. Ciò è utile negli scenari in cui i dati scaduti non sono più validi e non devono essere utilizzati. Se non vengono filtrati, continueranno a essere visualizzati nelle operazioni di lettura e scrittura finché non verranno eliminati dal processo in background.

**Nota**  
Questi elementi continuano a essere conteggiati ai fini dei costi di archiviazione e lettura fino a quando non vengono eliminati.

Le eliminazioni TTL possono essere identificate nei flussi DynamoDB, ma solo nella Regione in cui è avvenuta l’eliminazione. Le eliminazioni TTL che vengono replicate nelle aree della tabella globale non sono identificabili nei flussi DynamoDB nelle aree in cui viene replicata l’eliminazione.

## Filtraggio di elementi scaduti dalle operazioni di lettura
<a name="ttl-expired-items-filter"></a>

Per operazioni di lettura come [Scan](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html) e [Query](https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Query.html), un’espressione di filtro può filtrare gli elementi scaduti in attesa di eliminazione. Come illustrato nel seguente frammento di codice, l’espressione di filtro può filtrare gli elementi in cui il TTL è uguale o inferiore al momento corrente. Ad esempio, il codice dell’SDK per Python include un’istruzione di assegnazione che ottiene il momento corrente come variabile (`now`) e la converte in `int` per il formato ora epoch.

Gli esempi di codice seguenti mostrano come eseguire query su elementi TTL.

------
#### [ Java ]

**SDK per Java 2.x**  
Interroga l'espressione filtrata per raccogliere elementi TTL in una tabella DynamoDB utilizzando. AWS SDK for Java 2.x  

```
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.QueryRequest;
import software.amazon.awssdk.services.dynamodb.model.QueryResponse;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;

import java.util.Map;
import java.util.Optional;

        final QueryRequest request = QueryRequest.builder()
            .tableName(tableName)
            .keyConditionExpression(KEY_CONDITION_EXPRESSION)
            .filterExpression(FILTER_EXPRESSION)
            .expressionAttributeNames(expressionAttributeNames)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final QueryResponse response = ddb.query(request);
            System.out.println("Query successful. Found " + response.count() + " items that have not expired yet.");

            // Print each item
            response.items().forEach(item -> {
                System.out.println("Item: " + item);
            });

            return 0;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
```
+  Per informazioni dettagliate sull’API, consulta [Query](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/Query) nella *documentazione di riferimento dell’API AWS SDK for Java 2.x *. 

------
#### [ JavaScript ]

**SDK per (v3) JavaScript **  
Interroga l'espressione filtrata per raccogliere elementi TTL in una tabella DynamoDB utilizzando. AWS SDK per JavaScript  

```
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const queryFiltered = async (tableName, primaryKey, region = 'us-east-1') => {
    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;
    }
}

// Example usage (commented out for testing)
// queryFiltered('your-table-name', 'your-partition-key-value');
```
+  Per informazioni dettagliate sull’API, consulta [Query](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/QueryCommand) nella *documentazione di riferimento dell’API AWS SDK per JavaScript *. 

------
#### [ Python ]

**SDK per Python (Boto3)**  
Interroga l'espressione filtrata per raccogliere elementi TTL in una tabella DynamoDB utilizzando. AWS SDK per Python (Boto3)  

```
from datetime import datetime

import boto3


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")
```
+  Per informazioni dettagliate sull’API, consulta [Query](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/Query) nella *documentazione di riferimento dell’API SDK for Python (Boto3)AWS *. 

------

## Scrittura in base a una condizione su elementi scaduti
<a name="ttl-expired-items-conditional-write"></a>

È possibile utilizzare un’espressione condizionale per evitare scritture su elementi scaduti. Il frammento di codice riportato di seguito è un aggiornamento condizionale che verifica se la scadenza è posteriore al momento corrente. Se true, l’operazione di scrittura continuerà.

Gli esempi di codice seguenti mostrano come aggiornare in modo condizionale il valore TTL di un elemento.

------
#### [ Java ]

**SDK per Java 2.x**  
Aggiorna il TTL di un elemento DynamoDB esistente in una tabella con una condizione.  

```
package com.amazon.samplelib.ttl;

import com.amazon.samplelib.CodeSampleUtils;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;
import software.amazon.awssdk.services.dynamodb.model.ConditionalCheckFailedException;
import software.amazon.awssdk.services.dynamodb.model.DynamoDbException;
import software.amazon.awssdk.services.dynamodb.model.ResourceNotFoundException;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemRequest;
import software.amazon.awssdk.services.dynamodb.model.UpdateItemResponse;

import java.util.Map;
import java.util.Optional;

/**
 * Updates an item in a DynamoDB table with TTL attributes using a conditional expression.
 * This class demonstrates how to conditionally update TTL expiration timestamps.
 */
public class UpdateTTLConditional {

    private static final String USAGE =
        """
            Usage:
                <tableName> <primaryKey> <sortKey> <region>
            Where:
                tableName - The Amazon DynamoDB table being queried.
                primaryKey - The name of the primary key. Also known as the hash or partition key.
                sortKey - The name of the sort key. Also known as the range attribute.
                region (optional) - The AWS region that the Amazon DynamoDB table is located in. (Default: us-east-1)
            """;
    private static final int DAYS_TO_EXPIRE = 90;
    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
    private static final String PRIMARY_KEY_ATTR = "primaryKey";
    private static final String SORT_KEY_ATTR = "sortKey";
    private static final String UPDATED_AT_ATTR = "updatedAt";
    private static final String EXPIRE_AT_ATTR = "expireAt";
    private static final String UPDATE_EXPRESSION = "SET " + UPDATED_AT_ATTR + "=:c, " + EXPIRE_AT_ATTR + "=:e";
    private static final String CONDITION_EXPRESSION = "attribute_exists(" + PRIMARY_KEY_ATTR + ")";
    private static final String SUCCESS_MESSAGE = "%s UpdateItem operation with TTL successful.";
    private static final String CONDITION_FAILED_MESSAGE = "Condition check failed. Item does not exist.";
    private static final String TABLE_NOT_FOUND_ERROR = "Error: The Amazon DynamoDB table \"%s\" can't be found.";

    private final DynamoDbClient dynamoDbClient;

    /**
     * Constructs an UpdateTTLConditional with a default DynamoDB client.
     */
    public UpdateTTLConditional() {
        this.dynamoDbClient = null;
    }

    /**
     * Constructs an UpdateTTLConditional with the specified DynamoDB client.
     *
     * @param dynamoDbClient The DynamoDB client to use
     */
    public UpdateTTLConditional(final DynamoDbClient dynamoDbClient) {
        this.dynamoDbClient = dynamoDbClient;
    }

    /**
     * Main method to demonstrate conditionally updating an item with TTL.
     *
     * @param args Command line arguments
     */
    public static void main(final String[] args) {
        try {
            int result = new UpdateTTLConditional().processArgs(args);
            System.exit(result);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            System.exit(1);
        }
    }

    /**
     * Process command line arguments and conditionally update an item with TTL.
     *
     * @param args Command line arguments
     * @return 0 if successful, non-zero otherwise
     * @throws ResourceNotFoundException If the table doesn't exist
     * @throws DynamoDbException If an error occurs during the operation
     * @throws IllegalArgumentException If arguments are invalid
     */
    public int processArgs(final String[] args) {
        // Argument validation (remove or replace this line when reusing this code)
        CodeSampleUtils.validateArgs(args, new int[] {3, 4}, USAGE);

        final String tableName = args[0];
        final String primaryKey = args[1];
        final String sortKey = args[2];
        final Region region = Optional.ofNullable(args.length > 3 ? args[3] : null)
            .map(Region::of)
            .orElse(Region.US_EAST_1);

        // Get current time in epoch second format
        final long currentTime = System.currentTimeMillis() / 1000;

        // Calculate expiration time 90 days from now in epoch second format
        final long expireDate = currentTime + (DAYS_TO_EXPIRE * SECONDS_PER_DAY);

        // Create the key map for the item to update
        final Map<String, AttributeValue> keyMap = Map.of(
            PRIMARY_KEY_ATTR, AttributeValue.builder().s(primaryKey).build(),
            SORT_KEY_ATTR, AttributeValue.builder().s(sortKey).build());

        // Create the expression attribute values
        final Map<String, AttributeValue> expressionAttributeValues = Map.of(
            ":c", AttributeValue.builder().n(String.valueOf(currentTime)).build(),
            ":e", AttributeValue.builder().n(String.valueOf(expireDate)).build());

        final UpdateItemRequest request = UpdateItemRequest.builder()
            .tableName(tableName)
            .key(keyMap)
            .updateExpression(UPDATE_EXPRESSION)
            .conditionExpression(CONDITION_EXPRESSION)
            .expressionAttributeValues(expressionAttributeValues)
            .build();

        try (DynamoDbClient ddb = dynamoDbClient != null
            ? dynamoDbClient
            : DynamoDbClient.builder().region(region).build()) {
            final UpdateItemResponse response = ddb.updateItem(request);
            System.out.println(String.format(SUCCESS_MESSAGE, tableName));
            return 0;
        } catch (ConditionalCheckFailedException e) {
            System.err.println(CONDITION_FAILED_MESSAGE);
            throw e;
        } catch (ResourceNotFoundException e) {
            System.err.format(TABLE_NOT_FOUND_ERROR, tableName);
            throw e;
        } catch (DynamoDbException e) {
            System.err.println(e.getMessage());
            throw e;
        }
    }
}
```
+  *Per i dettagli sulle API, consulta [UpdateItem](https://docs.aws.amazon.com/goto/SdkForJavaV2/dynamodb-2012-08-10/UpdateItem)la sezione API Reference.AWS SDK for Java 2.x * 

------
#### [ JavaScript ]

**SDK per JavaScript (v3)**  
Aggiorna il TTL di un elemento DynamoDB esistente in una tabella con una condizione.  

```
import { DynamoDBClient, UpdateItemCommand } from "@aws-sdk/client-dynamodb";
import { marshall, unmarshall } from "@aws-sdk/util-dynamodb";

export const updateItemConditional = async (tableName, partitionKey, sortKey, region = 'us-east-1', newAttribute = 'default-value') => {
    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;
    }
};

// Example usage (commented out for testing)
// updateItemConditional('your-table-name', 'your-partition-key-value', 'your-sort-key-value');
```
+  Per i dettagli sull'API, consulta la sezione *AWS SDK per JavaScript API [UpdateItem](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/dynamodb/command/UpdateItemCommand)Reference*. 

------
#### [ Python ]

**SDK per Python (Boto3)**  
Aggiorna il TTL di un elemento DynamoDB esistente in una tabella con una condizione.  

```
from datetime import datetime, timedelta

import boto3
from botocore.exceptions import ClientError


def update_dynamodb_item_ttl(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 'expireAt' is not expired
        condition_expression = "expireAt > :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 'expireAt' 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_ttl(
    "your-table-name",
    "us-east-1",
    "your-partition-key-value",
    "your-sort-key-value",
    "your-ttl-attribute-value",
)
```
+  Per i dettagli sull'API, consulta [UpdateItem AWS](https://docs.aws.amazon.com/goto/boto3/dynamodb-2012-08-10/UpdateItem)*SDK for Python (Boto3) API Reference*. 

------

## Identificazione degli elementi eliminati nei flussi DynamoDB
<a name="ttl-expired-items-identifying"></a>

Il record Streams contiene un campo di identità utente `Records[<index>].userIdentity`. Gli elementi eliminati dal processo TTL hanno i seguenti campi:

```
Records[<index>].userIdentity.type
"Service"

Records[<index>].userIdentity.principalId
"dynamodb.amazonaws.com"
```

Il JSON seguente mostra la porzione rilevante di un singolo record di flussi:

```
"Records": [ 
  { 
	... 
		"userIdentity": {
		"type": "Service", 
      	"principalId": "dynamodb.amazonaws.com" 
   	} 
   ... 
	} 
]
```