Săriți la conținut

Blog ·

Copilul îl trezește pe părinte

Un flux care cheamă altul poate întreba sau poate fi anunțat. Am construit ambele, iar ceasul de rezervă este o zi, nu cinci minute, dintr-un motiv măsurat.

De Provibr

Un flux poate acum să cheme alt flux. Rularea care cheamă se oprește, rularea chemată pornește, iar când rularea chemată se încheie, rularea care a chemat continuă pe firul ok sau pe firul error.

Toată întrebarea de proiectare din propoziția aceea stă în cuvântul când. Ceva trebuie să bage de seamă că a terminat copilul. Există două feluri de a rândui asta și am ajuns să le avem pe amândouă, într-o anumită ordine, iar al doilea are în el un număr despre care s-a discutat în contradictoriu.

Părintele nu așteaptă, i se spune

Felul firesc de a scrie asta este un părinte care așteaptă. Părintele știe pe care rulare o așteaptă, deci poate să întrebe. Interoghează la fiecare zece secunde, vede dacă s-a încheiat copilul și continuă când s-a încheiat.

Este pe dos, iar motivul este că, de fapt, copilul știe deja. El este cel care trece în starea de încheiat. A-l pune pe părinte să întrebe înseamnă că informația călătorește de la partea care o are către partea care are nevoie de ea printr-o întrebare repetată, iar frecvența acelei întrebări este latența întregii funcții.

Așa că vestește copilul. Când o rulare-copil ajunge într-o stare terminală, ea pune ora de trezire de pe rândul de așteptare care arată spre ea pe acum, iar lucrătorul obișnuit de coadă o ia la următorul lui tact. Este exact mecanismul pe care îl folosește o aprobare omenească: a hotărî pune ora de trezire pe acum. O singură coloană cârmuiește coada și nu există, dinadins, o a doua cale către executor.

Vestirea aceea este o singură instrucțiune: actualizează rândul de așteptare unde identificatorul rulării-copil se potrivește și starea este încă de așteptare.

De ce identificatorul acela este o coloană și nu parte din blocul de stare

Continuarea unei parcurgeri puse în pauză este păstrată ca JSON și ține tot ce îi trebuie parcurgerii ca să se reia: stiva, nodurile vizitate, variabilele, contoarele. Ar fi fost consecvent să punem acolo și identificatorul copilului.

Este în schimb o coloană, iar motivul este direcția. Tot ce se mai află în blocul acela este citit de parcurgere, dinăuntru. Valoarea aceasta este citită din afară, de o rulare-copil care vrea să găsească rândul ce arată spre ea. În bloc, asta înseamnă o baleiere peste fiecare așteptare deschisă din sistem, iar indexul de care ați avea nevoie ca să o faceți ieftină este oricum coloana aceasta.

Cheia străină este pusă pe SET NULL și nu pe CASCADE. Dacă rularea-copil este curățată, așteptarea părintelui nu trebuie să dispară odată cu ea, fiindcă atunci un părinte rămâne suspendat fără nimic care să îl trezească vreodată. Pierderea referinței se poate supraviețui; pierderea rândului, nu.

Ceasul de rezervă este de o zi, iar numărul este argumentul

Vestirea este mecanismul. Ceasul este plasa de siguranță pentru cazul în care vestirea nu sosește niciodată: un container care a căzut la jumătatea încheierii copilului, un rând atins cu mâna.

Valoarea evidentă pentru o plasă de siguranță este ceva mic. Cinci minute par o alegere responsabilă.

Este greșit, iar motivul este ce are voie să facă un copil. O rulare-copil poate să conțină o aprobare omenească, iar o aprobare poate să aibă un termen limită peste treizeci de zile. Cu un ceas de cinci minute, părintele copilului aceluia se trezește de mii de ori de-a lungul acelor treizeci de zile ca să afle că nu s-a schimbat nimic, iar fiecare dintre acele treziri este o cerere HTTP de la poartă către containerul web.

Douăzeci și patru de ore costă cel mult treizeci de tacte fără rost de-a lungul celei mai lungi așteptări pe care o îngăduie produsul și mărginesc paguba unei vestiri într-adevăr pierdute la o singură zi. Acesta este târgul, spus în unitățile care contează: câte cereri costă plasa de siguranță atunci când nu este nimic în neregulă, față de cât timp rămâne nevăzut un eșec adevărat.

Forma generală: un interval de reîncercare nu este „cât de scurt ne putem permite”. Este o funcție de cea mai lungă așteptare îndreptățită, iar dacă nu ați întrebat cât este aceea, intervalul este o presupunere.

Un ceas pe care nu îl puteți scurta este un ceas pe care nu îl puteți dovedi

O plasă de siguranță pornește numai atunci când mecanismul de sub ea a eșuat. Cu intervalul fixat la o zi, ca să arătați că funcționează vă trebuie o zi, așa că runda care a construit-o a livrat ramura aceea ca nedovedită, însemnată cinstit.

Ispita este să o dovediți cu mâna: intrați în baza de date, mutați ora de trezire în trecut, vă uitați cum se reia rularea. Asta dovedește reluarea. Nu dovedește ceasul, fiindcă tocmai ceasul este lucrul pe care l-ați înlocuit.

Așa că intervalul citește o variabilă de mediu, iar cârligul trăiește în sursă, lângă constantă, și nu înăuntrul unui fișier de test. Este folosit de un script cap la cap care îl pune pe câteva secunde, lasă plasa de siguranță să pornească într-adevăr și se uită cum un părinte al cărui copil nu a vestit niciodată nimic își revine de unul singur.

Două însușiri fac cârligul acela sigur de livrat. Poate face intervalul numai mai scurt: valoarea este plafonată față de constanta de producție, deci un mediu prost configurat nu poate niciodată să facă un părinte să aștepte mai mult de o zi. Iar orice nu este un număr pozitiv cade înapoi pe valoarea de producție.

A doua nu este programare defensivă de dragul ei. Dacă vă copiați fișierul nostru de mediu dat ca exemplu, variabila este de față și goală, iar un șir gol nu este nedefinit. Prefăcut în număr, dă zero. Fără sită, un fișier de configurare copiat ar pune intervalul pe zero și ar băga fiecare părinte cu un copil în curs într-o buclă de trezire față de containerul web. Deosebirea dintre șirul gol și nedefinit ne-a mai mușcat, într-un loc unde a făcut ca o rută de descărcare să dea 404.

Două limite, fiecare impusă de două ori

Un flux care cheamă un flux ridică întrebarea unui flux care se cheamă pe sine. Există două limite, recursivitatea și adâncimea, iar fiecare este impusă în două locuri.

Static, atunci când un flux este salvat: graful este parcurs, fluxurile pe care le cheamă sunt rezolvate, iar un ciclu sau un lanț prea adânc este refuzat, cu lanțul numit în eroare. Dinamic, în timpul unei rulări: aceleași două limite din nou, cu propriile lor coduri de refuz.

Amândouă sunt trebuincioase fiindcă fluxurile sunt editate independent. Două fluxuri care, fiecare în parte, sunt în regulă pot deveni un ciclu în clipa în care cineva adaugă o chemare în al doilea, iar nimic nu îl revalidează pe primul. Verificarea statică este cea care dă un mesaj de eroare folositor în clipa în care lucrul mai poate fi încă reparat; verificarea dinamică este cea care chiar se ține.

Adâncimea este o coloană pe rulare și nu ceva calculat parcurgând părinții. Asta merge împotriva liniei pe care o ținem de obicei, anume că tot ce se poate deriva ar trebui derivat. Aici ea nu se ține, fiindcă referința către părinte este pusă pe SET NULL: odată ce o rulare-părinte a fost curățată, lanțul nu mai poate fi parcurs înapoi, iar adâncimea unui copil care rulează ar deveni de necunoscut exact în clipa în care contează.

Ce a măsurat runda următoare

Ramurile pe care proiectarea aceasta le-a lăsat deschise au fost parcurse într-o rundă de mai târziu, iar două dintre ele sunt cele interesante.

O rulare-copil care dispare cu totul: așteptarea își păstrează rândul și își pierde referința, ceasul de rezervă trezește părintele, iar reluarea nu găsește niciun copil și face nodul acela să eșueze cu un motiv anume, în loc să se blocheze. Un graf care nu poate fi citit deloc produce un alt motiv, deci cele două situații se pot deosebi în registrul rulării.

Un subflux înăuntrul unei bucle, în cele două forme care se poartă diferit: un copil care se încheie înăuntrul cererii din care a pornit și un copil care se suspendă singur. Primul nu atinge deloc coada. Al doilea este funcția însăși.

Ce am consemna

  1. Partea care știe ar trebui să spună, nu să fie întrebată. Interogarea repetată vă preface latența într-o valoare de configurare.
  2. Refolosiți calea de trezire pe care o aveți deja. O hotărâre și un copil încheiat sunt același eveniment pentru coadă.
  3. O valoare citită din afara blocului de stare își are locul într-o coloană. Direcția hotărăște asta, nu consecvența.
  4. Puneți pe SET NULL, nu pe CASCADE, atunci când rândul care ar fi șters este singurul fel în care cineva mai poate fi trezit.
  5. Intervalul unei plase de siguranță este o funcție de cea mai lungă așteptare îndreptățită, nu de cât de prompt ați vrea să păreți.
  6. Spuneți târgul în cereri și în ore. Treizeci de tacte irosite față de o zi în care nu se vede nimic este o hotărâre; „cinci minute” este un reflex.
  7. O constantă pe care nu o puteți schimba este o ramură pe care nu o puteți dovedi. Cârligul își are locul lângă constantă.
  8. Lăsați cârligul să facă lucrurile numai mai sigure, și plafonați-l față de valoarea de producție.
  9. O variabilă de mediu goală nu este nedefinită, iar prefacerea ei în număr vă dă zero.
  10. Verificați o limită acolo unde poate fi reparată și acolo unde trebuie să se țină. Grafurile editate independent au nevoie de amândouă.

Ca să fie limpede ce este aceasta: verificarea de îmbinare a rulat 16 din 16 pași fără nicio linie de eșec, suita web a fost 4583 verde, pachetele, poarta și uneltele împreună 7286 verde, parcurgerea 75 verde, verificarea statică de subflux 13 verde, rularea cap la cap față de baza de date de dezvoltare 58 verde, măsurătoarea destinatarilor 4 verde, un test de browser cu un lucrător de poartă adevărat 31 verde, în care o pauză de nouăzeci de secunde s-a reluat după nouăzeci și cinci de secunde, testul de editor 9 verde, iar baleiajul de accesibilitate nu a găsit nimic pe șase pagini. Nedovedite atunci: ceasul de rezervă, un subflux înăuntrul unei bucle, o rulare-copil dispărută și ramura de epuizare a reîncercărilor. Acele patru au fost parcurse în runda următoare.

Din munca de platformă la Provibr. Cum a devenit parcurgerea ceva ce se poate scrie într-un rând se află în fiecare autoapel era în poziție de coadă, iar runda care a ajuns în sfârșit la ramurile pe care aceasta le-a lăsat deschise se află în verde fiindcă nu putea ajunge acolo.

Începeți cu o gazdă și un agent

Creați un cont, instalați agentul cu o singură comandă și conectați primul dumneavoastră host Proxmox. Perioada de probă durează 14 zile și nu cere date de plată.