From a296930217927c2c09cfce484ceb13368c058d4c Mon Sep 17 00:00:00 2001 From: Luiza Vargas do Santos Date: Thu, 28 Aug 2025 12:30:48 -0300 Subject: [PATCH 01/11] feat: added kv store reference --- .../en/pages/guides/kv-store/manage-data.mdx | 84 ++++++++++++ .../reference/store/kv-store/kv-store.mdx | 127 ++++++++++++++++++ .../referencia/store/kv-store/kv-store.mdx | 121 +++++++++++++++++ 3 files changed, 332 insertions(+) create mode 100644 src/content/docs/en/pages/guides/kv-store/manage-data.mdx create mode 100644 src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx create mode 100644 src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx diff --git a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx new file mode 100644 index 0000000000..916ea16d2e --- /dev/null +++ b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx @@ -0,0 +1,84 @@ +--- +title: How to manage KV Store with Edge Functions +description: >- + +meta_tags: 'edge sql, storage, cloud, SQL, sqlite, data' +namespace: documentation_products_kv_store_manage_edge_functions +permalink: /documentation/products/guides/kv-store/manage-with-functions/ +--- + +import LinkButton from 'azion-webkit/linkbutton' + +See how to retrieve data from a with KV Store and Edge Functions. + + + +--- + +## Requirements + +- [Azion Edge Functions enabled](/en/documentation/products/build/edge-application/edge-functions/). +--- + +## Creating a kv +: +--- + +## Creating an edge function to communicate with KV Store + +1. Access [Azion Console](https://console.azion.com). +2. On the upper-left corner, select **Edge Functions** in the **Edge Libraries** section. +3. Click the **+ Edge Function** button. +4. Choose a name for your function. +5. Delete the placeholder function that is inside the code editor. +6. Paste the following code: + +```js +import { Database } from "azion:sql"; + +async function db_query() { + let connection = await Database.open("mydatabase"); + let rows = await connection.query("select * from users"); + let column_count = rows.columnCount(); + let column_names = []; + for (let i = 0; i < column_count; i++) { + column_names.push(rows.columnName(i)); + } + let response_lines = []; + response_lines.push(column_names.join("|")); + let row = await rows.next(); + while (row) { + let row_items = []; + for (let i = 0; i < column_count; i++) { + row_items.push(row.getString(i)); + } + response_lines.push(row_items.join("|")); + row = await rows.next(); + } + const response_text = response_lines.join("\n"); + return response_text; +} + +async function handle_request(request) { + if (request.method != "GET") { + return new Response("Method not allowed", { status: 405 }); + } + try { + return new Response(await db_query()); + } catch (e) { + console.log(e.message, e.stack); + return new Response(e.message, { status: 500 }); + } +} + +addEventListener("fetch", (event) => + event.respondWith(handle_request(event.request)) +); +``` + + + + + + + diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx new file mode 100644 index 0000000000..5e445d78f8 --- /dev/null +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -0,0 +1,127 @@ +--- +title: KV Store +description: >- + +meta_tags: 'kv, storage, key, distributed, queries' +namespace: docs_edge_sql +permalink: /documentation/products/store/kv-store/ +--- + +import Tag from 'primevue/tag' +import LinkButton from 'azion-webkit/linkbutton' + + + Preview + + + +## Overview + +KV Store is a distributed key–value storage service that runs across Azion’s edge network. It lets you persist and retrieve small pieces of data with very low latency from anywhere your users are, without managing servers. + +Typical use cases include: + +- Session and authentication tokens +- User preferences and personalization +- Caching API responses and computed fragments +- Rate-limit counters and idempotency keys +- Shopping cart or draft state + +--- + +## How it works + +- Data is organized into namespaces that contain independent sets of keys. +- Each item is addressed by a key that is unique within its namespace. +- Values can be stored as text, JSON, or binary/streaming payloads. +- Data is replicated across Azion edge nodes to maximize availability and read performance. +- Single-key operations are atomic per key. Multi-key transactions are not supported. + +--- + +## Implementation resources + + +| Scope | Resource | +| ----- | -------- | +| Manage KV store with Edge Functions | [How to manage KV store with Edge Functions](/en/documentation/products/guides/kv-store/manage-with-functions/) | +| xxx [How to xxxxx](xxxxxx/) | +--- + +## Business rules + + + +--- + +## Data resilience + +KV Store uses a distributed architecture with replication across Azion edge nodes. New writes are accepted at the edge and propagated to replicas to ensure durability and high availability. Reads are served from the closest healthy replica to minimize latency. + +--- + +## Namespaces + +A namespace is an isolated key space. Use namespaces to segment data by application, environment, or workload. + +Recommended patterns: + +- Separate namespaces for production and staging. +- Prefix keys to model hierarchy, for example: users/123/profile, flags/new-ui, carts/region-br/user-42. +- Keep keys short and meaningful; prefer a few path-like segments over long opaque identifiers. + +Naming: + +- Names must be unique within your account. +- Use lowercase letters, numbers, dashes, and underscores. + +--- + + +## Interacting with KV Store via Edge Functions + +(Create, Read, Update, Delete) +The examples below illustrate common patterns. + + +```js +const aqui=1 +``` + +--- + +## Methods + +- put(namespace, key, value, options?) + - value: string | object (JSON) | ArrayBuffer | ReadableStream + - options: { metadata?: object, contentType?: string } + - returns: void +- get(namespace, key, options?) + - options: { type: 'text' | 'json' | 'arrayBuffer' | 'stream' } + - returns: string | object | ArrayBuffer | ReadableStream +- delete(namespace, key) + - returns: void + + +--- + +## Limits + +These are the **default limits**: + +- Per-key write rate: up to 1 write per second to the same key. +- Key size: up to 512 bytes (UTF‑8). +- Metadata size: up to 1024 bytes (JSON-serialized). +- Value size: up to 25 MB per item. + + +These are the **default limits** for each Service Plan: + +| Scope | Developer | Business | Enterprise | Mission Critical | +| ----- | --------- | -------- | ---------- | ---------------- | +| Namespaces | 10 | 50 | 200 | 200 | +| Maximum file size | 200 MB | 500 MB | 2 GB | 2 GB | +| Maximum storage per account | 5 GB | 50 GB | 300 GB | 300 GB | + + +--- diff --git a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx new file mode 100644 index 0000000000..c62f970ccd --- /dev/null +++ b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx @@ -0,0 +1,121 @@ +--- +title: KV Store +description: >- + +meta_tags: 'kv, armazenamento, chave, distribuído, consultas' +namespace: docs_edge_sql +permalink: /documentacao/produtos/store/kv-store/ +--- + +import Tag from 'primevue/tag' +import LinkButton from 'azion-webkit/linkbutton' + + + Previsualização + + + +## Visão Geral + +KV Store é um serviço de armazenamento de chave-valor distribuído que opera em toda a rede de borda da Azion. Ele permite que você persista e recupere pequenos pedaços de dados com muito baixa latência de qualquer lugar onde seus usuários estejam, sem precisar gerenciar servidores. + +Casos de uso típicos incluem: + +- Sessões e tokens de autenticação +- Sinalizadores de recurso e agrupamentos de A/B testing +- Preferências de usuário e personalização +- Cache de respostas de API e fragmentos computados +- Contadores de limite de taxa e chaves de idempotência +- Estado do carrinho de compras ou rascunho + +--- + +## Como funciona + +- Os dados são organizados em namespaces que contêm conjuntos independentes de chaves. +- Cada item é endereçado por uma chave que é única dentro de seu namespace. +- Os valores podem ser armazenados como texto, JSON ou cargas úteis binárias/em fluxo. +- Os dados são replicados entre pronomes de borda da Azion para maximizar a disponibilidade e o desempenho de leitura. +- Operações de chave única são atômicas por chave. Transações de múltiplas chaves não são suportadas. + +--- + +## Recursos de Implementação + +| Âmbito | Recurso | +| ----- | -------- | +| Gerenciar KV store com Edge Functions | [Como gerenciar KV store com Edge Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/) | +| xxx [Como xxxxx](xxxxxx/) | +--- + +## Regras de Negócio + +## Resiliência de Dados + +KV Store usa uma arquitetura distribuída com replicação entre pronomes de borda da Azion. Novas gravações são aceitas na borda e propagadas para réplicas para garantir durabilidade e alta disponibilidade. Leituras são servidas da réplica saudável mais próxima para minimizar a latência. + + +--- + +## Namespaces + +Um namespace é um espaço de chave isolado. Use namespaces para segmentar dados por aplicação, ambiente ou carga de trabalho. + +Padrões recomendados: + +- Namespaces separados para produção e staging. +- Prefixe chaves para modelar hierarquia, por exemplo: users/123/profile, flags/new-ui, carts/region-br/user-42. +- Mantenha as chaves curtas e significativas; prefira alguns segmentos do tipo caminho em vez de longos identificadores opacos. + +Nomenclatura: + +- Os nomes devem ser únicos dentro da sua conta. +- Use letras minúsculas, números, hifens e sublinhados. + +--- + +## Interação com KV Store via Edge Functions + +Os exemplos abaixo ilustram padrões comuns. + +```js +const aqui=1 +``` + +--- + +## Métodos + +- put(namespace, key, value, options?) + - value: string | object (JSON) | ArrayBuffer | ReadableStream + - options: { metadata?: object, contentType?: string } + - returns: void +- get(namespace, key, options?) + - options: { type: 'text' | 'json' | 'arrayBuffer' | 'stream' } + - returns: string | object | ArrayBuffer | ReadableStream +- delete(namespace, key) + - returns: void + + + +--- + +## Limites + +Estes são os **limites padrão**: + +- Taxa de gravação por chave: até 1 gravação por segundo para a mesma chave. +- Tamanho da chave: até 512 bytes (UTF-8). +- Tamanho dos metadados: até 1024 bytes (JSON-serializado). +- Tamanho do valor: até 25 MB por item. + + +Estes são os **limites padrão** para cada Plano de Serviço: + +| Âmbito | Desenvolvedor | Negócios | Empresarial | Missão Crítica | +| ----- | --------- | -------- | ---------- | ---------------- | +| Namespaces | 10 | 50 | 200 | 200 | +| Tamanho máximo do arquivo | 200 MB | 500 MB | 2 GB | 2 GB | +| Armazenamento máximo por conta | 5 GB | 50 GB | 300 GB | 300 GB | + +--- From dadc805d6bb7cd73ee4b8bd048418dc6a8401537 Mon Sep 17 00:00:00 2001 From: Vitor Eltz <107409234+VitorAEltz@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:27:07 -0300 Subject: [PATCH 02/11] Apply suggestion from @MarianaReisAlcantara Co-authored-by: MarianaReisAlcantara --- src/content/docs/en/pages/guides/kv-store/manage-data.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx index 916ea16d2e..a198db3937 100644 --- a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx +++ b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx @@ -1,5 +1,5 @@ --- -title: How to manage KV Store with Edge Functions +title: How to manage KV Store with Functions description: >- meta_tags: 'edge sql, storage, cloud, SQL, sqlite, data' From 0eb64ba75da4d03740064b85d0e67d183899a91f Mon Sep 17 00:00:00 2001 From: Vitor Eltz <107409234+VitorAEltz@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:34:53 -0300 Subject: [PATCH 03/11] Apply suggestions from code review Co-authored-by: MarianaReisAlcantara --- .../en/pages/guides/kv-store/manage-data.mdx | 6 +++--- .../reference/store/kv-store/kv-store.mdx | 4 ++-- .../referencia/store/kv-store/kv-store.mdx | 18 +++++++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx index a198db3937..bcb5d8dbc7 100644 --- a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx +++ b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx @@ -9,7 +9,7 @@ permalink: /documentation/products/guides/kv-store/manage-with-functions/ import LinkButton from 'azion-webkit/linkbutton' -See how to retrieve data from a with KV Store and Edge Functions. +See how to retrieve data from a with KV Store and Functions. @@ -24,7 +24,7 @@ See how to retrieve data from a with KV Store and Edge Functions. : --- -## Creating an edge function to communicate with KV Store +## Creating a function to communicate with KV Store 1. Access [Azion Console](https://console.azion.com). 2. On the upper-left corner, select **Edge Functions** in the **Edge Libraries** section. @@ -79,6 +79,6 @@ addEventListener("fetch", (event) => - + diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index 5e445d78f8..4230ef717e 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -44,7 +44,7 @@ Typical use cases include: | Scope | Resource | | ----- | -------- | -| Manage KV store with Edge Functions | [How to manage KV store with Edge Functions](/en/documentation/products/guides/kv-store/manage-with-functions/) | +| Manage KV store with Functions | [How to manage KV store with Functions](/en/documentation/products/guides/kv-store/manage-with-functions/) | | xxx [How to xxxxx](xxxxxx/) | --- @@ -78,7 +78,7 @@ Naming: --- -## Interacting with KV Store via Edge Functions +## Interacting with KV Store via Functions (Create, Read, Update, Delete) The examples below illustrate common patterns. diff --git a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx index c62f970ccd..52e334d05d 100644 --- a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx +++ b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx @@ -40,19 +40,19 @@ Casos de uso típicos incluem: --- -## Recursos de Implementação +## Recursos de implementação | Âmbito | Recurso | | ----- | -------- | -| Gerenciar KV store com Edge Functions | [Como gerenciar KV store com Edge Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/) | +| Gerenciar KV store com Functions | [Como gerenciar KV store com Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/) | | xxx [Como xxxxx](xxxxxx/) | --- -## Regras de Negócio +## Regras de negócio -## Resiliência de Dados +## Resiliência de dados -KV Store usa uma arquitetura distribuída com replicação entre pronomes de borda da Azion. Novas gravações são aceitas na borda e propagadas para réplicas para garantir durabilidade e alta disponibilidade. Leituras são servidas da réplica saudável mais próxima para minimizar a latência. +KV Store usa uma arquitetura distribuída com replicação entre os edge nodes da Azion. Novas gravações são aceitas no edge e propagadas para réplicas para garantir durabilidade e alta disponibilidade. Leituras são servidas da réplica saudável mais próxima para minimizar a latência. --- @@ -74,7 +74,7 @@ Nomenclatura: --- -## Interação com KV Store via Edge Functions +## Interação com KV Store via Functions Os exemplos abaixo ilustram padrões comuns. @@ -112,7 +112,11 @@ Estes são os **limites padrão**: Estes são os **limites padrão** para cada Plano de Serviço: -| Âmbito | Desenvolvedor | Negócios | Empresarial | Missão Crítica | +| Âmbito | Developer | Business | Enterprise | Mission Critical |   +-- | -- + + +
| | ----- | --------- | -------- | ---------- | ---------------- | | Namespaces | 10 | 50 | 200 | 200 | | Tamanho máximo do arquivo | 200 MB | 500 MB | 2 GB | 2 GB | From 754fb7206d3ce348183d905b38ac4a04af9f75c1 Mon Sep 17 00:00:00 2001 From: Vitor Eltz <107409234+VitorAEltz@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:36:42 -0300 Subject: [PATCH 04/11] Apply suggestion from @MarianaReisAlcantara Co-authored-by: MarianaReisAlcantara --- .../en/pages/main-menu/reference/store/kv-store/kv-store.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index 4230ef717e..98cd66bad3 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -114,7 +114,6 @@ These are the **default limits**: - Metadata size: up to 1024 bytes (JSON-serialized). - Value size: up to 25 MB per item. - These are the **default limits** for each Service Plan: | Scope | Developer | Business | Enterprise | Mission Critical | From 335b94f3e964e9290d5856ac7de5a99088f655e1 Mon Sep 17 00:00:00 2001 From: Vitor Eltz <107409234+VitorAEltz@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:36:57 -0300 Subject: [PATCH 05/11] Apply suggestion from @MarianaReisAlcantara Co-authored-by: MarianaReisAlcantara --- src/content/docs/en/pages/guides/kv-store/manage-data.mdx | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx index bcb5d8dbc7..c94bc21868 100644 --- a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx +++ b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx @@ -76,9 +76,6 @@ addEventListener("fetch", (event) => ); ``` - - - From 15917b4f5be94836e71a406af5b09df3a9d0b365 Mon Sep 17 00:00:00 2001 From: Vitor Eltz <107409234+VitorAEltz@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:37:29 -0300 Subject: [PATCH 06/11] Apply suggestion from @MarianaReisAlcantara Co-authored-by: MarianaReisAlcantara --- .../en/pages/main-menu/reference/store/kv-store/kv-store.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index 98cd66bad3..d4dcfd9d1b 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -102,7 +102,6 @@ const aqui=1 - delete(namespace, key) - returns: void - --- ## Limits From 152cf7d0c8d4064d0da66516c9913a9f004a9616 Mon Sep 17 00:00:00 2001 From: Vitor Eltz <107409234+VitorAEltz@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:37:38 -0300 Subject: [PATCH 07/11] Apply suggestion from @MarianaReisAlcantara Co-authored-by: MarianaReisAlcantara --- .../en/pages/main-menu/reference/store/kv-store/kv-store.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index d4dcfd9d1b..47d2692d0c 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -121,5 +121,4 @@ These are the **default limits** for each Service Plan: | Maximum file size | 200 MB | 500 MB | 2 GB | 2 GB | | Maximum storage per account | 5 GB | 50 GB | 300 GB | 300 GB | - --- From 2566c391eb1be8789ea320b4dcfb6104f5f950d8 Mon Sep 17 00:00:00 2001 From: Vitor Eltz <107409234+VitorAEltz@users.noreply.github.com> Date: Tue, 10 Feb 2026 12:37:48 -0300 Subject: [PATCH 08/11] Apply suggestion from @MarianaReisAlcantara Co-authored-by: MarianaReisAlcantara --- .../en/pages/main-menu/reference/store/kv-store/kv-store.mdx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index 47d2692d0c..7391409c5e 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -83,7 +83,6 @@ Naming: (Create, Read, Update, Delete) The examples below illustrate common patterns. - ```js const aqui=1 ``` From df13fca213608cd89555b03fe84a6285f33cb44c Mon Sep 17 00:00:00 2001 From: Vitor-Azion Date: Tue, 10 Feb 2026 13:17:00 -0300 Subject: [PATCH 09/11] docs: expand KV Store documentation with comprehensive examples and API reference Add detailed usage examples for storing, retrieving, and deleting data in KV Store. Include examples for working with different data types (text, JSON, binary, streams), metadata handling, multiple key operations, and namespace management. Update guide structure with clearer sections and add API reference documentation for namespace and key management operations. Fix meta tags and namespace references. --- .../en/pages/guides/kv-store/manage-data.mdx | 346 +++++++++++-- .../reference/store/kv-store/kv-store.mdx | 450 +++++++++++++++-- .../guias/kv-store/gerenciar-com-funcoes.mdx | 321 ++++++++++++ .../referencia/store/kv-store/kv-store.mdx | 466 ++++++++++++++++-- 4 files changed, 1435 insertions(+), 148 deletions(-) create mode 100644 src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx diff --git a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx index c94bc21868..f98d613920 100644 --- a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx +++ b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx @@ -1,15 +1,17 @@ --- title: How to manage KV Store with Functions description: >- - -meta_tags: 'edge sql, storage, cloud, SQL, sqlite, data' + Learn how to store, retrieve, and delete data using KV Store within your + edge functions. +meta_tags: 'kv store, storage, key-value, edge functions, data' namespace: documentation_products_kv_store_manage_edge_functions permalink: /documentation/products/guides/kv-store/manage-with-functions/ --- import LinkButton from 'azion-webkit/linkbutton' -See how to retrieve data from a with KV Store and Functions. +This guide shows you how to interact with KV Store from your edge functions to +store, retrieve, and delete key-value data at the edge. @@ -17,65 +19,305 @@ See how to retrieve data from a with KV Store and Functions. ## Requirements -- [Azion Edge Functions enabled](/en/documentation/products/build/edge-application/edge-functions/). ---- +Before you begin, make sure you have: + +- [Functions enabled](/en/documentation/products/build/edge-application/edge-functions/) in your edge application. +- A KV Store namespace created via Console or API. -## Creating a kv -: --- -## Creating a function to communicate with KV Store +## Creating a function to interact with KV Store + +Follow these steps to create an edge function that communicates with KV Store: 1. Access [Azion Console](https://console.azion.com). -2. On the upper-left corner, select **Edge Functions** in the **Edge Libraries** section. -3. Click the **+ Edge Function** button. -4. Choose a name for your function. -5. Delete the placeholder function that is inside the code editor. -6. Paste the following code: - -```js -import { Database } from "azion:sql"; - -async function db_query() { - let connection = await Database.open("mydatabase"); - let rows = await connection.query("select * from users"); - let column_count = rows.columnCount(); - let column_names = []; - for (let i = 0; i < column_count; i++) { - column_names.push(rows.columnName(i)); - } - let response_lines = []; - response_lines.push(column_names.join("|")); - let row = await rows.next(); - while (row) { - let row_items = []; - for (let i = 0; i < column_count; i++) { - row_items.push(row.getString(i)); +2. On the upper-left corner, select **Functions** in the **Edge Libraries** section. +3. Click **+ Function**. +4. Enter a name for your function, for example: `kv-store-handler`. +5. Delete the placeholder code in the editor. +6. Paste one of the code examples below based on your use case. + +--- + +## Storing data + +This example demonstrates how to store different types of data in KV Store: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Store a simple string + await kv.put("greeting", "Hello, World!"); + + // Store a JSON object + await kv.put("user-preferences", { + theme: "dark", + language: "en", + notifications: true + }); + + // Store with metadata and expiration + await kv.put("session-token", "abc123xyz", { + metadata: { userId: "user-42" }, + expirationTtl: 3600 // expires in 1 hour + }); + + return new Response("Data stored successfully", { + headers: { "Content-Type": "text/plain" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Retrieving data + +This example shows how to retrieve data in different formats: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Get as text (default) + const greeting = await kv.get("greeting", "text"); + + // Get as JSON object + const preferences = await kv.get("user-preferences", "json"); + + // Handle missing keys + const missing = await kv.get("non-existent-key", "text"); + if (missing === null) { + console.log("Key not found"); } - response_lines.push(row_items.join("|")); - row = await rows.next(); - } - const response_text = response_lines.join("\n"); - return response_text; + + const response = { + greeting, + preferences, + keyExists: missing !== null + }; + + return new Response(JSON.stringify(response), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); } -async function handle_request(request) { - if (request.method != "GET") { - return new Response("Method not allowed", { status: 405 }); - } - try { - return new Response(await db_query()); - } catch (e) { - console.log(e.message, e.stack); - return new Response(e.message, { status: 500 }); - } +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Retrieving multiple keys + +Fetch multiple values in a single operation: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Store some test data + await kv.put("user-1", "Alice"); + await kv.put("user-2", "Bob"); + await kv.put("user-3", "Charlie"); + + // Retrieve multiple keys at once + const keys = ["user-1", "user-2", "user-3", "user-4"]; + const users = await kv.get(keys, "text"); + + // Result: { "user-1": "Alice", "user-2": "Bob", "user-3": "Charlie", "user-4": null } + + return new Response(JSON.stringify(users), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Retrieving data with metadata + +Use `getWithMetadata` to retrieve both the value and its associated metadata: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Store data with metadata + await kv.put("session", "active-session-data", { + metadata: { + createdAt: new Date().toISOString(), + userId: "user-42" + } + }); + + // Retrieve with metadata + const result = await kv.getWithMetadata("session", "text"); + + console.log(`Value: ${result.value}`); + console.log(`Metadata: ${JSON.stringify(result.metadata)}`); + + return new Response(JSON.stringify(result), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); } -addEventListener("fetch", (event) => - event.respondWith(handle_request(event.request)) -); -``` +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Deleting data + +Remove a key from the store: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const key = "session-token"; + + // Delete the key + await kv.delete(key); + + return new Response(`Key '${key}' deleted`, { + headers: { "Content-Type": "text/plain" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Working with binary data + +Store and retrieve binary data using ArrayBuffer: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Store binary data + const encoder = new TextEncoder(); + const binaryData = encoder.encode("Binary content here").buffer; + await kv.put("binary-key", binaryData); + + // Retrieve as ArrayBuffer + const retrieved = await kv.get("binary-key", "arrayBuffer"); + + // Decode back to string + const decoder = new TextDecoder("utf-8"); + const decodedString = decoder.decode(retrieved); + + return new Response(decodedString, { + headers: { "Content-Type": "text/plain" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Working with streams + +For large data, use ReadableStream for efficient memory usage: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "large-content"; + + // Retrieve as stream + const stream = await kv.get(key, "stream"); + + if (stream === null) { + return new Response("Key not found", { status: 404 }); + } + + // Return the stream directly in the response + return new Response(stream, { + headers: { "Content-Type": "application/octet-stream" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Using specific namespaces + +Work with different namespaces for data isolation: + +```javascript +async function handleRequest(request) { + // Use a specific namespace + const productionKV = new Azion.KV("production-data"); + const stagingKV = new Azion.KV("staging-data"); + + // Or use the open method + const cacheKV = await Azion.KV.open("cache-namespace"); + + // Each namespace is isolated + await productionKV.put("config", "production-value"); + await stagingKV.put("config", "staging-value"); + + const prodConfig = await productionKV.get("config", "text"); + const stagingConfig = await stagingKV.get("config", "text"); + + return new Response(JSON.stringify({ + production: prodConfig, + staging: stagingConfig + }), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Instantiating the function + +After creating your function, you need to instantiate it in your edge application: + + + +--- + +## Next steps - +- Learn more about [KV Store](/en/documentation/products/store/kv-store/) +- Explore [Functions](/en/documentation/products/build/edge-application/edge-functions/) diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index 7391409c5e..b275a9e90b 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -1,9 +1,10 @@ --- title: KV Store description: >- - -meta_tags: 'kv, storage, key, distributed, queries' -namespace: docs_edge_sql + KV Store is a distributed key-value storage service that runs across Azion's + edge network, providing low-latency data persistence and retrieval. +meta_tags: 'kv, storage, key, distributed, queries, edge, key-value' +namespace: docs_kv_store permalink: /documentation/products/store/kv-store/ --- @@ -14,14 +15,14 @@ import LinkButton from 'azion-webkit/linkbutton' Preview - -## Overview - -KV Store is a distributed key–value storage service that runs across Azion’s edge network. It lets you persist and retrieve small pieces of data with very low latency from anywhere your users are, without managing servers. +KV Store is a distributed key-value storage service that runs across Azion's +edge network. It lets you persist and retrieve small pieces of data with very +low latency from anywhere your users are, without managing servers. Typical use cases include: - Session and authentication tokens +- Feature flags and A/B testing configurations - User preferences and personalization - Caching API responses and computed fragments - Rate-limit counters and idempotency keys @@ -31,75 +32,433 @@ Typical use cases include: ## How it works -- Data is organized into namespaces that contain independent sets of keys. -- Each item is addressed by a key that is unique within its namespace. -- Values can be stored as text, JSON, or binary/streaming payloads. +KV Store organizes data into namespaces, where each namespace contains an +independent set of keys. Here's how the system operates: + +- Data is organized into **namespaces** that contain independent sets of keys. +- Each item is addressed by a **key** that is unique within its namespace. +- Values can be stored as **text**, **JSON**, **ArrayBuffer**, or **ReadableStream**. - Data is replicated across Azion edge nodes to maximize availability and read performance. -- Single-key operations are atomic per key. Multi-key transactions are not supported. +- Single-key operations are atomic per key. Multi-key transactions aren't supported. --- ## Implementation resources - | Scope | Resource | | ----- | -------- | -| Manage KV store with Functions | [How to manage KV store with Functions](/en/documentation/products/guides/kv-store/manage-with-functions/) | -| xxx [How to xxxxx](xxxxxx/) | ---- - -## Business rules - - +| Manage KV Store with Functions | [How to manage KV Store with Functions](/en/documentation/products/guides/kv-store/manage-with-functions/) | +| KV Store API reference | [Azion API - KV Store](https://api.azion.com/) | --- ## Data resilience -KV Store uses a distributed architecture with replication across Azion edge nodes. New writes are accepted at the edge and propagated to replicas to ensure durability and high availability. Reads are served from the closest healthy replica to minimize latency. +KV Store uses a distributed architecture with replication across Azion edge +nodes. New writes are accepted at the edge and propagated to replicas to ensure +durability and high availability. Reads are served from the closest healthy +replica to minimize latency. --- ## Namespaces -A namespace is an isolated key space. Use namespaces to segment data by application, environment, or workload. +A namespace is an isolated key space. Use namespaces to segment data by +application, environment, or workload. -Recommended patterns: +### Recommended patterns -- Separate namespaces for production and staging. -- Prefix keys to model hierarchy, for example: users/123/profile, flags/new-ui, carts/region-br/user-42. +- Use separate namespaces for production and staging environments. +- Prefix keys to model hierarchy, for example: `users/123/profile`, `flags/new-ui`, `carts/region-br/user-42`. - Keep keys short and meaningful; prefer a few path-like segments over long opaque identifiers. -Naming: +### Naming conventions - Names must be unique within your account. +- Names must be between 3 and 63 characters. - Use lowercase letters, numbers, dashes, and underscores. +- Names must match the pattern: `^[a-zA-Z0-9_-]+$` ---- +### Managing namespaces via API + +You can manage namespaces using the Azion API. The base endpoint is: + +``` +https://api.azion.com/v4/workspace/kv/namespaces +``` + +#### Create a namespace + +```bash +curl -X POST "https://api.azion.com/v4/workspace/kv/namespaces" \ + -H "Authorization: Token YOUR_API_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"name": "my-namespace"}' +``` +**Response (201 Created):** + +```json +{ + "name": "my-namespace", + "created_at": "2025-01-24T14:15:22Z", + "last_modified": "2025-01-24T14:15:22Z" +} +``` + +#### List namespaces + +```bash +curl -X GET "https://api.azion.com/v4/workspace/kv/namespaces" \ + -H "Authorization: Token YOUR_API_TOKEN" \ + -H "Accept: application/json" +``` + +**Query parameters:** + +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| `fields` | string | Comma-separated list of field names to include in the response | +| `page` | integer | Page number within the paginated result set | +| `page_size` | integer | Number of items per page | + +#### Retrieve a namespace + +```bash +curl -X GET "https://api.azion.com/v4/workspace/kv/namespaces/{namespace}" \ + -H "Authorization: Token YOUR_API_TOKEN" \ + -H "Accept: application/json" +``` + +--- ## Interacting with KV Store via Functions -(Create, Read, Update, Delete) -The examples below illustrate common patterns. +You can interact with KV Store directly from your edge functions using the +`Azion.KV` class. The examples below illustrate common patterns for creating, +reading, updating, and deleting data. + +### Initializing the KV client + +You can initialize the KV client using the constructor or the `open` method: + +```javascript +// Using the default namespace +const kv = new Azion.KV(); -```js -const aqui=1 +// Using a specific namespace +const kv = new Azion.KV("my-namespace"); + +// Using the open method +const kv = await Azion.KV.open("my-namespace"); +``` + +### Storing data (put) + +Store values in different formats: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "user-session"; + + // Store a string value + await kv.put(key, "session-data-here"); + + // Store a JSON object + await kv.put(key, { userId: 123, role: "admin" }); + + // Store an ArrayBuffer + const encoder = new TextEncoder(); + const buffer = encoder.encode("binary data").buffer; + await kv.put(key, buffer); + + // Store with options (metadata and expiration) + await kv.put(key, "value", { + metadata: { created_by: "user-42" }, + expiration: Math.floor(Date.now() / 1000) + 3600, // expires in 1 hour + expirationTtl: 3600 // alternative: TTL in seconds + }); + + return new Response("Data stored", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Storing large data with streams + +For large payloads, use `ReadableStream` to stream data efficiently: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "large-file"; + const dataSizeInKB = 500; + const totalSize = dataSizeInKB * 1024; + const chunkSize = 64 * 1024; // 64KB chunks + + 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(key, stream); + + return new Response("Large data stored", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Retrieving data (get) + +Retrieve values in different formats: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "user-session"; + + // Get as text (default) + const textValue = await kv.get(key, "text"); + + // Get as JSON + const jsonValue = await kv.get(key, "json"); + console.log(`User ID: ${jsonValue.userId}`); + + // Get as ArrayBuffer + const bufferValue = await kv.get(key, "arrayBuffer"); + const decoder = new TextDecoder("utf-8"); + const decodedString = decoder.decode(bufferValue); + + // Get as ReadableStream + const streamValue = await kv.get(key, "stream"); + + // Handle non-existent keys (returns null) + const missing = await kv.get("non-existent-key", "text"); + if (missing === null) { + console.log("Key not found"); + } + + return new Response(textValue, { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Retrieving multiple keys + +Retrieve multiple values in a single operation: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const keys = ["user-1", "user-2", "user-3"]; + const data = await kv.get(keys, "text"); + + // Returns an object with key-value pairs + // Non-existent keys have null values + console.log(JSON.stringify(data)); + + return new Response(JSON.stringify(data), { + headers: { "Content-Type": "application/json" }, + status: 200, + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Retrieving data with metadata + +Use `getWithMetadata` to retrieve both the value and its associated metadata: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "user-session"; + + // Store with metadata + await kv.put(key, "session-value", { + metadata: { created_by: "user-42", version: 1 } + }); + + // Retrieve with metadata + const data = await kv.getWithMetadata(key, "text"); + console.log(`Value: ${data.value}`); + console.log(`Metadata: ${JSON.stringify(data.metadata)}`); + + // Works with multiple keys too + const keys = ["key1", "key2"]; + const multiData = await kv.getWithMetadata(keys, "text"); + + return new Response(JSON.stringify(data), { + headers: { "Content-Type": "application/json" }, + status: 200, + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Reading streams + +Process streamed data incrementally: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "large-file"; + + const stream = await kv.get(key, "stream"); + + if (stream instanceof ReadableStream) { + const decoder = new TextDecoder(); + let text = ""; + + for await (const chunk of stream) { + text += decoder.decode(chunk, { stream: true }); + } + text += decoder.decode(); + + console.log(`Retrieved ${text.length} characters`); + } + + // Or return the stream directly in a response + return new Response(stream); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Deleting data + +Remove a key from the store: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "user-session"; + + await kv.delete(key); + + return new Response("Key deleted", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Working with Unicode and special characters + +KV Store supports UTF-8 and UTF-16 encoded keys and values: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // UTF-16 key (Chinese: "My Key") + const key = "我的钥匙"; + + // UTF-16 value with emojis + const value = "🌍🌎🌏 Hello World 你好 世界"; + + await kv.put(key, value); + + const retrieved = await kv.get(key, "text"); + console.log(`Key: ${key}, Value: ${retrieved}`); + + return new Response("OK", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Deleting namespaces + +Delete an entire namespace programmatically: + +```javascript +async function handleRequest(request) { + const namespaceName = "my-namespace"; + + // Delete the namespace + await Azion.KV.delete(namespaceName); + + return new Response("Namespace deleted", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); ``` --- -## Methods +## Methods reference + +The `Azion.KV` class provides the following methods: + +### Constructor and initialization + +| Method | Description | +| ------ | ----------- | +| `new Azion.KV()` | Creates a KV instance using the default namespace | +| `new Azion.KV(name)` | Creates a KV instance for the specified namespace | +| `Azion.KV.open(name)` | Opens a namespace asynchronously | +| `Azion.KV.delete(name)` | Deletes a namespace | + +### Data operations + +| Method | Parameters | Returns | Description | +| ------ | ---------- | ------- | ----------- | +| `put(key, value, options?)` | `key`: string
`value`: string \| object \| ArrayBuffer \| ReadableStream
`options`: { metadata?, expiration?, expirationTtl? } | `Promise` | Stores a value | +| `get(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise` | Retrieves a value | +| `getWithMetadata(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise<{value, metadata}>` | Retrieves value with metadata | +| `delete(key)` | `key`: string | `Promise` | Deletes a key | + +### Put options + +| Option | Type | Description | +| ------ | ---- | ----------- | +| `metadata` | object | Custom metadata to associate with the key (max 1024 bytes JSON-serialized) | +| `expiration` | number | Unix timestamp (seconds) when the key expires | +| `expirationTtl` | number | Time-to-live in seconds from now | + +### Get types -- put(namespace, key, value, options?) - - value: string | object (JSON) | ArrayBuffer | ReadableStream - - options: { metadata?: object, contentType?: string } - - returns: void -- get(namespace, key, options?) - - options: { type: 'text' | 'json' | 'arrayBuffer' | 'stream' } - - returns: string | object | ArrayBuffer | ReadableStream -- delete(namespace, key) - - returns: void +| Type | Returns | Description | +| ---- | ------- | ----------- | +| `"text"` | string | Returns the value as a UTF-8 string (default) | +| `"json"` | object | Parses the value as JSON | +| `"arrayBuffer"` | ArrayBuffer | Returns raw binary data | +| `"stream"` | ReadableStream | Returns a readable stream for large values | --- @@ -107,10 +466,13 @@ const aqui=1 These are the **default limits**: -- Per-key write rate: up to 1 write per second to the same key. -- Key size: up to 512 bytes (UTF‑8). -- Metadata size: up to 1024 bytes (JSON-serialized). -- Value size: up to 25 MB per item. +| Limit | Value | +| ----- | ----- | +| Per-key write rate | Up to 1 write per second to the same key | +| Key size | Up to 512 bytes (UTF-8) | +| Metadata size | Up to 1024 bytes (JSON-serialized) | +| Value size | Up to 25 MB per item | +| Namespace name length | 3-63 characters | These are the **default limits** for each Service Plan: diff --git a/src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx b/src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx new file mode 100644 index 0000000000..d97e7519a8 --- /dev/null +++ b/src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx @@ -0,0 +1,321 @@ +--- +title: Como gerenciar KV Store com Functions +description: >- + Aprenda como armazenar, recuperar e excluir dados usando KV Store dentro de + suas edge functions. +meta_tags: 'kv store, armazenamento, chave-valor, edge functions, dados' +namespace: documentation_products_kv_store_manage_edge_functions +permalink: /documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/ +--- + +import LinkButton from 'azion-webkit/linkbutton' + +Este guia mostra como interagir com o KV Store a partir de suas edge functions +para armazenar, recuperar e excluir dados chave-valor no edge. + + + +--- + +## Requisitos + +Antes de começar, certifique-se de ter: + +- [Functions habilitadas](/pt-br/documentacao/produtos/build/edge-application/edge-functions/) em sua edge application. +- Um namespace do KV Store criado via Console ou API. + +--- + +## Criando uma função para interagir com o KV Store + +Siga estes passos para criar uma edge function que se comunica com o KV Store: + +1. Acesse o [Azion Console](https://console.azion.com). +2. No canto superior esquerdo, selecione **Functions** na seção **Edge Libraries**. +3. Clique em **+ Function**. +4. Digite um nome para sua função, por exemplo: `kv-store-handler`. +5. Exclua o código placeholder no editor. +6. Cole um dos exemplos de código abaixo de acordo com seu caso de uso. + +--- + +## Armazenando dados + +Este exemplo demonstra como armazenar diferentes tipos de dados no KV Store: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Armazenar uma string simples + await kv.put("saudacao", "Olá, Mundo!"); + + // Armazenar um objeto JSON + await kv.put("preferencias-usuario", { + tema: "escuro", + idioma: "pt-br", + notificacoes: true + }); + + // Armazenar com metadados e expiração + await kv.put("token-sessao", "abc123xyz", { + metadata: { userId: "user-42" }, + expirationTtl: 3600 // expira em 1 hora + }); + + return new Response("Dados armazenados com sucesso", { + headers: { "Content-Type": "text/plain" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Recuperando dados + +Este exemplo mostra como recuperar dados em diferentes formatos: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Obter como texto (padrão) + const saudacao = await kv.get("saudacao", "text"); + + // Obter como objeto JSON + const preferencias = await kv.get("preferencias-usuario", "json"); + + // Tratar chaves inexistentes + const inexistente = await kv.get("chave-inexistente", "text"); + if (inexistente === null) { + console.log("Chave não encontrada"); + } + + const response = { + saudacao, + preferencias, + chaveExiste: inexistente !== null + }; + + return new Response(JSON.stringify(response), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Recuperando múltiplas chaves + +Busque múltiplos valores em uma única operação: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Armazenar alguns dados de teste + await kv.put("usuario-1", "Alice"); + await kv.put("usuario-2", "Bob"); + await kv.put("usuario-3", "Charlie"); + + // Recuperar múltiplas chaves de uma vez + const chaves = ["usuario-1", "usuario-2", "usuario-3", "usuario-4"]; + const usuarios = await kv.get(chaves, "text"); + + // Resultado: { "usuario-1": "Alice", "usuario-2": "Bob", "usuario-3": "Charlie", "usuario-4": null } + + return new Response(JSON.stringify(usuarios), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Recuperando dados com metadados + +Use `getWithMetadata` para recuperar tanto o valor quanto seus metadados associados: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Armazenar dados com metadados + await kv.put("sessao", "dados-sessao-ativa", { + metadata: { + criadoEm: new Date().toISOString(), + userId: "user-42" + } + }); + + // Recuperar com metadados + const resultado = await kv.getWithMetadata("sessao", "text"); + + console.log(`Valor: ${resultado.value}`); + console.log(`Metadados: ${JSON.stringify(resultado.metadata)}`); + + return new Response(JSON.stringify(resultado), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Excluindo dados + +Remova uma chave do armazenamento: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const chave = "token-sessao"; + + // Excluir a chave + await kv.delete(chave); + + return new Response(`Chave '${chave}' excluída`, { + headers: { "Content-Type": "text/plain" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Trabalhando com dados binários + +Armazene e recupere dados binários usando ArrayBuffer: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Armazenar dados binários + const encoder = new TextEncoder(); + const dadosBinarios = encoder.encode("Conteúdo binário aqui").buffer; + await kv.put("chave-binaria", dadosBinarios); + + // Recuperar como ArrayBuffer + const recuperado = await kv.get("chave-binaria", "arrayBuffer"); + + // Decodificar de volta para string + const decoder = new TextDecoder("utf-8"); + const stringDecodificada = decoder.decode(recuperado); + + return new Response(stringDecodificada, { + headers: { "Content-Type": "text/plain" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Trabalhando com streams + +Para dados grandes, use ReadableStream para uso eficiente de memória: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const chave = "conteudo-grande"; + + // Recuperar como stream + const stream = await kv.get(chave, "stream"); + + if (stream === null) { + return new Response("Chave não encontrada", { status: 404 }); + } + + // Retornar o stream diretamente na resposta + return new Response(stream, { + headers: { "Content-Type": "application/octet-stream" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Usando namespaces específicos + +Trabalhe com diferentes namespaces para isolamento de dados: + +```javascript +async function handleRequest(request) { + // Usar um namespace específico + const producaoKV = new Azion.KV("dados-producao"); + const stagingKV = new Azion.KV("dados-staging"); + + // Ou usar o método open + const cacheKV = await Azion.KV.open("namespace-cache"); + + // Cada namespace é isolado + await producaoKV.put("config", "valor-producao"); + await stagingKV.put("config", "valor-staging"); + + const configProducao = await producaoKV.get("config", "text"); + const configStaging = await stagingKV.get("config", "text"); + + return new Response(JSON.stringify({ + producao: configProducao, + staging: configStaging + }), { + headers: { "Content-Type": "application/json" }, + status: 200 + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Instanciando a função + +Após criar sua função, você precisa instanciá-la em sua edge application: + + + +--- + +## Próximos passos + +- Saiba mais sobre o [KV Store](/pt-br/documentacao/produtos/store/kv-store/) +- Explore as [Functions](/pt-br/documentacao/produtos/build/edge-application/edge-functions/) diff --git a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx index 52e334d05d..e023154c4a 100644 --- a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx +++ b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx @@ -1,9 +1,11 @@ --- title: KV Store description: >- - -meta_tags: 'kv, armazenamento, chave, distribuído, consultas' -namespace: docs_edge_sql + KV Store é um serviço de armazenamento de chave-valor distribuído que opera + na rede de edge da Azion, fornecendo persistência e recuperação de dados com + baixa latência. +meta_tags: 'kv, armazenamento, chave, distribuído, consultas, edge, chave-valor' +namespace: docs_kv_store permalink: /documentacao/produtos/store/kv-store/ --- @@ -11,92 +13,454 @@ import Tag from 'primevue/tag' import LinkButton from 'azion-webkit/linkbutton' - Previsualização + Preview - -## Visão Geral - -KV Store é um serviço de armazenamento de chave-valor distribuído que opera em toda a rede de borda da Azion. Ele permite que você persista e recupere pequenos pedaços de dados com muito baixa latência de qualquer lugar onde seus usuários estejam, sem precisar gerenciar servidores. +KV Store é um serviço de armazenamento de chave-valor distribuído que opera em +toda a rede de edge da Azion. Ele permite que você persista e recupere pequenos +pedaços de dados com latência muito baixa de qualquer lugar onde seus usuários +estejam, sem precisar gerenciar servidores. Casos de uso típicos incluem: - Sessões e tokens de autenticação -- Sinalizadores de recurso e agrupamentos de A/B testing +- Feature flags e configurações de testes A/B - Preferências de usuário e personalização - Cache de respostas de API e fragmentos computados -- Contadores de limite de taxa e chaves de idempotência +- Contadores de rate limit e chaves de idempotência - Estado do carrinho de compras ou rascunho --- ## Como funciona -- Os dados são organizados em namespaces que contêm conjuntos independentes de chaves. -- Cada item é endereçado por uma chave que é única dentro de seu namespace. -- Os valores podem ser armazenados como texto, JSON ou cargas úteis binárias/em fluxo. -- Os dados são replicados entre pronomes de borda da Azion para maximizar a disponibilidade e o desempenho de leitura. +O KV Store organiza dados em namespaces, onde cada namespace contém um conjunto +independente de chaves. Veja como o sistema opera: + +- Os dados são organizados em **namespaces** que contêm conjuntos independentes de chaves. +- Cada item é endereçado por uma **chave** que é única dentro de seu namespace. +- Os valores podem ser armazenados como **texto**, **JSON**, **ArrayBuffer** ou **ReadableStream**. +- Os dados são replicados entre os edge nodes da Azion para maximizar a disponibilidade e o desempenho de leitura. - Operações de chave única são atômicas por chave. Transações de múltiplas chaves não são suportadas. --- ## Recursos de implementação -| Âmbito | Recurso | -| ----- | -------- | -| Gerenciar KV store com Functions | [Como gerenciar KV store com Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/) | -| xxx [Como xxxxx](xxxxxx/) | ---- +| Escopo | Recurso | +| ------ | ------- | +| Gerenciar KV Store com Functions | [Como gerenciar KV Store com Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/) | +| Referência da API KV Store | [Azion API - KV Store](https://api.azion.com/) | -## Regras de negócio +--- ## Resiliência de dados -KV Store usa uma arquitetura distribuída com replicação entre os edge nodes da Azion. Novas gravações são aceitas no edge e propagadas para réplicas para garantir durabilidade e alta disponibilidade. Leituras são servidas da réplica saudável mais próxima para minimizar a latência. - +O KV Store usa uma arquitetura distribuída com replicação entre os edge nodes +da Azion. Novas gravações são aceitas no edge e propagadas para réplicas para +garantir durabilidade e alta disponibilidade. Leituras são servidas da réplica +saudável mais próxima para minimizar a latência. --- ## Namespaces -Um namespace é um espaço de chave isolado. Use namespaces para segmentar dados por aplicação, ambiente ou carga de trabalho. +Um namespace é um espaço de chaves isolado. Use namespaces para segmentar dados +por aplicação, ambiente ou carga de trabalho. -Padrões recomendados: +### Padrões recomendados -- Namespaces separados para produção e staging. -- Prefixe chaves para modelar hierarquia, por exemplo: users/123/profile, flags/new-ui, carts/region-br/user-42. +- Use namespaces separados para ambientes de produção e staging. +- Prefixe chaves para modelar hierarquia, por exemplo: `users/123/profile`, `flags/new-ui`, `carts/region-br/user-42`. - Mantenha as chaves curtas e significativas; prefira alguns segmentos do tipo caminho em vez de longos identificadores opacos. -Nomenclatura: +### Convenções de nomenclatura - Os nomes devem ser únicos dentro da sua conta. -- Use letras minúsculas, números, hifens e sublinhados. +- Os nomes devem ter entre 3 e 63 caracteres. +- Use letras minúsculas, números, hifens e underscores. +- Os nomes devem corresponder ao padrão: `^[a-zA-Z0-9_-]+$` + +### Gerenciando namespaces via API + +Você pode gerenciar namespaces usando a API da Azion. O endpoint base é: + +``` +https://api.azion.com/v4/workspace/kv/namespaces +``` + +#### Criar um namespace + +```bash +curl -X POST "https://api.azion.com/v4/workspace/kv/namespaces" \ + -H "Authorization: Token SEU_TOKEN_API" \ + -H "Content-Type: application/json" \ + -d '{"name": "meu-namespace"}' +``` + +**Resposta (201 Created):** + +```json +{ + "name": "meu-namespace", + "created_at": "2025-01-24T14:15:22Z", + "last_modified": "2025-01-24T14:15:22Z" +} +``` + +#### Listar namespaces + +```bash +curl -X GET "https://api.azion.com/v4/workspace/kv/namespaces" \ + -H "Authorization: Token SEU_TOKEN_API" \ + -H "Accept: application/json" +``` + +**Parâmetros de consulta:** + +| Parâmetro | Tipo | Descrição | +| --------- | ---- | --------- | +| `fields` | string | Lista separada por vírgulas de nomes de campos para incluir na resposta | +| `page` | integer | Número da página dentro do conjunto de resultados paginados | +| `page_size` | integer | Número de itens por página | + +#### Recuperar um namespace + +```bash +curl -X GET "https://api.azion.com/v4/workspace/kv/namespaces/{namespace}" \ + -H "Authorization: Token SEU_TOKEN_API" \ + -H "Accept: application/json" +``` --- ## Interação com KV Store via Functions -Os exemplos abaixo ilustram padrões comuns. +Você pode interagir com o KV Store diretamente de suas edge functions usando a +classe `Azion.KV`. Os exemplos abaixo ilustram padrões comuns para criar, ler, +atualizar e excluir dados. + +### Inicializando o cliente KV + +Você pode inicializar o cliente KV usando o construtor ou o método `open`: + +```javascript +// Usando o namespace padrão +const kv = new Azion.KV(); + +// Usando um namespace específico +const kv = new Azion.KV("meu-namespace"); + +// Usando o método open +const kv = await Azion.KV.open("meu-namespace"); +``` + +### Armazenando dados (put) + +Armazene valores em diferentes formatos: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "sessao-usuario"; + + // Armazenar um valor string + await kv.put(key, "dados-da-sessao-aqui"); + + // Armazenar um objeto JSON + await kv.put(key, { userId: 123, role: "admin" }); + + // Armazenar um ArrayBuffer + const encoder = new TextEncoder(); + const buffer = encoder.encode("dados binários").buffer; + await kv.put(key, buffer); + + // Armazenar com opções (metadados e expiração) + await kv.put(key, "valor", { + metadata: { created_by: "user-42" }, + expiration: Math.floor(Date.now() / 1000) + 3600, // expira em 1 hora + expirationTtl: 3600 // alternativa: TTL em segundos + }); + + return new Response("Dados armazenados", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### 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 key = "arquivo-grande"; + 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); -```js -const aqui=1 + 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(key, stream); + + return new Response("Dados grandes armazenados", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Recuperando dados (get) + +Recupere valores em diferentes formatos: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "sessao-usuario"; + + // Obter como texto (padrão) + const textValue = await kv.get(key, "text"); + + // Obter como JSON + const jsonValue = await kv.get(key, "json"); + console.log(`User ID: ${jsonValue.userId}`); + + // Obter como ArrayBuffer + const bufferValue = await kv.get(key, "arrayBuffer"); + const decoder = new TextDecoder("utf-8"); + const decodedString = decoder.decode(bufferValue); + + // Obter como ReadableStream + const streamValue = await kv.get(key, "stream"); + + // Tratar chaves inexistentes (retorna null) + const missing = await kv.get("chave-inexistente", "text"); + if (missing === null) { + console.log("Chave não encontrada"); + } + + return new Response(textValue, { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Recuperando múltiplas chaves + +Recupere múltiplos valores em uma única operação: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const keys = ["usuario-1", "usuario-2", "usuario-3"]; + const data = await kv.get(keys, "text"); + + // Retorna um objeto com pares chave-valor + // Chaves inexistentes têm valores null + console.log(JSON.stringify(data)); + + return new Response(JSON.stringify(data), { + headers: { "Content-Type": "application/json" }, + status: 200, + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Recuperando dados com metadados + +Use `getWithMetadata` para recuperar tanto o valor quanto seus metadados associados: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "sessao-usuario"; + + // Armazenar com metadados + await kv.put(key, "valor-sessao", { + metadata: { created_by: "user-42", version: 1 } + }); + + // Recuperar com metadados + const data = await kv.getWithMetadata(key, "text"); + console.log(`Valor: ${data.value}`); + console.log(`Metadados: ${JSON.stringify(data.metadata)}`); + + // Funciona com múltiplas chaves também + const keys = ["chave1", "chave2"]; + const multiData = await kv.getWithMetadata(keys, "text"); + + return new Response(JSON.stringify(data), { + headers: { "Content-Type": "application/json" }, + status: 200, + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Lendo streams + +Processe dados em stream de forma incremental: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "arquivo-grande"; + + const stream = await kv.get(key, "stream"); + + if (stream instanceof ReadableStream) { + const decoder = new TextDecoder(); + let text = ""; + + for await (const chunk of stream) { + text += decoder.decode(chunk, { stream: true }); + } + text += decoder.decode(); + + console.log(`Recuperados ${text.length} caracteres`); + } + + // Ou retorne o stream diretamente na resposta + return new Response(stream); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Excluindo dados + +Remova uma chave do armazenamento: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "sessao-usuario"; + + await kv.delete(key); + + return new Response("Chave excluída", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Trabalhando com Unicode e caracteres especiais + +O KV Store suporta chaves e valores codificados em UTF-8 e UTF-16: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Chave UTF-16 (Chinês: "Minha Chave") + const key = "我的钥匙"; + + // Valor UTF-16 com emojis + const value = "🌍🌎🌏 Hello World 你好 世界"; + + await kv.put(key, value); + + const retrieved = await kv.get(key, "text"); + console.log(`Chave: ${key}, Valor: ${retrieved}`); + + return new Response("OK", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Excluindo namespaces + +Exclua um namespace inteiro programaticamente: + +```javascript +async function handleRequest(request) { + const namespaceName = "meu-namespace"; + + // Excluir o namespace + await Azion.KV.delete(namespaceName); + + return new Response("Namespace excluído", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); ``` --- -## Métodos +## Referência de métodos + +A classe `Azion.KV` fornece os seguintes métodos: + +### Construtor e inicialização -- put(namespace, key, value, options?) - - value: string | object (JSON) | ArrayBuffer | ReadableStream - - options: { metadata?: object, contentType?: string } - - returns: void -- get(namespace, key, options?) - - options: { type: 'text' | 'json' | 'arrayBuffer' | 'stream' } - - returns: string | object | ArrayBuffer | ReadableStream -- delete(namespace, key) - - returns: void +| Método | Descrição | +| ------ | --------- | +| `new Azion.KV()` | Cria uma instância KV usando o namespace padrão | +| `new Azion.KV(name)` | Cria uma instância KV para o namespace especificado | +| `Azion.KV.open(name)` | Abre um namespace de forma assíncrona | +| `Azion.KV.delete(name)` | Exclui um namespace | +### Operações de dados +| Método | Parâmetros | Retorna | Descrição | +| ------ | ---------- | ------- | --------- | +| `put(key, value, options?)` | `key`: string
`value`: string \| object \| ArrayBuffer \| ReadableStream
`options`: { metadata?, expiration?, expirationTtl? } | `Promise` | Armazena um valor | +| `get(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise` | Recupera um valor | +| `getWithMetadata(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise<{value, metadata}>` | Recupera valor com metadados | +| `delete(key)` | `key`: string | `Promise` | Exclui uma chave | + +### Opções do put + +| Opção | Tipo | Descrição | +| ----- | ---- | --------- | +| `metadata` | object | Metadados personalizados para associar à chave (máx 1024 bytes JSON-serializado) | +| `expiration` | number | Timestamp Unix (segundos) quando a chave expira | +| `expirationTtl` | number | Time-to-live em segundos a partir de agora | + +### Tipos do get + +| Tipo | Retorna | Descrição | +| ---- | ------- | --------- | +| `"text"` | string | Retorna o valor como uma string UTF-8 (padrão) | +| `"json"` | object | Faz parse do valor como JSON | +| `"arrayBuffer"` | ArrayBuffer | Retorna dados binários brutos | +| `"stream"` | ReadableStream | Retorna um stream legível para valores grandes | --- @@ -104,20 +468,18 @@ const aqui=1 Estes são os **limites padrão**: -- Taxa de gravação por chave: até 1 gravação por segundo para a mesma chave. -- Tamanho da chave: até 512 bytes (UTF-8). -- Tamanho dos metadados: até 1024 bytes (JSON-serializado). -- Tamanho do valor: até 25 MB por item. - +| Limite | Valor | +| ------ | ----- | +| Taxa de gravação por chave | Até 1 gravação por segundo para a mesma chave | +| Tamanho da chave | Até 512 bytes (UTF-8) | +| Tamanho dos metadados | Até 1024 bytes (JSON-serializado) | +| Tamanho do valor | Até 25 MB por item | +| Comprimento do nome do namespace | 3-63 caracteres | Estes são os **limites padrão** para cada Plano de Serviço: -| Âmbito | Developer | Business | Enterprise | Mission Critical |   --- | -- - - -
| -| ----- | --------- | -------- | ---------- | ---------------- | +| Escopo | Developer | Business | Enterprise | Mission Critical | +| ------ | --------- | -------- | ---------- | ---------------- | | Namespaces | 10 | 50 | 200 | 200 | | Tamanho máximo do arquivo | 200 MB | 500 MB | 2 GB | 2 GB | | Armazenamento máximo por conta | 5 GB | 50 GB | 300 GB | 300 GB | From 619c5971bfc2908383cb530362939b3867285690 Mon Sep 17 00:00:00 2001 From: Vitor-Azion Date: Tue, 10 Feb 2026 15:10:39 -0300 Subject: [PATCH 10/11] docs: add KV Store API reference documentation with read, write, and delete operations Add comprehensive API reference pages for KV Store operations including methods for reading key-value pairs (get, getWithMetadata), writing data (put), and deleting entries. Include detailed parameter descriptions, response types, usage examples, and guidance for handling different data types (text, JSON, binary, streams), metadata, multiple keys, and namespace management. Document eventual consistency behavior --- .../api-reference/kv-store/delete.mdx | 180 +++++++++ .../api-reference/kv-store/index.mdx | 86 +++++ .../api-reference/kv-store/read.mdx | 355 +++++++++++++++++ .../api-reference/kv-store/write.mdx | 231 +++++++++++ .../en/pages/guides/kv-store/manage-data.mdx | 16 +- .../guides/kv-store/redis-compatibility.mdx | 326 ++++++++++++++++ .../reference/store/kv-store/kv-store.mdx | 39 +- .../api-reference/kv-store/delete.mdx | 180 +++++++++ .../api-reference/kv-store/index.mdx | 87 +++++ .../api-reference/kv-store/read.mdx | 359 ++++++++++++++++++ .../api-reference/kv-store/write.mdx | 231 +++++++++++ .../guias/kv-store/compatibilidade-redis.mdx | 326 ++++++++++++++++ .../guias/kv-store/gerenciar-com-funcoes.mdx | 16 +- .../referencia/store/kv-store/kv-store.mdx | 39 +- 14 files changed, 2437 insertions(+), 34 deletions(-) create mode 100644 src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx create mode 100644 src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx create mode 100644 src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx create mode 100644 src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx create mode 100644 src/content/docs/en/pages/guides/kv-store/redis-compatibility.mdx create mode 100644 src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx create mode 100644 src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx create mode 100644 src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx create mode 100644 src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx create mode 100644 src/content/docs/pt-br/pages/guias/kv-store/compatibilidade-redis.mdx diff --git a/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx new file mode 100644 index 0000000000..f1d7e8a7bd --- /dev/null +++ b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx @@ -0,0 +1,180 @@ +--- +title: Delete key-value pairs +description: >- + To remove a key-value pair from KV Store, call the delete() method on your + KV instance. +meta_tags: 'kv store, api, functions, delete, remove, storage' +namespace: documentation_runtime_kv_store_delete +permalink: /documentation/runtime/api-reference/kv-store/delete/ +menu_namespace: runtimeMenu +--- + +To remove a key-value pair from KV Store, call the `delete()` method on your +KV instance: + +```javascript +await kv.delete(key); +``` + +## Example + +An example of deleting a key-value pair from within a Function: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + try { + await kv.delete("user-session"); + + return new Response("Key deleted successfully", { status: 200 }); + } catch (e) { + return new Response(e.message, { status: 500 }); + } +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Reference + +### `delete()` method + +To remove a key-value pair, call the `delete()` method on your KV instance: + +```javascript +await kv.delete(key); +``` + +#### Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `string` | The key of the KV pair to delete. | + +#### Response + +| Response | Type | Description | +|----------|------|-------------| +| `response` | `Promise` | A Promise that resolves when the deletion is complete. | + +The `delete()` method returns a Promise that you should `await` to verify +successful deletion. + +--- + +## Guidance + +### Deleting non-existent keys + +Deleting a key that doesn't exist will not throw an error. The operation +completes successfully regardless of whether the key existed: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // This will succeed even if the key doesn't exist + await kv.delete("non-existent-key"); + + return new Response("Delete operation completed", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Eventual consistency + +Like all KV Store operations, deletions are eventually consistent. After +deleting a key: + +- The deletion is immediately visible in the same global network location. +- Other locations may still see the old value for up to 60 seconds (or the + duration of any `cacheTtl` that was set when reading the key). + +### Conditional deletion + +You may want to check if a key exists before deleting it, or perform +additional logic: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "user-session"; + + // Check if key exists before deleting + const value = await kv.get(key, "text"); + + if (value === null) { + return new Response("Key not found", { status: 404 }); + } + + // Perform deletion + await kv.delete(key); + + return new Response("Key deleted", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Deleting multiple keys + +To delete multiple keys, you can use `Promise.all()`: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const keysToDelete = ["key1", "key2", "key3"]; + + await Promise.all(keysToDelete.map(key => kv.delete(key))); + + return new Response("All keys deleted", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Deleting namespaces + +To delete an entire namespace (not just a key), use the static +`Azion.KV.delete()` method: + +```javascript +async function handleRequest(request) { + const namespaceName = "my-namespace"; + + // Delete the entire namespace + await Azion.KV.delete(namespaceName); + + return new Response("Namespace deleted", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +:::caution +Deleting a namespace removes all key-value pairs within it. This operation +cannot be undone. +::: + +--- + +## Related + +- [Write key-value pairs](/en/documentation/runtime/api-reference/kv-store/write/) +- [Read key-value pairs](/en/documentation/runtime/api-reference/kv-store/read/) +- [KV Store API overview](/en/documentation/runtime/api-reference/kv-store/) diff --git a/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx new file mode 100644 index 0000000000..482b20e4e3 --- /dev/null +++ b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx @@ -0,0 +1,86 @@ +--- +title: KV Store API +description: >- + The KV Store API provides methods to store, retrieve, and delete key-value + pairs from within your Functions. +meta_tags: 'kv store, api, functions, key-value, storage' +namespace: documentation_runtime_kv_store_api +permalink: /documentation/runtime/api-reference/kv-store/ +menu_namespace: runtimeMenu +--- + +The KV Store API allows your Functions to interact with Azion's distributed +key-value storage directly from the runtime. This enables low-latency data +persistence and retrieval without external API calls. + +## Initializing the KV client + +You can initialize the KV client using the constructor or the `open` method: + +```javascript +// Using the default namespace +const kv = new Azion.KV(); + +// Using a specific namespace +const kv = new Azion.KV("my-namespace"); + +// Using the open method (async) +const kv = await Azion.KV.open("my-namespace"); +``` + +## Available methods + +The `Azion.KV` class provides the following methods for data operations: + +| Method | Description | Reference | +|--------|-------------|-----------| +| `put(key, value, options?)` | Store a key-value pair | [Write key-value pairs](/en/documentation/runtime/api-reference/kv-store/write/) | +| `get(key, type?, options?)` | Retrieve a value by key | [Read key-value pairs](/en/documentation/runtime/api-reference/kv-store/read/) | +| `getWithMetadata(key, type?, options?)` | Retrieve a value with its metadata | [Read key-value pairs](/en/documentation/runtime/api-reference/kv-store/read/) | +| `delete(key)` | Delete a key-value pair | [Delete key-value pairs](/en/documentation/runtime/api-reference/kv-store/delete/) | + +## Namespace management + +| Method | Description | +|--------|-------------| +| `new Azion.KV()` | Creates a KV instance using the default namespace | +| `new Azion.KV(name)` | Creates a KV instance for the specified namespace | +| `Azion.KV.open(name)` | Opens a namespace asynchronously | +| `Azion.KV.delete(name)` | Deletes a namespace | + +:::note +Namespaces must be created via the [Azion API](https://api.azion.com/) or Console before they can be used in Functions. You cannot create namespaces from within Functions. +::: + +## Supported value types + +KV Store supports the following value types: + +| Type | Description | +|------|-------------| +| `string` | Text data (UTF-8 encoded) | +| `object` | JSON-serializable objects (automatically stringified) | +| `ArrayBuffer` | Binary data | +| `ReadableStream` | Streaming data for large values | + +## Limits + +| Limit | Value | +|-------|-------| +| Key size | Up to 512 bytes (UTF-8) | +| Value size | Up to 25 MB per item | +| Metadata size | Up to 1024 bytes (JSON-serialized) | +| Per-key write rate | Up to 1 write per second to the same key | +| Minimum `expirationTtl` | 60 seconds | +| Minimum `cacheTtl` | 60 seconds | + +## Eventual consistency + +KV Store uses eventual consistency. Writes are immediately visible to other +requests in the same global network location, but can take up to 60 seconds +(or the value of the `cacheTtl` parameter) to be visible in other locations. + +## Related documentation + +- [KV Store reference](/en/documentation/products/store/kv-store/) +- [How to manage KV Store with Functions](/en/documentation/products/guides/kv-store/manage-with-functions/) diff --git a/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx new file mode 100644 index 0000000000..6d936c4418 --- /dev/null +++ b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx @@ -0,0 +1,355 @@ +--- +title: Read key-value pairs +description: >- + To get the value for a given key, call the get() method on your KV instance. +meta_tags: 'kv store, api, functions, read, get, storage' +namespace: documentation_runtime_kv_store_read +permalink: /documentation/runtime/api-reference/kv-store/read/ +menu_namespace: runtimeMenu +--- + +To get the value for a given key, call the `get()` method on your KV instance: + +```javascript +// Read individual key +const value = await kv.get(key); + +// Read multiple keys +const values = await kv.get(keys); +``` + +The `get()` method returns a promise you can `await` to get the value. + +If you request a single key as a string, you will get a single response in the +promise. If the key is not found, the promise will resolve with the literal +value `null`. + +You can also request an array of keys. The return value will be an object with +key-value pairs, where keys not found have `null` values. + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + try { + // Read single key, returns value or null + const value = await kv.get("first-key", "text"); + + // Read multiple keys, returns object with values + const values = await kv.get(["first-key", "second-key"], "text"); + + // Read single key with metadata + const valueWithMetadata = await kv.getWithMetadata("first-key", "text"); + + // Read multiple keys with metadata + const valuesWithMetadata = await kv.getWithMetadata(["first-key", "second-key"], "text"); + + return new Response(JSON.stringify({ + value: value, + values: values, + valueWithMetadata: valueWithMetadata, + valuesWithMetadata: valuesWithMetadata + }), { + headers: { "Content-Type": "application/json" } + }); + } catch (e) { + return new Response(e.message, { status: 500 }); + } +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +:::note +`get()` and `getWithMetadata()` methods may return stale values. If a given +key has recently been read in a given location, writes or updates to the key +made in other locations may take up to 60 seconds (or the duration of the +`cacheTtl`) to display. +::: + +--- + +## Reference + +The following methods are provided to read from KV Store: + +- [get()](#get-method) +- [getWithMetadata()](#getwithmetadata-method) + +### `get()` method + +Use the `get()` method to get a single value, or multiple values if given +multiple keys. + +#### Request a single key + +To get the value for a single key, call the `get()` method on your KV instance: + +```javascript +await kv.get(key, type?, options?); +``` + +##### Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `string` | The key of the KV pair. | +| `type` | `"text"` \| `"json"` \| `"arrayBuffer"` \| `"stream"` | Optional. The type of the value to be returned. `text` is the default. | +| `options` | `{ cacheTtl?: number }` | Optional. Object containing the `cacheTtl` property. | + +##### Options + +| Option | Type | Description | +|--------|------|-------------| +| `cacheTtl` | `number` | Time in seconds to cache the result locally. Minimum value is 60. | + +##### Response + +| Response | Type | Description | +|----------|------|-------------| +| `response` | `Promise` | The value for the requested KV pair, or `null` if not found. | + +The response type depends on the `type` parameter: + +| Type | Returns | +|------|---------| +| `"text"` | A `string` (default) | +| `"json"` | An object decoded from a JSON string | +| `"arrayBuffer"` | An `ArrayBuffer` instance | +| `"stream"` | A `ReadableStream` | + +#### Request multiple keys + +To get the values for multiple keys, call the `get()` method with an array: + +```javascript +await kv.get(keys, type?); +``` + +##### Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `keys` | `string[]` | The keys of the KV pairs. | +| `type` | `"text"` \| `"json"` | Optional. The type of the value to be returned. `text` is the default. | + +##### Response + +| Response | Type | Description | +|----------|------|-------------| +| `response` | `Promise` | An object with key-value pairs. Keys not found have `null` values. | + +--- + +### `getWithMetadata()` method + +Use the `getWithMetadata()` method to get a single value along with its +metadata, or multiple values with their metadata. + +#### Request a single key with metadata + +To get the value for a given key along with its metadata: + +```javascript +await kv.getWithMetadata(key, type?, options?); +``` + +Metadata is a serializable value you append to each KV entry when using `put()`. + +##### Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `string` | The key of the KV pair. | +| `type` | `"text"` \| `"json"` \| `"arrayBuffer"` \| `"stream"` | Optional. The type of the value to be returned. `text` is the default. | +| `options` | `{ cacheTtl?: number }` | Optional. Object containing the `cacheTtl` property. | + +##### Response + +| Response | Type | Description | +|----------|------|-------------| +| `response` | `Promise<{ value: string \| object \| ArrayBuffer \| ReadableStream \| null, metadata: object \| null }>` | An object containing the value and metadata. | + +If there is no metadata associated with the requested key-value pair, `null` +will be returned for metadata. + +#### Request multiple keys with metadata + +To get the values for multiple keys along with their metadata: + +```javascript +await kv.getWithMetadata(keys, type?); +``` + +##### Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `keys` | `string[]` | The keys of the KV pairs. | +| `type` | `"text"` \| `"json"` | Optional. The type of the value to be returned. `text` is the default. | + +##### Response + +| Response | Type | Description | +|----------|------|-------------| +| `response` | `Promise` | An object with keys mapped to `{ value, metadata }` objects. | + +--- + +## Guidance + +### Type parameter + +For simple values, use the default `text` type which provides your value as a +`string`. For convenience, a `json` type is also specified which will convert +a JSON value into an object before returning it. For large values, use `stream` +to request a `ReadableStream`. For binary values, use `arrayBuffer` to request +an `ArrayBuffer`. + +For large values, the choice of `type` can have a noticeable effect on latency +and CPU usage. For reference, the `type` can be ordered from fastest to slowest +as `stream`, `arrayBuffer`, `text`, and `json`. + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Get as text (default) + const textValue = await kv.get("my-key", "text"); + + // Get as JSON (automatically parsed) + const jsonValue = await kv.get("my-key", "json"); + console.log(jsonValue.someProperty); + + // Get as ArrayBuffer + const bufferValue = await kv.get("my-key", "arrayBuffer"); + const decoder = new TextDecoder("utf-8"); + const decodedString = decoder.decode(bufferValue); + + // Get as ReadableStream + const streamValue = await kv.get("my-key", "stream"); + + return new Response(textValue); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### CacheTtl parameter + +`cacheTtl` is a parameter that defines the length of time in seconds that a KV +result is cached in the global network location where it is accessed. + +Defining the length of time in seconds is useful for reducing cold read latency +on keys that are read relatively infrequently. `cacheTtl` is useful if your +data is write-once or write-rarely. + +:::note[Hot and cold reads] +A hot read means that the data is cached locally. A cold read means that the +data is not cached, so it must be fetched from the central stores. Both +existing key-value pairs and non-existent key-value pairs (negative lookups) +are cached. +::: + +`cacheTtl` is not recommended if your data is updated often and you need to +see updates shortly after they are written, because writes from other global +network locations will not be visible until the cached value expires. + +The minimum value for `cacheTtl` is 60 seconds. + +```javascript +// Cache the result for 5 minutes +const value = await kv.get("config-key", "json", { cacheTtl: 300 }); +``` + +### Handling non-existent keys + +When a key doesn't exist, `get()` returns `null`: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const value = await kv.get("non-existent-key", "text"); + + if (value === null) { + return new Response("Key not found", { status: 404 }); + } + + return new Response(value); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Reading streams + +For large values stored as streams, process the data incrementally: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const stream = await kv.get("large-file", "stream"); + + if (stream instanceof ReadableStream) { + const decoder = new TextDecoder(); + let text = ""; + + for await (const chunk of stream) { + text += decoder.decode(chunk, { stream: true }); + } + text += decoder.decode(); + + console.log(`Retrieved ${text.length} characters`); + } + + // Or return the stream directly in a response + return new Response(stream); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Working with metadata + +Retrieve both value and metadata in a single call: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const result = await kv.getWithMetadata("user-profile", "json"); + + console.log("Value:", result.value); + console.log("Metadata:", result.metadata); + + if (result.metadata && result.metadata.version) { + console.log("Version:", result.metadata.version); + } + + return new Response(JSON.stringify(result), { + headers: { "Content-Type": "application/json" } + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Related + +- [Write key-value pairs](/en/documentation/runtime/api-reference/kv-store/write/) +- [Delete key-value pairs](/en/documentation/runtime/api-reference/kv-store/delete/) +- [KV Store API overview](/en/documentation/runtime/api-reference/kv-store/) diff --git a/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx new file mode 100644 index 0000000000..eea07ac28a --- /dev/null +++ b/src/content/docs/en/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx @@ -0,0 +1,231 @@ +--- +title: Write key-value pairs +description: >- + To create a new key-value pair, or to update the value for a particular key, + call the put() method on your KV instance. +meta_tags: 'kv store, api, functions, write, put, storage' +namespace: documentation_runtime_kv_store_write +permalink: /documentation/runtime/api-reference/kv-store/write/ +menu_namespace: runtimeMenu +--- + +To create a new key-value pair, or to update the value for a particular key, +call the `put()` method on your KV instance: + +```javascript +await kv.put(key, value); +``` + +## Example + +An example of writing a key-value pair from within a Function: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + try { + await kv.put("first-key", "This is the value for the key"); + + return new Response("Successful write", { status: 201 }); + } catch (e) { + return new Response(e.message, { status: 500 }); + } +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Reference + +### `put()` method + +To create a new key-value pair, or to update the value for a particular key, +call the `put()` method on your KV instance: + +```javascript +await kv.put(key, value, options?); +``` + +#### Parameters + +| Parameter | Type | Description | +|-----------|------|-------------| +| `key` | `string` | The key to associate with the value. Keys have a maximum length of 512 bytes. | +| `value` | `string` \| `object` \| `ArrayBuffer` \| `ReadableStream` | The value to store. The type is inferred. The maximum size of a value is 25 MB. | +| `options` | `object` | Optional. An object containing `expiration`, `expirationTtl`, and `metadata` attributes. | + +#### Options + +| Option | Type | Description | +|--------|------|-------------| +| `expiration` | `number` | The number representing when to expire the key-value pair in seconds since epoch. | +| `expirationTtl` | `number` | The number representing when to expire the key-value pair in seconds from now. The minimum value is 60. | +| `metadata` | `object` | An object that must serialize to JSON. The maximum size of the serialized JSON representation is 1024 bytes. | + +#### Response + +| Response | Type | Description | +|----------|------|-------------| +| `response` | `Promise` | A Promise that resolves if the update is successful. | + +The `put()` method returns a Promise that you should `await` to verify a +successful update. + +--- + +## Guidance + +### Writing different value types + +You can store different types of values: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Store a string value + await kv.put("user-name", "John Doe"); + + // Store a JSON object (automatically stringified) + await kv.put("user-data", { id: 123, role: "admin" }); + + // Store an ArrayBuffer + const encoder = new TextEncoder(); + const buffer = encoder.encode("binary data").buffer; + await kv.put("binary-key", buffer); + + // Store a ReadableStream (for large data) + const stream = new ReadableStream({ + start(controller) { + controller.enqueue(new TextEncoder().encode("large data...")); + controller.close(); + } + }); + await kv.put("stream-key", stream); + + return new Response("Data stored", { status: 201 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Concurrent writes to the same key + +Due to the eventually consistent nature of KV Store, concurrent writes to the +same key can end up overwriting one another. If concurrent writes are made to +the same key, the last write will take precedence. + +Writes are immediately visible to other requests in the same global network +location, but can take up to 60 seconds (or the value of the `cacheTtl` +parameter of the `get()` or `getWithMetadata()` methods) to be visible in +other parts of the world. + +### Expiring keys + +KV Store offers the ability to create keys that automatically expire. You can +configure expiration to occur either at a particular point in time (using the +`expiration` option), or after a certain amount of time has passed since the +key was last modified (using the `expirationTtl` option). + +Once the expiration time of an expiring key is reached, it will be deleted +from the system. After its deletion, attempts to read the key will behave as +if the key does not exist. + +:::note +Expiration targets that are less than 60 seconds into the future are not +supported. This is true for both expiration methods. +::: + +#### Create expiring keys + +To create expiring keys, set `expiration` in the `put()` options to a number +representing the seconds since epoch, or set `expirationTtl` in the `put()` +options to a number representing the seconds from now: + +```javascript +// Expire at a specific time (seconds since epoch) +await kv.put("session-key", "session-data", { + expiration: Math.floor(Date.now() / 1000) + 3600 // 1 hour from now +}); + +// Expire after a duration (TTL in seconds) +await kv.put("cache-key", "cached-data", { + expirationTtl: 300 // 5 minutes from now +}); +``` + +### Metadata + +To associate metadata with a key-value pair, set `metadata` in the `put()` +options to an object (serializable to JSON): + +```javascript +await kv.put("user-profile", JSON.stringify(userData), { + metadata: { + createdBy: "admin", + version: 1, + tags: ["user", "profile"] + } +}); +``` + +You can later retrieve this metadata using the `getWithMetadata()` method. + +### Rate limits + +KV Store has a maximum of 1 write to the same key per second. Writes made to +the same key within 1 second may cause rate limiting errors. + +You should not write more than once per second to the same key. Consider +consolidating your writes to a key within a Function invocation to a single +write, or wait at least 1 second between writes. + +### Storing large data with streams + +For large payloads, use `ReadableStream` to stream data efficiently: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const dataSizeInKB = 500; + const totalSize = dataSizeInKB * 1024; + const chunkSize = 64 * 1024; // 64KB chunks + + 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("large-file", stream); + + return new Response("Large data stored", { status: 201 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Related + +- [Read key-value pairs](/en/documentation/runtime/api-reference/kv-store/read/) +- [Delete key-value pairs](/en/documentation/runtime/api-reference/kv-store/delete/) +- [KV Store API overview](/en/documentation/runtime/api-reference/kv-store/) diff --git a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx index f98d613920..a5d2931f52 100644 --- a/src/content/docs/en/pages/guides/kv-store/manage-data.mdx +++ b/src/content/docs/en/pages/guides/kv-store/manage-data.mdx @@ -2,16 +2,16 @@ title: How to manage KV Store with Functions description: >- Learn how to store, retrieve, and delete data using KV Store within your - edge functions. -meta_tags: 'kv store, storage, key-value, edge functions, data' + functions. +meta_tags: 'kv store, storage, key-value, functions, data' namespace: documentation_products_kv_store_manage_edge_functions permalink: /documentation/products/guides/kv-store/manage-with-functions/ --- import LinkButton from 'azion-webkit/linkbutton' -This guide shows you how to interact with KV Store from your edge functions to -store, retrieve, and delete key-value data at the edge. +This guide shows you how to interact with KV Store from your functions to +store, retrieve, and delete key-value data. @@ -21,17 +21,17 @@ store, retrieve, and delete key-value data at the edge. Before you begin, make sure you have: -- [Functions enabled](/en/documentation/products/build/edge-application/edge-functions/) in your edge application. +- [Functions enabled](/en/documentation/products/build/edge-application/edge-functions/) in your application. - A KV Store namespace created via Console or API. --- ## Creating a function to interact with KV Store -Follow these steps to create an edge function that communicates with KV Store: +Follow these steps to create a function that communicates with KV Store: 1. Access [Azion Console](https://console.azion.com). -2. On the upper-left corner, select **Functions** in the **Edge Libraries** section. +2. On the upper-left corner, select **Functions**. 3. Click **+ Function**. 4. Enter a name for your function, for example: `kv-store-handler`. 5. Delete the placeholder code in the editor. @@ -309,7 +309,7 @@ addEventListener("fetch", (event) => { ## Instantiating the function -After creating your function, you need to instantiate it in your edge application: +After creating your function, you need to instantiate it in your application: diff --git a/src/content/docs/en/pages/guides/kv-store/redis-compatibility.mdx b/src/content/docs/en/pages/guides/kv-store/redis-compatibility.mdx new file mode 100644 index 0000000000..67ed0f8179 --- /dev/null +++ b/src/content/docs/en/pages/guides/kv-store/redis-compatibility.mdx @@ -0,0 +1,326 @@ +--- +title: How to use KV Store with Redis-compatible SDK +description: >- + Learn how to use the Azion KV SDK with a Redis-like interface for seamless + integration with your applications. +meta_tags: 'kv store, redis, sdk, key-value, client, compatibility' +namespace: documentation_products_kv_store_redis_compatibility +permalink: /documentation/products/guides/kv-store/redis-compatibility/ +--- + +import LinkButton from 'azion-webkit/linkbutton' + +The Azion KV SDK provides a Redis-like client interface for interacting with +KV Store. This makes it easier to migrate existing applications that use Redis +patterns and provides a familiar developer experience. + + + +--- + +## Requirements + +Before you begin, make sure you have: + +- An [Azion account](https://console.azion.com/signup). +- A KV Store namespace created via Console or API. +- Node.js 18+ or a compatible JavaScript runtime. + +--- + +## Installing the SDK + +Install the Azion SDK using npm: + +```bash +npm install azion +``` + +--- + +## Creating a client + +The SDK uses a Redis-like client pattern with chainable methods: + +```typescript +import { createClient } from 'azion/kv'; + +// Create and connect a client +const client = await createClient() + .on('error', (err) => console.error('KV Client Error:', err)) + .connect(); +``` + +### Client options + +You can customize the client with options: + +```typescript +const client = await createClient({ + namespace: 'my-namespace', + apiToken: 'my-token', +}) + .on('error', (err) => console.error('KV Error:', err)) + .connect(); +``` + +| Option | Type | Description | +|--------|------|-------------| +| `namespace` | string | The KV Store namespace to use | +| `apiToken` | string | Your Azion API token (required for API provider) | + +--- + +## Storing data + +Use the `set` method to store values: + +```typescript +// Simple set +await client.set('user:123', 'John Doe'); + +// Set with expiration (10 seconds) +await client.set('session:abc', 'session-data', { + expiration: { + type: 'EX', + value: 10, + }, +}); + +// Set with metadata +await client.set('config:theme', 'dark', { + metadata: { + updatedBy: 'admin', + version: 1 + }, +}); + +// Set with both expiration and metadata +await client.set('cache:api-response', JSON.stringify(data), { + expiration: { + type: 'EX', + value: 300, // 5 minutes + }, + metadata: { + source: 'external-api', + cached_at: Date.now() + }, +}); +``` + +### Expiration types + +| Type | Description | +|------|-------------| +| `EX` | Expiration time in seconds | +| `PX` | Expiration time in milliseconds | +| `EXAT` | Unix timestamp in seconds | +| `PXAT` | Unix timestamp in milliseconds | + +--- + +## Retrieving data + +Use the `get` method to retrieve values: + +```typescript +// Simple get +const value = await client.get('user:123'); +console.log(value); // 'John Doe' + +// Returns null if key doesn't exist +const missing = await client.get('non-existent'); +console.log(missing); // null +``` + +### Retrieving with metadata + +Use `getWithMetadata` to get both the value and its metadata: + +```typescript +const result = await client.getWithMetadata('config:theme'); +console.log(result.value); // 'dark' +console.log(result.metadata); // { updatedBy: 'admin', version: 1 } +``` + +--- + +## Deleting data + +Use `delete` or `del` to remove keys: + +```typescript +await client.delete('user:123'); +// or +await client.del('user:123'); +``` + +--- + +## Hash operations + +The SDK provides Redis-compatible hash operations for working with field-value pairs: + +### hSet / HSET + +Store a field-value pair: + +```typescript +await client.hSet('user:profile:123', 'name', 'John Doe'); +await client.hSet('user:profile:123', 'email', 'john@example.com'); +await client.hSet('user:profile:123', 'role', 'admin'); + +// Uppercase alias also available +await client.HSET('user:profile:123', 'status', 'active'); +``` + +### hGetAll / HGETALL + +Get all fields and values: + +```typescript +const profile = await client.hGetAll('user:profile:123'); +console.log(profile); +// { name: 'John Doe', email: 'john@example.com', role: 'admin', status: 'active' } + +// Uppercase alias +const data = await client.HGETALL('user:profile:123'); +``` + +### hVals / HVALS + +Get all values (without field names): + +```typescript +const values = await client.hVals('user:profile:123'); +console.log(values); +// ['John Doe', 'john@example.com', 'admin', 'active'] + +// Uppercase alias +const vals = await client.HVALS('user:profile:123'); +``` + +--- + +## Provider detection + +The SDK automatically detects the runtime environment and selects the appropriate provider: + +- **Native provider**: Used when running inside Azion Functions runtime +- **API provider**: Used when running outside Azion (local development, external servers) + +You can check which provider is being used: + +```typescript +const providerType = client.getProviderType(); +console.log(providerType); // 'native' or 'api' +``` + +--- + +## Error handling + +The SDK uses an event-based error handling pattern: + +```typescript +const client = await createClient() + .on('error', (err) => { + console.error('KV Error:', err.message); + // Handle error (retry, fallback, etc.) + }) + .connect(); +``` + +You can also use try-catch for individual operations: + +```typescript +try { + await client.set('key', 'value'); +} catch (error) { + console.error('Failed to set value:', error); +} +``` + +--- + +## Disconnecting + +Always disconnect when you're done: + +```typescript +await client.disconnect(); +// or +await client.quit(); +``` + +--- + +## Complete example + +Here's a complete example showing common operations: + +```typescript +import { createClient } from 'azion/kv'; + +async function main() { + // Create and connect client + const client = await createClient({ + namespace: 'my-app', + }) + .on('error', (err) => console.error('KV Error:', err)) + .connect(); + + try { + // Store user data + await client.set('user:1', JSON.stringify({ name: 'Alice', age: 30 }), { + expiration: { type: 'EX', value: 3600 }, // 1 hour + metadata: { created: Date.now() }, + }); + + // Store user profile using hash operations + await client.hSet('profile:1', 'theme', 'dark'); + await client.hSet('profile:1', 'language', 'en'); + await client.hSet('profile:1', 'notifications', 'true'); + + // Retrieve user data + const userData = await client.get('user:1'); + console.log('User:', JSON.parse(userData)); + + // Retrieve with metadata + const result = await client.getWithMetadata('user:1'); + console.log('Created at:', result.metadata.created); + + // Get all profile settings + const profile = await client.hGetAll('profile:1'); + console.log('Profile:', profile); + + // Clean up + await client.delete('user:1'); + + } finally { + await client.disconnect(); + } +} + +main().catch(console.error); +``` + +--- + +## Redis method mapping + +| Redis Command | SDK Method | Description | +|---------------|------------|-------------| +| `GET` | `get(key)` | Get a value | +| `SET` | `set(key, value, options?)` | Set a value | +| `DEL` | `delete(key)` / `del(key)` | Delete a key | +| `HSET` | `hSet(key, field, value)` / `HSET(...)` | Set hash field | +| `HGETALL` | `hGetAll(key)` / `HGETALL(key)` | Get all hash fields | +| `HVALS` | `hVals(key)` / `HVALS(key)` | Get all hash values | + +--- + +## Next steps + +- Learn more about [KV Store](/en/documentation/products/store/kv-store/) +- Explore [managing KV Store with Functions](/en/documentation/products/guides/kv-store/manage-with-functions/) diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index b275a9e90b..082b8b3645 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -2,8 +2,8 @@ title: KV Store description: >- KV Store is a distributed key-value storage service that runs across Azion's - edge network, providing low-latency data persistence and retrieval. -meta_tags: 'kv, storage, key, distributed, queries, edge, key-value' + network, providing low-latency data persistence and retrieval. +meta_tags: 'kv, storage, key, distributed, queries, key-value' namespace: docs_kv_store permalink: /documentation/products/store/kv-store/ --- @@ -16,9 +16,12 @@ import LinkButton from 'azion-webkit/linkbutton' KV Store is a distributed key-value storage service that runs across Azion's -edge network. It lets you persist and retrieve small pieces of data with very +network. It lets you persist and retrieve small pieces of data with very low latency from anywhere your users are, without managing servers. +The JavaScript API is designed to be compatible with the Cloudflare Workers KV +API, making it easier to migrate existing applications to Azion's platform. + Typical use cases include: - Session and authentication tokens @@ -38,7 +41,7 @@ independent set of keys. Here's how the system operates: - Data is organized into **namespaces** that contain independent sets of keys. - Each item is addressed by a **key** that is unique within its namespace. - Values can be stored as **text**, **JSON**, **ArrayBuffer**, or **ReadableStream**. -- Data is replicated across Azion edge nodes to maximize availability and read performance. +- Data is replicated across Azion nodes to maximize availability and read performance. - Single-key operations are atomic per key. Multi-key transactions aren't supported. --- @@ -54,8 +57,8 @@ independent set of keys. Here's how the system operates: ## Data resilience -KV Store uses a distributed architecture with replication across Azion edge -nodes. New writes are accepted at the edge and propagated to replicas to ensure +KV Store uses a distributed architecture with replication across Azion +nodes. New writes are accepted and propagated to replicas to ensure durability and high availability. Reads are served from the closest healthy replica to minimize latency. @@ -134,7 +137,7 @@ curl -X GET "https://api.azion.com/v4/workspace/kv/namespaces/{namespace}" \ ## Interacting with KV Store via Functions -You can interact with KV Store directly from your edge functions using the +You can interact with KV Store directly from your functions using the `Azion.KV` class. The examples below illustrate common patterns for creating, reading, updating, and deleting data. @@ -439,8 +442,8 @@ The `Azion.KV` class provides the following methods: | Method | Parameters | Returns | Description | | ------ | ---------- | ------- | ----------- | | `put(key, value, options?)` | `key`: string
`value`: string \| object \| ArrayBuffer \| ReadableStream
`options`: { metadata?, expiration?, expirationTtl? } | `Promise` | Stores a value | -| `get(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise` | Retrieves a value | -| `getWithMetadata(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise<{value, metadata}>` | Retrieves value with metadata | +| `get(key, type?, options?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream"
`options`: { cacheTtl? } | `Promise` | Retrieves a value | +| `getWithMetadata(key, type?, options?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream"
`options`: { cacheTtl? } | `Promise<{value, metadata}>` | Retrieves value with metadata | | `delete(key)` | `key`: string | `Promise` | Deletes a key | ### Put options @@ -451,6 +454,12 @@ The `Azion.KV` class provides the following methods: | `expiration` | number | Unix timestamp (seconds) when the key expires | | `expirationTtl` | number | Time-to-live in seconds from now | +### Get options + +| Option | Type | Description | +| ------ | ---- | ----------- | +| `cacheTtl` | number | Time in seconds to cache the result locally (minimum 60 seconds) | + ### Get types | Type | Returns | Description | @@ -473,6 +482,8 @@ These are the **default limits**: | Metadata size | Up to 1024 bytes (JSON-serialized) | | Value size | Up to 25 MB per item | | Namespace name length | 3-63 characters | +| Minimum `expirationTtl` | 60 seconds | +| Minimum `cacheTtl` | 60 seconds | These are the **default limits** for each Service Plan: @@ -483,3 +494,13 @@ These are the **default limits** for each Service Plan: | Maximum storage per account | 5 GB | 50 GB | 300 GB | 300 GB | --- + +## Limitations + +The following operations are **not supported**: + +- **List keys**: There is no `list()` method to enumerate keys within a namespace. Design your application to track keys externally if needed. +- **Multi-key transactions**: Operations are atomic per key, but there is no support for transactions spanning multiple keys. +- **Namespace management from functions**: Namespaces must be created and managed via the [Azion API](https://api.azion.com/) or Console, not from within functions. + +--- diff --git a/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx new file mode 100644 index 0000000000..78a79a8990 --- /dev/null +++ b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/delete.mdx @@ -0,0 +1,180 @@ +--- +title: Excluir pares chave-valor +description: >- + Para remover um par chave-valor do KV Store, chame o método delete() na sua + instância KV. +meta_tags: 'kv store, api, functions, excluir, delete, armazenamento' +namespace: documentation_runtime_kv_store_delete +permalink: /documentacao/runtime/api-reference/kv-store/delete/ +menu_namespace: runtimeMenu +--- + +Para remover um par chave-valor do KV Store, chame o método `delete()` na sua +instância KV: + +```javascript +await kv.delete(key); +``` + +## Exemplo + +Um exemplo de exclusão de um par chave-valor de dentro de uma Function: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + try { + await kv.delete("sessao-usuario"); + + return new Response("Chave excluída com sucesso", { status: 200 }); + } catch (e) { + return new Response(e.message, { status: 500 }); + } +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Referência + +### Método `delete()` + +Para remover um par chave-valor, chame o método `delete()` na sua instância KV: + +```javascript +await kv.delete(key); +``` + +#### Parâmetros + +| Parâmetro | Tipo | Descrição | +|-----------|------|-----------| +| `key` | `string` | A chave do par KV a ser excluído. | + +#### Resposta + +| Resposta | Tipo | Descrição | +|----------|------|-----------| +| `response` | `Promise` | Uma Promise que resolve quando a exclusão é concluída. | + +O método `delete()` retorna uma Promise que você deve usar `await` para +verificar a exclusão bem-sucedida. + +--- + +## Orientações + +### Excluindo chaves inexistentes + +Excluir uma chave que não existe não lançará um erro. A operação é concluída +com sucesso independentemente de a chave existir: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Isso terá sucesso mesmo se a chave não existir + await kv.delete("chave-inexistente"); + + return new Response("Operação de exclusão concluída", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Consistência eventual + +Como todas as operações do KV Store, exclusões são eventualmente consistentes. +Após excluir uma chave: + +- A exclusão é imediatamente visível na mesma localização da rede global. +- Outras localizações ainda podem ver o valor antigo por até 60 segundos (ou a + duração de qualquer `cacheTtl` que foi definido ao ler a chave). + +### Exclusão condicional + +Você pode querer verificar se uma chave existe antes de excluí-la, ou executar +lógica adicional: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + const key = "sessao-usuario"; + + // Verificar se a chave existe antes de excluir + const value = await kv.get(key, "text"); + + if (value === null) { + return new Response("Chave não encontrada", { status: 404 }); + } + + // Executar exclusão + await kv.delete(key); + + return new Response("Chave excluída", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Excluindo múltiplas chaves + +Para excluir múltiplas chaves, você pode usar `Promise.all()`: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const chavesParaExcluir = ["chave1", "chave2", "chave3"]; + + await Promise.all(chavesParaExcluir.map(key => kv.delete(key))); + + return new Response("Todas as chaves excluídas", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Excluindo namespaces + +Para excluir um namespace inteiro (não apenas uma chave), use o método estático +`Azion.KV.delete()`: + +```javascript +async function handleRequest(request) { + const namespaceName = "meu-namespace"; + + // Excluir o namespace inteiro + await Azion.KV.delete(namespaceName); + + return new Response("Namespace excluído", { status: 200 }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +:::caution +Excluir um namespace remove todos os pares chave-valor dentro dele. Esta +operação não pode ser desfeita. +::: + +--- + +## Relacionados + +- [Escrever pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/write/) +- [Ler pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/read/) +- [Visão geral da API KV Store](/pt-br/documentacao/runtime/api-reference/kv-store/) diff --git a/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx new file mode 100644 index 0000000000..b7c876615a --- /dev/null +++ b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/index.mdx @@ -0,0 +1,87 @@ +--- +title: API KV Store +description: >- + A API KV Store fornece métodos para armazenar, recuperar e excluir pares + chave-valor de dentro de suas Functions. +meta_tags: 'kv store, api, functions, chave-valor, armazenamento' +namespace: documentation_runtime_kv_store_api +permalink: /documentacao/runtime/api-reference/kv-store/ +menu_namespace: runtimeMenu +--- + +A API KV Store permite que suas Functions interajam com o armazenamento +chave-valor distribuído da Azion diretamente do runtime. Isso possibilita +persistência e recuperação de dados com baixa latência sem chamadas de API externas. + +## Inicializando o cliente KV + +Você pode inicializar o cliente KV usando o construtor ou o método `open`: + +```javascript +// Usando o namespace padrão +const kv = new Azion.KV(); + +// Usando um namespace específico +const kv = new Azion.KV("meu-namespace"); + +// Usando o método open (assíncrono) +const kv = await Azion.KV.open("meu-namespace"); +``` + +## Métodos disponíveis + +A classe `Azion.KV` fornece os seguintes métodos para operações de dados: + +| Método | Descrição | Referência | +|--------|-----------|------------| +| `put(key, value, options?)` | Armazena um par chave-valor | [Escrever pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/write/) | +| `get(key, type?, options?)` | Recupera um valor pela chave | [Ler pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/read/) | +| `getWithMetadata(key, type?, options?)` | Recupera um valor com seus metadados | [Ler pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/read/) | +| `delete(key)` | Exclui um par chave-valor | [Excluir pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/delete/) | + +## Gerenciamento de namespaces + +| Método | Descrição | +|--------|-----------| +| `new Azion.KV()` | Cria uma instância KV usando o namespace padrão | +| `new Azion.KV(name)` | Cria uma instância KV para o namespace especificado | +| `Azion.KV.open(name)` | Abre um namespace de forma assíncrona | +| `Azion.KV.delete(name)` | Exclui um namespace | + +:::note +Namespaces devem ser criados via [API da Azion](https://api.azion.com/) ou Console antes de poderem ser usados em Functions. Você não pode criar namespaces de dentro de Functions. +::: + +## Tipos de valores suportados + +O KV Store suporta os seguintes tipos de valores: + +| Tipo | Descrição | +|------|-----------| +| `string` | Dados de texto (codificados em UTF-8) | +| `object` | Objetos serializáveis em JSON (automaticamente convertidos para string) | +| `ArrayBuffer` | Dados binários | +| `ReadableStream` | Dados em streaming para valores grandes | + +## Limites + +| Limite | Valor | +|--------|-------| +| Tamanho da chave | Até 512 bytes (UTF-8) | +| Tamanho do valor | Até 25 MB por item | +| Tamanho dos metadados | Até 1024 bytes (JSON-serializado) | +| Taxa de gravação por chave | Até 1 gravação por segundo para a mesma chave | +| Mínimo `expirationTtl` | 60 segundos | +| Mínimo `cacheTtl` | 60 segundos | + +## Consistência eventual + +O KV Store usa consistência eventual. 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`) para serem visíveis em outras +localizações. + +## Documentação relacionada + +- [Referência do KV Store](/pt-br/documentacao/produtos/store/kv-store/) +- [Como gerenciar KV Store com Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/) diff --git a/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx new file mode 100644 index 0000000000..5e8f71ed27 --- /dev/null +++ b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/read.mdx @@ -0,0 +1,359 @@ +--- +title: Ler pares chave-valor +description: >- + Para obter o valor de uma chave específica, chame o método get() na sua + instância KV. +meta_tags: 'kv store, api, functions, ler, get, armazenamento' +namespace: documentation_runtime_kv_store_read +permalink: /documentacao/runtime/api-reference/kv-store/read/ +menu_namespace: runtimeMenu +--- + +Para obter o valor de uma chave específica, chame o método `get()` na sua +instância KV: + +```javascript +// Ler chave individual +const value = await kv.get(key); + +// Ler múltiplas chaves +const values = await kv.get(keys); +``` + +O método `get()` retorna uma promise que você pode usar `await` para obter o valor. + +Se você solicitar uma única chave como string, receberá uma única resposta na +promise. Se a chave não for encontrada, a promise resolverá com o valor literal +`null`. + +Você também pode solicitar um array de chaves. O valor de retorno será um +objeto com pares chave-valor, onde chaves não encontradas têm valores `null`. + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + try { + // Ler chave única, retorna valor ou null + const value = await kv.get("primeira-chave", "text"); + + // Ler múltiplas chaves, retorna objeto com valores + const values = await kv.get(["primeira-chave", "segunda-chave"], "text"); + + // Ler chave única com metadados + const valueWithMetadata = await kv.getWithMetadata("primeira-chave", "text"); + + // Ler múltiplas chaves com metadados + const valuesWithMetadata = await kv.getWithMetadata(["primeira-chave", "segunda-chave"], "text"); + + return new Response(JSON.stringify({ + value: value, + values: values, + valueWithMetadata: valueWithMetadata, + valuesWithMetadata: valuesWithMetadata + }), { + headers: { "Content-Type": "application/json" } + }); + } catch (e) { + return new Response(e.message, { status: 500 }); + } +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +:::note +Os métodos `get()` e `getWithMetadata()` podem retornar valores desatualizados. +Se uma chave foi lida recentemente em uma determinada localização, gravações ou +atualizações na chave feitas em outras localizações podem levar até 60 segundos +(ou a duração do `cacheTtl`) para serem exibidas. +::: + +--- + +## Referência + +Os seguintes métodos são fornecidos para ler do KV Store: + +- [get()](#método-get) +- [getWithMetadata()](#método-getwithmetadata) + +### Método `get()` + +Use o método `get()` para obter um único valor, ou múltiplos valores se forem +fornecidas múltiplas chaves. + +#### Solicitar uma única chave + +Para obter o valor de uma única chave, chame o método `get()` na sua instância KV: + +```javascript +await kv.get(key, type?, options?); +``` + +##### Parâmetros + +| Parâmetro | Tipo | Descrição | +|-----------|------|-----------| +| `key` | `string` | A chave do par KV. | +| `type` | `"text"` \| `"json"` \| `"arrayBuffer"` \| `"stream"` | Opcional. O tipo do valor a ser retornado. `text` é o padrão. | +| `options` | `{ cacheTtl?: number }` | Opcional. Objeto contendo a propriedade `cacheTtl`. | + +##### Opções + +| Opção | Tipo | Descrição | +|-------|------|-----------| +| `cacheTtl` | `number` | Tempo em segundos para armazenar o resultado em cache localmente. O valor mínimo é 60. | + +##### Resposta + +| Resposta | Tipo | Descrição | +|----------|------|-----------| +| `response` | `Promise` | O valor para o par KV solicitado, ou `null` se não encontrado. | + +O tipo de resposta depende do parâmetro `type`: + +| Tipo | Retorna | +|------|---------| +| `"text"` | Uma `string` (padrão) | +| `"json"` | Um objeto decodificado de uma string JSON | +| `"arrayBuffer"` | Uma instância de `ArrayBuffer` | +| `"stream"` | Um `ReadableStream` | + +#### Solicitar múltiplas chaves + +Para obter os valores de múltiplas chaves, chame o método `get()` com um array: + +```javascript +await kv.get(keys, type?); +``` + +##### Parâmetros + +| Parâmetro | Tipo | Descrição | +|-----------|------|-----------| +| `keys` | `string[]` | As chaves dos pares KV. | +| `type` | `"text"` \| `"json"` | Opcional. O tipo do valor a ser retornado. `text` é o padrão. | + +##### Resposta + +| Resposta | Tipo | Descrição | +|----------|------|-----------| +| `response` | `Promise` | Um objeto com pares chave-valor. Chaves não encontradas têm valores `null`. | + +--- + +### Método `getWithMetadata()` + +Use o método `getWithMetadata()` para obter um único valor junto com seus +metadados, ou múltiplos valores com seus metadados. + +#### Solicitar uma única chave com metadados + +Para obter o valor de uma chave junto com seus metadados: + +```javascript +await kv.getWithMetadata(key, type?, options?); +``` + +Metadados são um valor serializável que você anexa a cada entrada KV ao usar `put()`. + +##### Parâmetros + +| Parâmetro | Tipo | Descrição | +|-----------|------|-----------| +| `key` | `string` | A chave do par KV. | +| `type` | `"text"` \| `"json"` \| `"arrayBuffer"` \| `"stream"` | Opcional. O tipo do valor a ser retornado. `text` é o padrão. | +| `options` | `{ cacheTtl?: number }` | Opcional. Objeto contendo a propriedade `cacheTtl`. | + +##### Resposta + +| Resposta | Tipo | Descrição | +|----------|------|-----------| +| `response` | `Promise<{ value: string \| object \| ArrayBuffer \| ReadableStream \| null, metadata: object \| null }>` | Um objeto contendo o valor e os metadados. | + +Se não houver metadados associados ao par chave-valor solicitado, `null` será +retornado para metadata. + +#### Solicitar múltiplas chaves com metadados + +Para obter os valores de múltiplas chaves junto com seus metadados: + +```javascript +await kv.getWithMetadata(keys, type?); +``` + +##### Parâmetros + +| Parâmetro | Tipo | Descrição | +|-----------|------|-----------| +| `keys` | `string[]` | As chaves dos pares KV. | +| `type` | `"text"` \| `"json"` | Opcional. O tipo do valor a ser retornado. `text` é o padrão. | + +##### Resposta + +| Resposta | Tipo | Descrição | +|----------|------|-----------| +| `response` | `Promise` | Um objeto com chaves mapeadas para objetos `{ value, metadata }`. | + +--- + +## Orientações + +### Parâmetro type + +Para valores simples, use o tipo padrão `text` que fornece seu valor como uma +`string`. Por conveniência, um tipo `json` também é especificado que converterá +um valor JSON em um objeto antes de retorná-lo. Para valores grandes, use +`stream` para solicitar um `ReadableStream`. Para valores binários, use +`arrayBuffer` para solicitar um `ArrayBuffer`. + +Para valores grandes, a escolha do `type` pode ter um efeito notável na latência +e uso de CPU. Para referência, o `type` pode ser ordenado do mais rápido ao mais +lento como `stream`, `arrayBuffer`, `text` e `json`. + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + // Obter como texto (padrão) + const textValue = await kv.get("minha-chave", "text"); + + // Obter como JSON (automaticamente parseado) + const jsonValue = await kv.get("minha-chave", "json"); + console.log(jsonValue.someProperty); + + // Obter como ArrayBuffer + const bufferValue = await kv.get("minha-chave", "arrayBuffer"); + const decoder = new TextDecoder("utf-8"); + const decodedString = decoder.decode(bufferValue); + + // Obter como ReadableStream + const streamValue = await kv.get("minha-chave", "stream"); + + return new Response(textValue); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Parâmetro cacheTtl + +`cacheTtl` é um parâmetro que define o tempo em segundos que um resultado KV +é armazenado em cache na localização da rede global onde é acessado. + +Definir o tempo em segundos é útil para reduzir a latência de leitura fria em +chaves que são lidas com pouca frequência. `cacheTtl` é útil se seus dados são +escritos uma vez ou raramente. + +:::note[Leituras quentes e frias] +Uma leitura quente significa que os dados estão em cache localmente. Uma +leitura fria significa que os dados não estão em cache, então devem ser +buscados dos armazenamentos centrais. Tanto pares chave-valor existentes +quanto pares chave-valor inexistentes (lookups negativos) são armazenados +em cache. +::: + +`cacheTtl` não é recomendado se seus dados são atualizados frequentemente e +você precisa ver as atualizações logo após serem escritas, porque gravações +de outras localizações da rede global não serão visíveis até que o valor em +cache expire. + +O valor mínimo para `cacheTtl` é 60 segundos. + +```javascript +// Armazenar o resultado em cache por 5 minutos +const value = await kv.get("chave-config", "json", { cacheTtl: 300 }); +``` + +### Tratando chaves inexistentes + +Quando uma chave não existe, `get()` retorna `null`: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const value = await kv.get("chave-inexistente", "text"); + + if (value === null) { + return new Response("Chave não encontrada", { status: 404 }); + } + + return new Response(value); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Lendo streams + +Para valores grandes armazenados como streams, processe os dados incrementalmente: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const stream = await kv.get("arquivo-grande", "stream"); + + if (stream instanceof ReadableStream) { + const decoder = new TextDecoder(); + let text = ""; + + for await (const chunk of stream) { + text += decoder.decode(chunk, { stream: true }); + } + text += decoder.decode(); + + console.log(`Recuperados ${text.length} caracteres`); + } + + // Ou retorne o stream diretamente na resposta + return new Response(stream); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +### Trabalhando com metadados + +Recupere tanto o valor quanto os metadados em uma única chamada: + +```javascript +async function handleRequest(request) { + const kv = new Azion.KV(); + + const result = await kv.getWithMetadata("perfil-usuario", "json"); + + console.log("Valor:", result.value); + console.log("Metadados:", result.metadata); + + if (result.metadata && result.metadata.version) { + console.log("Versão:", result.metadata.version); + } + + return new Response(JSON.stringify(result), { + headers: { "Content-Type": "application/json" } + }); +} + +addEventListener("fetch", (event) => { + event.respondWith(handleRequest(event.request)); +}); +``` + +--- + +## Relacionados + +- [Escrever pares chave-valor](/pt-br/documentacao/runtime/api-reference/kv-store/write/) +- [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/) diff --git a/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx new file mode 100644 index 0000000000..b5dd6e5f19 --- /dev/null +++ b/src/content/docs/pt-br/pages/devtools/azion-edge-runtime/api-reference/kv-store/write.mdx @@ -0,0 +1,231 @@ +--- +title: Escrever pares chave-valor +description: >- + 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. +meta_tags: 'kv store, api, functions, escrever, put, armazenamento' +namespace: documentation_runtime_kv_store_write +permalink: /documentacao/runtime/api-reference/kv-store/write/ +menu_namespace: runtimeMenu +--- + +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` | 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/) diff --git a/src/content/docs/pt-br/pages/guias/kv-store/compatibilidade-redis.mdx b/src/content/docs/pt-br/pages/guias/kv-store/compatibilidade-redis.mdx new file mode 100644 index 0000000000..cad266e639 --- /dev/null +++ b/src/content/docs/pt-br/pages/guias/kv-store/compatibilidade-redis.mdx @@ -0,0 +1,326 @@ +--- +title: Como usar KV Store com SDK compatível com Redis +description: >- + Aprenda como usar o SDK Azion KV com uma interface similar ao Redis para + integração simplificada com suas aplicações. +meta_tags: 'kv store, redis, sdk, chave-valor, cliente, compatibilidade' +namespace: documentation_products_kv_store_redis_compatibility +permalink: /documentacao/produtos/guias/kv-store/compatibilidade-redis/ +--- + +import LinkButton from 'azion-webkit/linkbutton' + +O SDK Azion KV fornece uma interface de cliente similar ao Redis para interagir +com o KV Store. Isso facilita a migração de aplicações existentes que usam +padrões Redis e proporciona uma experiência familiar para desenvolvedores. + + + +--- + +## Requisitos + +Antes de começar, certifique-se de ter: + +- Uma [conta Azion](https://console.azion.com/signup). +- Um namespace do KV Store criado via Console ou API. +- Node.js 18+ ou um runtime JavaScript compatível. + +--- + +## Instalando o SDK + +Instale o SDK da Azion usando npm: + +```bash +npm install azion +``` + +--- + +## Criando um cliente + +O SDK usa um padrão de cliente similar ao Redis com métodos encadeáveis: + +```typescript +import { createClient } from 'azion/kv'; + +// Criar e conectar um cliente +const client = await createClient() + .on('error', (err) => console.error('Erro do Cliente KV:', err)) + .connect(); +``` + +### Opções do cliente + +Você pode personalizar o cliente com opções: + +```typescript +const client = await createClient({ + namespace: 'meu-namespace', + apiToken: 'meu-token', +}) + .on('error', (err) => console.error('Erro KV:', err)) + .connect(); +``` + +| Opção | Tipo | Descrição | +|-------|------|-----------| +| `namespace` | string | O namespace do KV Store a ser usado | +| `apiToken` | string | Seu token da API Azion (obrigatório para provider API) | + +--- + +## Armazenando dados + +Use o método `set` para armazenar valores: + +```typescript +// Set simples +await client.set('user:123', 'John Doe'); + +// Set com expiração (10 segundos) +await client.set('session:abc', 'dados-sessao', { + expiration: { + type: 'EX', + value: 10, + }, +}); + +// Set com metadados +await client.set('config:theme', 'dark', { + metadata: { + updatedBy: 'admin', + version: 1 + }, +}); + +// Set com expiração e metadados +await client.set('cache:api-response', JSON.stringify(data), { + expiration: { + type: 'EX', + value: 300, // 5 minutos + }, + metadata: { + source: 'external-api', + cached_at: Date.now() + }, +}); +``` + +### Tipos de expiração + +| Tipo | Descrição | +|------|-----------| +| `EX` | Tempo de expiração em segundos | +| `PX` | Tempo de expiração em milissegundos | +| `EXAT` | Timestamp Unix em segundos | +| `PXAT` | Timestamp Unix em milissegundos | + +--- + +## Recuperando dados + +Use o método `get` para recuperar valores: + +```typescript +// Get simples +const value = await client.get('user:123'); +console.log(value); // 'John Doe' + +// Retorna null se a chave não existir +const missing = await client.get('inexistente'); +console.log(missing); // null +``` + +### Recuperando com metadados + +Use `getWithMetadata` para obter tanto o valor quanto seus metadados: + +```typescript +const result = await client.getWithMetadata('config:theme'); +console.log(result.value); // 'dark' +console.log(result.metadata); // { updatedBy: 'admin', version: 1 } +``` + +--- + +## Excluindo dados + +Use `delete` ou `del` para remover chaves: + +```typescript +await client.delete('user:123'); +// ou +await client.del('user:123'); +``` + +--- + +## Operações de hash + +O SDK fornece operações de hash compatíveis com Redis para trabalhar com pares campo-valor: + +### hSet / HSET + +Armazena um par campo-valor: + +```typescript +await client.hSet('user:profile:123', 'name', 'John Doe'); +await client.hSet('user:profile:123', 'email', 'john@example.com'); +await client.hSet('user:profile:123', 'role', 'admin'); + +// Alias em maiúsculas também disponível +await client.HSET('user:profile:123', 'status', 'active'); +``` + +### hGetAll / HGETALL + +Obtém todos os campos e valores: + +```typescript +const profile = await client.hGetAll('user:profile:123'); +console.log(profile); +// { name: 'John Doe', email: 'john@example.com', role: 'admin', status: 'active' } + +// Alias em maiúsculas +const data = await client.HGETALL('user:profile:123'); +``` + +### hVals / HVALS + +Obtém todos os valores (sem os nomes dos campos): + +```typescript +const values = await client.hVals('user:profile:123'); +console.log(values); +// ['John Doe', 'john@example.com', 'admin', 'active'] + +// Alias em maiúsculas +const vals = await client.HVALS('user:profile:123'); +``` + +--- + +## Detecção de provider + +O SDK detecta automaticamente o ambiente de execução e seleciona o provider apropriado: + +- **Provider nativo**: Usado quando executando dentro do runtime de Functions da Azion +- **Provider API**: Usado quando executando fora da Azion (desenvolvimento local, servidores externos) + +Você pode verificar qual provider está sendo usado: + +```typescript +const providerType = client.getProviderType(); +console.log(providerType); // 'native' ou 'api' +``` + +--- + +## Tratamento de erros + +O SDK usa um padrão de tratamento de erros baseado em eventos: + +```typescript +const client = await createClient() + .on('error', (err) => { + console.error('Erro KV:', err.message); + // Tratar erro (retry, fallback, etc.) + }) + .connect(); +``` + +Você também pode usar try-catch para operações individuais: + +```typescript +try { + await client.set('key', 'value'); +} catch (error) { + console.error('Falha ao definir valor:', error); +} +``` + +--- + +## Desconectando + +Sempre desconecte quando terminar: + +```typescript +await client.disconnect(); +// ou +await client.quit(); +``` + +--- + +## Exemplo completo + +Aqui está um exemplo completo mostrando operações comuns: + +```typescript +import { createClient } from 'azion/kv'; + +async function main() { + // Criar e conectar cliente + const client = await createClient({ + namespace: 'minha-app', + }) + .on('error', (err) => console.error('Erro KV:', err)) + .connect(); + + try { + // Armazenar dados do usuário + await client.set('user:1', JSON.stringify({ name: 'Alice', age: 30 }), { + expiration: { type: 'EX', value: 3600 }, // 1 hora + metadata: { created: Date.now() }, + }); + + // Armazenar perfil do usuário usando operações de hash + await client.hSet('profile:1', 'theme', 'dark'); + await client.hSet('profile:1', 'language', 'pt-br'); + await client.hSet('profile:1', 'notifications', 'true'); + + // Recuperar dados do usuário + const userData = await client.get('user:1'); + console.log('Usuário:', JSON.parse(userData)); + + // Recuperar com metadados + const result = await client.getWithMetadata('user:1'); + console.log('Criado em:', result.metadata.created); + + // Obter todas as configurações do perfil + const profile = await client.hGetAll('profile:1'); + console.log('Perfil:', profile); + + // Limpar + await client.delete('user:1'); + + } finally { + await client.disconnect(); + } +} + +main().catch(console.error); +``` + +--- + +## Mapeamento de métodos Redis + +| Comando Redis | Método SDK | Descrição | +|---------------|------------|-----------| +| `GET` | `get(key)` | Obtém um valor | +| `SET` | `set(key, value, options?)` | Define um valor | +| `DEL` | `delete(key)` / `del(key)` | Exclui uma chave | +| `HSET` | `hSet(key, field, value)` / `HSET(...)` | Define campo de hash | +| `HGETALL` | `hGetAll(key)` / `HGETALL(key)` | Obtém todos os campos do hash | +| `HVALS` | `hVals(key)` / `HVALS(key)` | Obtém todos os valores do hash | + +--- + +## Próximos passos + +- Saiba mais sobre o [KV Store](/pt-br/documentacao/produtos/store/kv-store/) +- Explore [gerenciar KV Store com Functions](/pt-br/documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/) diff --git a/src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx b/src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx index d97e7519a8..e080e0cc19 100644 --- a/src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx +++ b/src/content/docs/pt-br/pages/guias/kv-store/gerenciar-com-funcoes.mdx @@ -2,16 +2,16 @@ title: Como gerenciar KV Store com Functions description: >- Aprenda como armazenar, recuperar e excluir dados usando KV Store dentro de - suas edge functions. -meta_tags: 'kv store, armazenamento, chave-valor, edge functions, dados' + suas functions. +meta_tags: 'kv store, armazenamento, chave-valor, functions, dados' namespace: documentation_products_kv_store_manage_edge_functions permalink: /documentacao/produtos/guias/kv-store/gerenciar-com-funcoes/ --- import LinkButton from 'azion-webkit/linkbutton' -Este guia mostra como interagir com o KV Store a partir de suas edge functions -para armazenar, recuperar e excluir dados chave-valor no edge. +Este guia mostra como interagir com o KV Store a partir de suas functions +para armazenar, recuperar e excluir dados chave-valor. @@ -21,17 +21,17 @@ para armazenar, recuperar e excluir dados chave-valor no edge. Antes de começar, certifique-se de ter: -- [Functions habilitadas](/pt-br/documentacao/produtos/build/edge-application/edge-functions/) em sua edge application. +- [Functions habilitadas](/pt-br/documentacao/produtos/build/edge-application/edge-functions/) em sua application. - Um namespace do KV Store criado via Console ou API. --- ## Criando uma função para interagir com o KV Store -Siga estes passos para criar uma edge function que se comunica com o KV Store: +Siga estes passos para criar uma function que se comunica com o KV Store: 1. Acesse o [Azion Console](https://console.azion.com). -2. No canto superior esquerdo, selecione **Functions** na seção **Edge Libraries**. +2. No canto superior esquerdo, selecione **Functions**. 3. Clique em **+ Function**. 4. Digite um nome para sua função, por exemplo: `kv-store-handler`. 5. Exclua o código placeholder no editor. @@ -309,7 +309,7 @@ addEventListener("fetch", (event) => { ## Instanciando a função -Após criar sua função, você precisa instanciá-la em sua edge application: +Após criar sua função, você precisa instanciá-la em sua application: diff --git a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx index e023154c4a..9866d59e73 100644 --- a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx +++ b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx @@ -2,9 +2,9 @@ title: KV Store description: >- KV Store é um serviço de armazenamento de chave-valor distribuído que opera - na rede de edge da Azion, fornecendo persistência e recuperação de dados com + na rede da Azion, fornecendo persistência e recuperação de dados com baixa latência. -meta_tags: 'kv, armazenamento, chave, distribuído, consultas, edge, chave-valor' +meta_tags: 'kv, armazenamento, chave, distribuído, consultas, chave-valor' namespace: docs_kv_store permalink: /documentacao/produtos/store/kv-store/ --- @@ -17,10 +17,13 @@ import LinkButton from 'azion-webkit/linkbutton' KV Store é um serviço de armazenamento de chave-valor distribuído que opera em -toda a rede de edge da Azion. Ele permite que você persista e recupere pequenos +toda a rede da Azion. Ele permite que você persista e recupere pequenos pedaços de dados com latência muito baixa de qualquer lugar onde seus usuários estejam, sem precisar gerenciar servidores. +A API JavaScript foi projetada para ser compatível com a API do Cloudflare Workers +KV, facilitando a migração de aplicações existentes para a plataforma da Azion. + Casos de uso típicos incluem: - Sessões e tokens de autenticação @@ -40,7 +43,7 @@ independente de chaves. Veja como o sistema opera: - Os dados são organizados em **namespaces** que contêm conjuntos independentes de chaves. - Cada item é endereçado por uma **chave** que é única dentro de seu namespace. - Os valores podem ser armazenados como **texto**, **JSON**, **ArrayBuffer** ou **ReadableStream**. -- Os dados são replicados entre os edge nodes da Azion para maximizar a disponibilidade e o desempenho de leitura. +- Os dados são replicados entre os nodes da Azion para maximizar a disponibilidade e o desempenho de leitura. - Operações de chave única são atômicas por chave. Transações de múltiplas chaves não são suportadas. --- @@ -56,8 +59,8 @@ independente de chaves. Veja como o sistema opera: ## Resiliência de dados -O KV Store usa uma arquitetura distribuída com replicação entre os edge nodes -da Azion. Novas gravações são aceitas no edge e propagadas para réplicas para +O KV Store usa uma arquitetura distribuída com replicação entre os nodes +da Azion. Novas gravações são aceitas e propagadas para réplicas para garantir durabilidade e alta disponibilidade. Leituras são servidas da réplica saudável mais próxima para minimizar a latência. @@ -136,7 +139,7 @@ curl -X GET "https://api.azion.com/v4/workspace/kv/namespaces/{namespace}" \ ## Interação com KV Store via Functions -Você pode interagir com o KV Store diretamente de suas edge functions usando a +Você pode interagir com o KV Store diretamente de suas functions usando a classe `Azion.KV`. Os exemplos abaixo ilustram padrões comuns para criar, ler, atualizar e excluir dados. @@ -441,8 +444,8 @@ A classe `Azion.KV` fornece os seguintes métodos: | Método | Parâmetros | Retorna | Descrição | | ------ | ---------- | ------- | --------- | | `put(key, value, options?)` | `key`: string
`value`: string \| object \| ArrayBuffer \| ReadableStream
`options`: { metadata?, expiration?, expirationTtl? } | `Promise` | Armazena um valor | -| `get(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise` | Recupera um valor | -| `getWithMetadata(key, type?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream" | `Promise<{value, metadata}>` | Recupera valor com metadados | +| `get(key, type?, options?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream"
`options`: { cacheTtl? } | `Promise` | Recupera um valor | +| `getWithMetadata(key, type?, options?)` | `key`: string \| string[]
`type`: "text" \| "json" \| "arrayBuffer" \| "stream"
`options`: { cacheTtl? } | `Promise<{value, metadata}>` | Recupera valor com metadados | | `delete(key)` | `key`: string | `Promise` | Exclui uma chave | ### Opções do put @@ -453,6 +456,12 @@ A classe `Azion.KV` fornece os seguintes métodos: | `expiration` | number | Timestamp Unix (segundos) quando a chave expira | | `expirationTtl` | number | Time-to-live em segundos a partir de agora | +### Opções do get + +| Opção | Tipo | Descrição | +| ----- | ---- | --------- | +| `cacheTtl` | number | Tempo em segundos para armazenar o resultado em cache localmente (mínimo 60 segundos) | + ### Tipos do get | Tipo | Retorna | Descrição | @@ -475,6 +484,8 @@ Estes são os **limites padrão**: | Tamanho dos metadados | Até 1024 bytes (JSON-serializado) | | Tamanho do valor | Até 25 MB por item | | Comprimento do nome do namespace | 3-63 caracteres | +| Mínimo `expirationTtl` | 60 segundos | +| Mínimo `cacheTtl` | 60 segundos | Estes são os **limites padrão** para cada Plano de Serviço: @@ -485,3 +496,13 @@ Estes são os **limites padrão** para cada Plano de Serviço: | Armazenamento máximo por conta | 5 GB | 50 GB | 300 GB | 300 GB | --- + +## Limitações + +As seguintes operações **não são suportadas**: + +- **Listar chaves**: Não existe um método `list()` para enumerar chaves dentro de um namespace. Projete sua aplicação para rastrear chaves externamente, se necessário. +- **Transações de múltiplas chaves**: Operações são atômicas por chave, mas não há suporte para transações que abrangem múltiplas chaves. +- **Gerenciamento de namespaces a partir de functions**: Namespaces devem ser criados e gerenciados via [API da Azion](https://api.azion.com/) ou Console, não de dentro de functions. + +--- From 7784d8ab1c7701d1af4942e0618e3d97d3b648e9 Mon Sep 17 00:00:00 2001 From: Vitor-Azion Date: Tue, 10 Feb 2026 15:27:34 -0300 Subject: [PATCH 11/11] docs: update KV Store namespace limits to 1000 across all service plans Update namespace limits from varying values (10/50/200) to a unified limit of 1000 namespaces for all service plans (Developer, Business, Enterprise, and Mission Critical) in both English and Portuguese documentation. --- .../en/pages/main-menu/reference/store/kv-store/kv-store.mdx | 2 +- .../pages/menu-principal/referencia/store/kv-store/kv-store.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx index 082b8b3645..0d1034f2ef 100644 --- a/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx +++ b/src/content/docs/en/pages/main-menu/reference/store/kv-store/kv-store.mdx @@ -489,7 +489,7 @@ These are the **default limits** for each Service Plan: | Scope | Developer | Business | Enterprise | Mission Critical | | ----- | --------- | -------- | ---------- | ---------------- | -| Namespaces | 10 | 50 | 200 | 200 | +| Namespaces | 1000 | 1000 | 1000 | 1000 | | Maximum file size | 200 MB | 500 MB | 2 GB | 2 GB | | Maximum storage per account | 5 GB | 50 GB | 300 GB | 300 GB | diff --git a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx index 9866d59e73..c06d67a36a 100644 --- a/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx +++ b/src/content/docs/pt-br/pages/menu-principal/referencia/store/kv-store/kv-store.mdx @@ -491,7 +491,7 @@ Estes são os **limites padrão** para cada Plano de Serviço: | Escopo | Developer | Business | Enterprise | Mission Critical | | ------ | --------- | -------- | ---------- | ---------------- | -| Namespaces | 10 | 50 | 200 | 200 | +| Namespaces | 1000 | 1000 | 1000 | 1000 | | Tamanho máximo do arquivo | 200 MB | 500 MB | 2 GB | 2 GB | | Armazenamento máximo por conta | 5 GB | 50 GB | 300 GB | 300 GB |