Novinkový souhrn #002
Přidal Filip Kalousek dne
Úvod
Jsou to dnes čtyři dny, co Ryan Dahl představil Deno KV -> je nestabilní (1. 5. 2023) key-value databáze, kterou lze použít pro ukládání a načítání dat. Data jsou ukládána jako páry klíč-hodnota, kde klíč je objekt typu Deno.Klíče jsou jedinečné uvnitř databáze a poslední hodnota nastavená pro daný klíč se vrátí při čtení klíče. Klíče lze z databáze smazat, v takovém případě již nebudou vráceny při čtení klíčů.
Hodnoty mohou být jakákoliv strukturovaná serializovatelná hodnota v JavaScriptu (objekty, pole, řetězce, čísla atd.). Speciální hodnota Deno.KvU64 může být použita k ukládání 64bitových neoznačených celých čísel v databázi. Tato speciální hodnota nemůže být vnořena do jiných objektů nebo polí.
Klíče jsou verzovány při zápisu přidělením "verzovací známky" klíči, která se postupně zvyšuje. Verzovací známka reprezentuje verzi daného klíče-hodnoty v databázi v určitém čase a lze ji použít k provádění transakčních operací na databázi bez potřeby uzamčení. To je umožněno atomickými operacemi, které mohou mít podmínky, které zajistí, že operace uspěje pouze v případě, že verzovací známka klíče-hodnoty odpovídá očekávané verzi.
Klíče mají maximální délku 2048 bytů po serializaci. Hodnoty mají maximální délku 64 KiB po serializaci. Serializace klíčů a hodnot je trochu neprůhledná, ale obvykle lze předpokládat, že serializace jakékoli hodnoty má stejnou délku jako výsledný řetězec z JSON serializace téže hodnoty. Pokud jsou tyto limity překročeny, dojde k vyhození výjimky.
Metody
Pro začátek bych asi vypíchnul ty hlavní a těmi jsou:
Set
const db = await Deno.openKv();
const pageViews = await db.get(["pageViews"]); // 121
await db.set(["pageViews"], pageViews.value + 1); // 122
// Nebo
await db.atomic()
.mutate({type: "sum", ["pageViews"], value: new Deno.KvU64(1n)})
.commit(); // 123
Get
Získá hodnotu a razítko verze pro daný klíč z databáze. Pokud pro daný klíč neexistuje žádná hodnota, vrácená položka bude mít nulovou hodnotu a razítko verze.
const db = await Deno.openKv();
const result = await db.get(["pageViews"]);
result.key; // ["pageViews"]
result.value; // 123
result.versionstamp; // "00000000000000010000"
Get Many
Stejný jako metoda Get akorát celé zabalené v poli.
const db = await Deno.openKv();
const result = await db.getMany([["pageViews"], ["statistics"]]);
result[0].key; // ["pageViews"]
result[0].value; // 123
result[1].key; // ["statistics"]
result[1].value; // [{ip: "77.75.79.222", visits: 45}, {ip: "34.120.54.55", visits: 78}]
Delete
Odstraní hodnotu zadaného klíče z databáze. Pokud pro daný klíč neexistuje žádná hodnota, je tato operace neúspěšná.
const db = await Deno.openKv();
await db.delete(["pageViews"]);
Závěr
Deno KV mě celkem nadchlo, teším se až budu tvořit na produkci na nějakém projektu, celý tenhle článek měl v ukázkách pageViews, zkusil jsem si tedy implementovat na vlastní příklad, kde dostupné metody jsou set a reset, je to celé zaobalené ještě jako http client.
- Nastavení hodnoty
parametr ?value=[platné číslo]
- Resetování hodnoty
import { serve } from "https://deno.land/std@0.177.0/http/server.ts";
const db = await Deno.openKv();
interface RouteHandler {
[key: string]: (url: URL) => Promise<{ body: string; status?: number }>;
}
const template = `\n\rtry /reset or /set?value=[your value]`
const routes: RouteHandler = {
"/": async () => {
const pageViews = await db.get(["pageViews"]);
await db.atomic()
.mutate({type: "sum", ["pageViews"], value: new Deno.KvU64(1n)})
.commit();
return { body: `Total views: ${pageViews.value + 1}` + template };
},
"/set": async (url: URL) => {
const value = url.searchParams.get("value");
if (value === null || /^\d+$/.test(value)) {
await db.set(["pageViews"], value ? parseInt(value) : 0);
return { body: `${value}` };
}
return { body: "NOT OK", status: 400 };
},
"/reset": async () => {
await db.set(["pageViews"], 0);
return { body: "OK" };
},
"*": async () => {
return { body: "I'm a teapot", status: 418 };
},
};
serve(async (req: Request) => {
const url = new URL(req.url);
const handler = routes[url.pathname] ?? routes["*"];
const res = await handler(url);
return new Response(res.body, { status: res.status ?? 200 });
});