# Escrever pares chave-valor

Para criar um novo par chave-valor, ou atualizar o valor de uma chave 
específica, chame o método `put()` na sua instância KV:

```javascript
await kv.put(key, value);
```

## Exemplo

Um exemplo de escrita de um par chave-valor de dentro de uma Function:

```javascript
async function handleRequest(request) {
  const kv = new Azion.KV();

  try {
    await kv.put("primeira-chave", "Este é o valor para a chave");

    return new Response("Escrita bem-sucedida", { status: 201 });
  } catch (e) {
    return new Response(e.message, { status: 500 });
  }
}

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});
```

---

## Referência

### Método `put()`

Para criar um novo par chave-valor, ou atualizar o valor de uma chave 
específica, chame o método `put()` na sua instância KV:

```javascript
await kv.put(key, value, options?);
```

#### Parâmetros

| Parâmetro | Tipo | Descrição |
|-----------|------|-----------|
| `key` | `string` | A chave para associar ao valor. Chaves têm um comprimento máximo de 512 bytes. |
| `value` | `string` \| `object` \| `ArrayBuffer` \| `ReadableStream` | O valor a ser armazenado. O tipo é inferido. O tamanho máximo de um valor é 25 MB. |
| `options` | `object` | Opcional. Um objeto contendo os atributos `expiration`, `expirationTtl` e `metadata`. |

#### Opções

| Opção | Tipo | Descrição |
|-------|------|-----------|
| `expiration` | `number` | O número representando quando expirar o par chave-valor em segundos desde epoch. |
| `expirationTtl` | `number` | O número representando quando expirar o par chave-valor em segundos a partir de agora. O valor mínimo é 60. |
| `metadata` | `object` | Um objeto que deve ser serializável em JSON. O tamanho máximo da representação JSON serializada é 1024 bytes. |

#### Resposta

| Resposta | Tipo | Descrição |
|----------|------|-----------|
| `response` | `Promise<void>` | Uma Promise que resolve se a atualização for bem-sucedida. |

O método `put()` retorna uma Promise que você deve usar `await` para verificar 
uma atualização bem-sucedida.

---

## Orientações

### Escrevendo diferentes tipos de valores

Você pode armazenar diferentes tipos de valores:

```javascript
async function handleRequest(request) {
  const kv = new Azion.KV();

  // Armazenar um valor string
  await kv.put("nome-usuario", "John Doe");

  // Armazenar um objeto JSON (automaticamente convertido para string)
  await kv.put("dados-usuario", { id: 123, role: "admin" });

  // Armazenar um ArrayBuffer
  const encoder = new TextEncoder();
  const buffer = encoder.encode("dados binários").buffer;
  await kv.put("chave-binaria", buffer);

  // Armazenar um ReadableStream (para dados grandes)
  const stream = new ReadableStream({
    start(controller) {
      controller.enqueue(new TextEncoder().encode("dados grandes..."));
      controller.close();
    }
  });
  await kv.put("chave-stream", stream);

  return new Response("Dados armazenados", { status: 201 });
}

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});
```

### Gravações concorrentes na mesma chave

Devido à natureza eventualmente consistente do KV Store, gravações concorrentes 
na mesma chave podem acabar sobrescrevendo umas às outras. Se gravações 
concorrentes forem feitas na mesma chave, a última gravação terá precedência.

Gravações são imediatamente visíveis para outras requisições na mesma 
localização da rede global, mas podem levar até 60 segundos (ou o valor do 
parâmetro `cacheTtl` dos métodos `get()` ou `getWithMetadata()`) para serem 
visíveis em outras partes do mundo.

### Chaves com expiração

O KV Store oferece a capacidade de criar chaves que expiram automaticamente. 
Você pode configurar a expiração para ocorrer em um momento específico (usando 
a opção `expiration`), ou após um certo período de tempo desde que a chave foi 
modificada pela última vez (usando a opção `expirationTtl`).

Uma vez que o tempo de expiração de uma chave é atingido, ela será excluída do 
sistema. Após sua exclusão, tentativas de ler a chave se comportarão como se a 
chave não existisse.

:::note
Alvos de expiração que são menores que 60 segundos no futuro não são 
suportados. Isso é verdade para ambos os métodos de expiração.
:::

#### Criar chaves com expiração

Para criar chaves com expiração, defina `expiration` nas opções do `put()` como 
um número representando os segundos desde epoch, ou defina `expirationTtl` nas 
opções do `put()` como um número representando os segundos a partir de agora:

```javascript
// Expirar em um momento específico (segundos desde epoch)
await kv.put("chave-sessao", "dados-sessao", {
  expiration: Math.floor(Date.now() / 1000) + 3600 // 1 hora a partir de agora
});

// Expirar após uma duração (TTL em segundos)
await kv.put("chave-cache", "dados-cache", {
  expirationTtl: 300 // 5 minutos a partir de agora
});
```

### Metadados

Para associar metadados a um par chave-valor, defina `metadata` nas opções do 
`put()` como um objeto (serializável em JSON):

```javascript
await kv.put("perfil-usuario", JSON.stringify(dadosUsuario), {
  metadata: { 
    createdBy: "admin",
    version: 1,
    tags: ["usuario", "perfil"]
  }
});
```

Você pode recuperar esses metadados posteriormente usando o método `getWithMetadata()`.

### Limites de taxa

O KV Store tem um máximo de 1 gravação na mesma chave por segundo. Gravações 
feitas na mesma chave dentro de 1 segundo podem causar erros de limitação de taxa.

Você não deve gravar mais de uma vez por segundo na mesma chave. Considere 
consolidar suas gravações em uma chave dentro de uma invocação de Function em 
uma única gravação, ou aguarde pelo menos 1 segundo entre gravações.

### Armazenando dados grandes com streams

Para payloads grandes, use `ReadableStream` para transmitir dados de forma eficiente:

```javascript
async function handleRequest(request) {
  const kv = new Azion.KV();
  const dataSizeInKB = 500;
  const totalSize = dataSizeInKB * 1024;
  const chunkSize = 64 * 1024; // chunks de 64KB

  const stream = new ReadableStream({
    async start(controller) {
      const encoder = new TextEncoder();
      const numChunks = Math.ceil(totalSize / chunkSize);

      for (let i = 0; i < numChunks; i++) {
        const currentChunkSize = Math.min(chunkSize, totalSize - i * chunkSize);
        const chunk = "a".repeat(currentChunkSize);
        controller.enqueue(encoder.encode(chunk));
      }
      controller.close();
    },
  });

  await kv.put("arquivo-grande", stream);

  return new Response("Dados grandes armazenados", { status: 201 });
}

addEventListener("fetch", (event) => {
  event.respondWith(handleRequest(event.request));
});
```

---

## Relacionados

- [Ler pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/read/)
- [Excluir pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/delete/)
- [Visão geral da API KV Store](/pt-br/documentacao/runtime/api-reference/kv-store/)