Použití FaunaDB pro živé počítadla v deletemydata.io

Když uživatelé procházejí web, chtějí vědět, že obsah, který čtou, je spolehlivý a důvěryhodný. V roce 2009 Facebook spustil tlačítko „sdílet“ pro vydavatele, které zobrazovalo analýzu článků, kolikrát byl článek sdílen na Facebooku. V roce 2010 rychle následoval twitter s vlastním tlačítkem „tweet“. A v příštích několika letech se objevilo několik dalších tlačítek „sdílení“ jako jedno z Pinterestu pro „připnutí“. Hlavním důvodem, proč vydavatelé používají tato tlačítka „sdílení“, je poskytnout návštěvníkovi webu pocit důvěry, že ostatní četli a považovali obsah za užitečný. Je to stádová mentalita, že pokud to četli mnozí před vámi, pak tady musí být něco v pořádku.

deletemydata.io si klade za cíl nabídnout jediné spolehlivé místo na webu, kde zjistíte, jak cokoli odstranit. Abychom zvýšili spolehlivost a faktor důvěry mezi návštěvníky, chtěl jsem přijmout stejnou strategii růstu – ukázat živé počítadlo uživatelů, kteří považovali obsah za hodnotný. A oni říkají, že obsah je užitečný, kliknutím na jednoduché tlačítko Ano/Ne pro Bylo to užitečné? V dolní části stránky.

V tomto článku se podělím o to, jak jsem implementoval toto živé počítadlo pomocí svého stávajícího technologického zásobníku s využitím FaunaDB jednoduchým a efektivním způsobem. Nejprve vám pomůže porozumět technologickému zásobníku deletemydata.io.

deletemydata.io tech stack

Tři pilíře mého stacku jsou:

  • Netlify
  • React-Static
  • Imgix – Hostování obrázků

Netlify je nejlepší platforma, kterou jsem doposud viděl pro vytváření webových stránek, pokud jste vývojář. React-Static je generátor statických stránek, který využívá principy JAMStack. JAMStack je terminologie používaná pro předběžné vykreslování souborů a jejich poskytování prostřednictvím CDN bez nutnosti mít backend server. Má mnoho výhod oproti tradičnímu způsobu používání serverů k vytváření a vykreslování stejné stránky znovu a znovu.

Možnosti pro implementaci čítače

Existuje několik způsobů, jak implementovat živé počítadlo. Některé z běžných způsobů jsou:

  • Pomocí panelu nástrojů pro sdílení na Facebooku, který jsem zmínil výše.
  • Použití redis a aktualizace

S panelem nástrojů sdílení fb je implementace extrémně jednoduchá. Vy ale nemáte kontrolu nad designem samotné lišty a museli byste sdílet data svých návštěvníků s facebookem. Tím se můj web otevře pro podporu legislativy GDPR a CCPA pro uživatele.

S redis budete mít kontrolu nad designem na rozdíl od panelu nástrojů. Když nastavujete nový systém, je to hodně časově náročná provozní práce – vyhodnocování mezi GCP a AWS., zpřístupnění systému přístupu k internetu, přidání bezpečnostní vrstvy navrch není triviální, aby nedošlo k jejímu zneužití atd.

Narazil jsem na třetí možnost, která byla šetrnější k mému stávajícímu zásobníku - FaunaDB. I když to bylo něco, s čím jsem dříve nebyl obeznámen, při čtení o podpoře doplňku Netlify pro FaunaDB a jeho nativní podpoře dočasnosti jsem se rozhodl, že stojí za to se na to podívat.

  • Používání FaunaDB

Co je to dočasnost

Dočasnost je koncept nabídky uchování určitého kusu dat. FaunaDB nabízí tuto funkci podporou ttl (time to live) pro každý dokument, který vytvoříte. Nyní je tedy sbírka jednoduše deník se záznamy s časovým razítkem využívající nativní schopnost FaunaDB vynutit si její uchovávání. Každý záznam by vypadal podobně jako ten níže:

id záznam ttl
1 {pageid:xxxxxx} 30 dní

Výše uvedený záznam je dokument, který bude přidán. id a ttl jsou znázorněny jen proto, aby ukázaly, jak by fungovala temporalita.

Chtěl bych jednoduše poskytnout možnost sdělit svým uživatelům - kolik z nich předtím, než jste shledali informace důvěryhodnými a smazali tento účet za poslední měsíc. Pokud tedy pro každou stránku na webu mám záznamy pro uživatele, kteří považují stránku za užitečnou, se vstupním časovým razítkem a v kombinaci s měsíční dobou uchování bych měl být technicky schopen získat # uživatelů, kteří tuto stránku našli užitečné za poslední měsíc.

Tato podpora byla pro deletemydata.io docela důležitá. Kdykoli máte na webu obsah, je důležité, aby byl relevantní. Jako novému uživateli to dává webu větší důvěru, když vím, že informace nejsou zastaralé. V tomto případě sdílíme metriky, které ukazují, že několik dalších smazalo stejný účet, který hledáte, velmi nedávno.

S uváženými možnostmi mohla FaunaDB nabídnout více než ostatní. Bylo pro mě hodně příslibem rychlé vyzkoušení POC k ověření.

Začínáme s Netlify a Faunou

Existuje několik zdrojů pro integraci FaunaDB s vaší aplikací netlify. Níže propojím ty, které jsem použil.

Krok 1:Nainstalujte netlify cli

npm install netlify-cli -g

Krok 2:Vytvořte instanci databáze fauna pro web

netlify addons:create fauna

Add-on "fauna" created for nifty-8fce5d

Krok 3:Vytvořte si účet s faunou

netlify addons:auth fauna

Otevírání adresy URL správce doplňku fauny:
https://dashboard.fauna.com/#auth={auth_token}

Fauna má integraci Oauth s Netlify. To je příjemné, protože si nemusíte vytvářet další účet a můžete se pouze přihlásit pomocí Netlify.

Jakmile to autorizujete, netlify vám „importuje“ db do vašeho účtu fauna.

Přestože ve vaší databázi nic není, budete mít nastavené klíče pro přístup přes aplikaci netlify.

Tyto klíče budou automaticky vloženy pomocí netlify jako addon env proměnná. Můžete to vidět, když netlify dev příkaz ve vašem místním prostředí.

netlify dev
◈ Netlify Dev ◈
◈ Injected addon env var:  FAUNADB_ADMIN_SECRET
◈ Injected addon env var:  FAUNADB_SERVER_SECRET
◈ Injected addon env var:  FAUNADB_CLIENT_SECRET

Než se ponořím příliš hluboko do toho, jak budeme psát kód v netlify, abychom mluvili s faunou, chtěl jsem si vyzkoušet faunu jako jazyk, sémantiku a jak by to ve fauně vypadalo. Fauna shell bylo úžasné místo pro to. Skořápku fauny můžete vidět v řídicím panelu na webu nebo ji spustit lokálně.

Architektura

Každá stránka na deletemydata.io má jedinečný slug. U živého počítadla chceme mít počítadlo na stránku, které bude brát v úvahu i to, že každé počítadlo trvá pouze 30 dní. 30 dní je libovolných, není příliš krátkých na to, aby byly hodnoty počítadla nízké, a příliš dlouhých, aby na uživatele nevzbudil špatný dojem kvůli zastaralému obsahu.

I když s vámi sdílím strukturu db ve fauně, podělím se také o to, jak jsem k vytvoření a zároveň otestování použil shell fauny.

Datový model

Jedna tabulka s jedním polem - pageid obsahující ttl 30 dní pro každý záznam.

Tuto kolekci (nebo tabulku) budeme nazývat odstranění:

CreateCollection({ name: "deletes" }

Chceme, aby klient udělal dvě věci:

  • Vytvořte záznam
  • Načtěte počet

Pokud chcete přidat dokument do sbírky, je to docela jednoduché. Ale také chceme mít u této položky ttl, aby mohla platit dočasnost

Create(Collection("deletes"), {
  data: {
    pageid: "test-1"
  },
  ttl: TimeAdd(Now(), 30, "days")
}

Každý záznam je sám o sobě čítačem. To bude stačit pro první případ použití za předpokladu, že FaunaDB dodrží svůj ttl pro dokument.

Abychom podporovali načítání na ID stránky, musíme vytvořit index pro rychlejší vyhledávání.

CreateIndex({
  name: "deletes_by_pageid",
  source: Collection("deletes"),
  unique: false,
  terms: [{ field: ["data", "pageid"] }]
})

Když tedy nyní zadáte dotaz na počet pro ID stránky, získáme zpět počet existujících dokumentů, které odpovídají této hodnotě

Count(Match(Index("deletes_by_pageid"), "test-1"))

Pamatujte, že použití funkce počítání je riskantní, protože pokud máte velkou sadu dokumentů, můžete překročit limit transakce 30 sekund. Funguje to jako dobrý výchozí bod vzhledem k tomu, že všechny dokumenty mají krátkou životnost, aby byly živé pouze 30 dní.

Po několika testech na dokumentech se zkráceným ttls existovala dostatečná jistota, že to bude fungovat pro tento případ použití. Jedna obava, která s tím může přijít, je, jak rychle se to bude počítat, protože vytváříme nový dokument pro každé ID stránky na zpětnou vazbu (takto víme, že to uživatel považuje za cenné). Ale protože máme index tohoto dokumentu pro pole, vyhledávání bylo docela rychlé.

Funkce Netlify

Nyní, když jsme mohli otestovat, jak to bude vypadat s FaunaDB, jsem se rozhodl implementovat totéž s aplikací. V netlify, podle principů JAMStack, i když nemáte backend, máte přístup ke spouštění funkcí lambda bez serveru, které může váš klient volat.

Průběh vytváření

Takto vypadal datový tok pro vytvoření

Uživatel ===> Zpětná vazba ke kliknutí-ANO ===> Volání smaže-vytvoření ===> Vytvořit dokument

Kód klienta:

const faunadb = require('faunadb')

/* configure faunaDB Client with our secret */
const q = faunadb.query
const client = new faunadb.Client({
  secret: process.env.FAUNADB_SERVER_SECRET
})

/* export our lambda function as named "handler" export */
exports.handler = (event, context, callback) => {
  /* parse the string body into a useable JS object */
  const data = JSON.parse(event.body)
  console.log('Function `deletes-create` invoked', data)
  const item = {
    data: data,
    ttl: q.TimeAdd(q.Now(), 30, "days")
  }
  /* construct the fauna query */
  return client
    .query(q.Create(q.Collection("deletes"), item))
    .then(response => {
          console.log('success', response)
          /* Success! return the response with statusCode 200 */
          return callback(null,{
                statusCode: 200,
                body: JSON.stringify(response)
          })
    })
    .catch(error => {
          console.log('error', error)
          /* Error! return the error with statusCode 400 */
          return callback(null,{
                statusCode: 400,
                body: JSON.stringify(error)
          })
    })
}

Counter flow

Během vykreslování stránka zavolá, aby načetla počet z fauny.

Kód klienta:

const faunadb = require('faunadb')

const q = faunadb.query
const client = new faunadb.Client({
  secret: process.env.FAUNADB_SERVER_SECRET
})

/* export our lambda function as named "handler" export */
exports.handler = (event, context, callback) => {
  /* parse the string body into a useable JS object */
  console.log("Function `deletes-count` invoked")

  if(event && event.queryStringParameters && event.queryStringParameters.pageid) {
    /* construct the fauna query */
    return client.query(q.Count(q.Match(q.Index("deletes_by_pageid"), event.queryStringParameters.pageid)))
    .then((response) => {
          console.log("success", response)
          /* Success! return the response with statusCode 200 */
         return callback(null, {
               statusCode: 200,
               body: JSON.stringify(response)
         })
    }).catch((error) => {
         console.log("error", error)
        /* Error! return the error with statusCode 400 */
        return callback(null, {
              statusCode: 400,
              body: JSON.stringify(error)
        })
    })
  }
  return callback(null, {
    statusCode: 400,
    body: JSON.stringify("No query parameter pageid found")
  })
}

Výroba

Od spuštění těchto dvou funkcí jsou doby odezvy pod 20 ms pro vytvoření i počet dotazů. Několik stránek již bylo uživateli započítáno jako relevantní několik setkrát. Zde je video z výroby:https://www.youtube.com/watch?v=AdTN0KYNz4A

Závěr

FaunaDB se neuvěřitelně snadno používá s netlify a snadno se s ním integruje. Trvalo jen něco málo přes půl dne, než se to dostalo do výroby. Jsem si jistý, že tato architektura se bude muset vyvíjet, jak budou stránky získávat trakci, aby i nadále splňovaly přísné smlouvy SLA. Jedním ze způsobů, jak toho dosáhnout, bude předem agregovat hodnoty a uložit je. Překvapuje mě, že to může fungovat i bez mezipaměti před ním. Je úžasné vidět, že databáze nativně podporují temporalitu hned po vybalení. Je to taková úspora času, která se skvěle hodí k tak výraznému a snadno čitelnému programovacímu jazyku.

Zdroje:

  • Oznámení doplňku FaunaDB pro Netlify
  • netlify/netlify-faunadb-příklad:Použití FaunaDB s funkcemi netlify
  • Prostředí FaunaDB