Egy importáló elküld egy új cikket, majd időtúllépést kap. A kezelő újraindítja a teljes folyamatot, és később két bejegyzés jelenik meg. A probléma abból adódhat, hogy az első kérés mentése már megtörtént, csak a válasz nem jutott vissza a klienshez.
Az időtúllépés ezért bizonytalan kimenetet jelent. A következő lépést a szerveroldali állapot visszaolvasása és az API dokumentált ismétlési szerződése alapján kell kiválasztani. A puszta „próbáld újra” kezelés írási műveleteknél nem mindig biztonságos.
Változatlan azonosítóval tedd ellenőrizhetővé a mentést
Saját mintafolyamatunkban az új cikk azonosítója minta-szamitas-ellenorzese, a létrehozáskor elvárt korábbi revízió pedig 0. Ez azt jelenti, hogy az adott azonosító alatt még nem létezhet korábbi bejegyzés. A szerver ellenőrzi ezt a feltételt, és sikeres mentéskor létrehozza az első revíziót.
Ha a kliens nem kap választ, először ugyanezt az azonosítót olvassa vissza. Ha az első revízió létezik, és tartalma megegyezik a feltöltött adatokkal, a létrehozás sikeresnek tekinthető. Nincs szükség egy második, számozott vagy véletlen azonosítójú cikkre.
Ha a visszaolvasás sem sikerül, az eredmény továbbra is ismeretlen. Ilyenkor a folyamat álljon meg egyértelmű állapotjelzéssel. A bizonytalanságot ne nevezze automatikusan sikertelen mentésnek.
Meglévő cikknél a revíziót is egyeztesd
Egy másik példában egy cikket az 5. revízióból szeretnél módosítani. Közben egy szerkesztő már elmentette a 6. revíziót. Ha a kliens csak az azonosítót használja, felülírhatja a szerkesztő újabb munkáját.
A feltételes mentés az elvárt 5. revíziót is elküldi. A szerver a tényleges 6. revízió miatt konfliktust jelez, és változatlanul hagyja a tartalmat. A kliens ezután megmutathatja az eltérést, de nem növelheti vakon az elvárt számot újabb írás kedvéért.
A JSON-összehasonlító használható a kiinduló, a szerkesztett és az aktuálisan visszaolvasott mezők vizsgálatára. A döntéshez a tartalom kell, a státuszkód önmagában kevés.
A HTTP-módszer nem helyettesíti az alkalmazási szerződést
A HTTP szemantikáját leíró szabvány megkülönbözteti a biztonságos és az idempotens módszereket. Az idempotencia az ismétlés kívánt szerveroldali hatásáról szól; nem jelenti azt, hogy minden válasz vagy naplóbejegyzés azonos lesz.
Egy POST-létrehozás ismételhetőségét az alkalmazásnak külön biztosítania kell, például dokumentált idempotenciakulccsal vagy egyediség- és revíziófeltétellel. Ilyen támogatást nem szabad feltételezni pusztán azért, mert a végpont neve ismerős.
A HTTP-fejléc-elemző a bemásolt válasz értelmezésében segíthet. Hitelesítési kulcsot azonban ne másolj bele nyilvános jelentésbe vagy képernyőképbe. A naplóban csak a szükséges, nem titkos hibakód és műveletazonosító maradjon.
Az import haladását bejegyzésenként őrizd meg
Ötven cikkből például húsz visszaellenőrzötten mentett, egynek bizonytalan a kimenete, huszonkilenc pedig még el sem indult. Ez három külön állapot. Az egész csomagot „sikertelennek” nevezni elveszíti a fontos részleteket.
Folytatáskor először a bizonytalan cikket egyeztesd. A már igazolt húsz bejegyzést ne hozd létre újra. A hátralévő műveletekhez ugyanazok az előkészített azonosítók és változatlan tartalmi ellenőrzőösszegek tartozzanak. A közzététel külön lépés is lehet a vázlatok sikeres ellenőrzése után.
A „még nem található” válasz mellett is futhat az első mentés
Egy külön időrendben a kliens elküldi a létrehozást, majd időtúllépést kap. Az azonnali visszaolvasás még nem talál cikket, az eredeti szerverfolyamat azonban egy pillanattal később befejezi a mentést. A korábbi „nem található” válasz önmagában ezért nem bizonyítja, hogy az első kérés már biztosan nem hajt végre írást. Elosztott rendszerben az olvasási út frissessége is számíthat.
A mintában a védelem az, hogy az azonosító egyedi, és a szerver a 0 elvárt revíziót a létrehozással egyetlen oszthatatlan műveletként ellenőrzi. Ha az első kérés létrehozta az 1. revíziót, a második, ugyanerre a névre és 0 revízióra érkező létrehozás már nem teljesítheti a feltételt. Az eredmény legfeljebb egy létrehozott cikk. A konfliktus után ismét vissza kell olvasni és egyeztetni a tartalmat.
Kliensoldali „előbb megnézem, aztán létrehozom” ellenőrzés szerveroldali egyediség nélkül kevés: két kérés ugyanazt a még üres állapotot láthatja. Hasonló védelmet dokumentált idempotenciakulcs adhat, de annak érvényességi idejét és az eltérő tartalmú újraküldés szabályát is ismerni kell. Az HTTP-szabvány feltételes kérései ehhez kapcsolódó mechanizmusokat írnak le; a saját végpont tényleges támogatása külön ellenőrzendő.
Az ötvenes import példájában, ha a bizonytalan huszonegyedik mentést sikeresen visszaegyeztetted, az állapot 21 igazolt és 29 el nem indított cikk. Ha az eredeti kérés lezárulta és az állapot alapján igazoltan nem történt mentés, a 20 kész mellé 30 még elvégzendő kerül. Ezt az átmenetet a konkrét cikkhez naplózd. A teljes csomag újraindítása egyik esetben sem ad pontosabb állapotot.
Gyakori kérdések
A 401 válasz bizonyítja, hogy a feltöltés működik?
Csak a hitelesítés nélküli vagy elutasított kérés állapotát jelzi. Sikeres mentést a hitelesített írás és az utána végzett visszaolvasás igazol.
Időtúllépés után töröljem a félkésznek gondolt cikket?
Előbb olvasd vissza. Lehet, hogy a mentés teljesen sikerült; bizonyíték nélkül a törlés adatvesztést okozhat.
Konfliktusnál automatikusan a saját változatom legyen az újabb?
Ne írj felül közben módosított tartalmat vakon. Az eltéréseket és a tényleges revíziót össze kell egyeztetni.
Záró tudáspróba
Válassz kérdésenként egy választ. A megoldások ellenőrzése után minden helyes válaszért 1 pontot adj magadnak; a hibás, kihagyott vagy több válasszal megjelölt kérdés 0 pont. Összesen 0–3 pont szerezhető.
1. Időtúllépés után az első visszaolvasás még nem talál cikket. Mi következik ebből?
- A) Az eredeti kérés biztosan már nem menthet.
- B) Csak az, hogy azon az olvasási úton akkor még nem volt látható; az eredeti kérés állapotát és az ismétlés szerződését is tisztázni kell.
- C) Biztonságos új, véletlen azonosítóval létrehozni ugyanazt a cikket.
2. Az első kérés az 1. revíziót már létrehozta. Mit tegyen a szerver a második, azonos nevű, 0 elvárt revíziós létrehozással?
- A) Automatikusan adjon neki új nevet.
- B) Írja felül az első cikket.
- C) Utasítsa el a már nem teljesülő létrehozási feltételt.
3. 20 cikk igazolt, egy bizonytalan, 29 még nem indult. A bizonytalan mentést sikeresen igazolod. Mi az új állapot?
- A) 21 igazolt és 29 még nem indult.
- B) 20 igazolt és 30 újra feltöltendő.
- C) Mind az 50-et elölről kell kezdeni.
Megoldások és pontszám
1. B. A szerverfolyamat később is befejezheti a korábban elküldött írást. A feltételes létrehozás vagy idempotenciakulcs szerveroldali garanciája ezért fontos.
2. C. A 0 azt feltételezi, hogy még nincs korábbi bejegyzés. A szervernek ezt a létrehozással együtt kell ellenőriznie, majd konfliktus után tartalmi visszaegyeztetés következik.
3. A. A bizonytalan egy cikk az igazolt állapotba kerül. A korábban kész húsz változatlanul kész, a hátralévő 29 még nem indult.
3 pont: A bizonytalan válaszból és a szerveroldali feltételből is helyes következő lépést választottál. Saját importnál a kérés és a cikk állapotát külön rögzítsd.
2 pont: Az 1. kérdéshez a későn befejeződő mentés időrendjét, a 2.-hoz az oszthatatlan revíziófeltételt, a 3.-hoz az ötvenes állapottáblát nézd át.
0–1 pont: Írd fel, mit tudsz biztosan a kérésről és a szerverállapotról. Ezután a dokumentált egyediség- vagy idempotenciagarancia alapján döntsd el, mikor küldhető újra a művelet.