Blog

A Közzététel kétszeri megnyomása most egyszer közzéteszi

Ugyanarra az appra három közzétételi kérés érkezett az API-nkhoz 84 ezredmásodperces eltéréssel, és mindegyik elindított egy teljes deployt az adott appra. Versenyeztek egymással ugyanarra a tárhelyre, az eredményül kapott kiadások közül többen meghiúsultak, mert egy másik már odaért előttük, és az egyetlen látható jel egy „kiadás sikertelen” email volt — maga az app végül rendben volt. Mostantól az a közzététel, amely egy másik közben érkezik ugyanarra az appra, nem indít második buildet. Az adatbázis dönti el, melyik kérés nyer, a többiek pedig megkapják az igazat: már fut egy közzététel.

Mi történt

Amikor közzéteszel egy appot a Mythexen, az API rögzít egy telepítési rekordot, és megkéri az orchestrátort — a buildeket futtató szolgáltatást —, hogy építse és adja ki. A közzététel indulhat a Közzététel gombról, egy másik böngészőlapról, vagy onnan, hogy az ügynöktől kéred. Egy dupla kattintás, két lap vagy kétszer érkező ügynöki kérés mind több közzétételt eredményezhet ugyanarra az appra, szinte ugyanabban a pillanatban.

Ezúttal három érkezett 84 ms-on belül. Mindegyik teljes deployt futtatott. A tárhelyplatformon ugyanazon az appon belül ugyanabban a másodpercben jöttek létre a kiadások, és háromból több is meghiúsult, mert mások már folyamatban voltak. Egy későbbi kiadás beragadt, de az app utána működött.

Ez tette könnyen elnézhetővé. A felhasználó egy működő appot látott. A hibák csak kiadási hiba-emailekben jelentkeztek.

Miért nem állította meg semmi

A közzétételi kód volt egy lépés, amely megnézte a projekt folyamatban lévő deployjait. De azt tette, hogy minden folyamatban lévő deployt sikertelennek jelölt, mielőtt elindult — „egy új közzététel felülírta” üzenettel. Ez arra szolgált, hogy a megszakadt folyamat által hátrahagyott buildeket takarítsa el.

A gyakorlatban ez azt jelentette, hogy egy második közzététel, amely egy build közben érkezett, halottnak nyilvánította az elsőt, és elindította a sajátját. Mindkettő végigment ugyanazon az appon. Nem volt zár; volt egy lépés, amely aktívan utat nyitott a versenyhelyzetnek.

Az első közzététel egy app életében furcsább tünetet is okozott. Ha nem volt még telepítési rekord, amelyet újra lehetett volna használni, két egyidejű első közzététel is megpróbált egyet beszúrni. Az adatbázisnak egyedi indexe van az app linknevére (a slugra, például sajat-app a sajat-app.mythex.ai-ban), így a második beszúrás sikertelen volt. Az API ezt úgy fordította le, hogy „ez a linknév foglalt” — azt tanácsolva a felhasználónak, hogy nevezze át az appot, amely abban a pillanatban sikeresen publikált ezen a néven.

A javítás: a foglalás a zár

A telepítési rekord foglalása most egyetlen feltételes adatbázis-frissítés: vedd ezt a sort, és jelöld épülőnek csak akkor, ha senki nem publikálja. Mivel ez egyetlen utasítás, az adatbázis ugyanabban az ezredmásodpercben érkező kéréseket is rendez. Pontosan egy kérés változtatja meg a sort. A többiek azt látják, hogy nulla sor változott, leállnak, és soha nem érik el az orchestrátort.

A zárnak van kiút, ha a birtokosa meghal. Ha az API újraindult egy közzététel közben, a sor örökre „épül” állapotban maradna, és az app nem lenne közzétehető. Ezért egy sor, amelynek tulajdonosa már nem küld életjelet — a futó közzététel 30 másodpercenként frissíti a sort, és öt perc csend halottnak számít —, újra foglalható. Ez a küszöb az életjeltől származik, nem egy becslésből, hogy mennyi ideig tart egy build. Egy felhasználó saját Dockerfile-jának buildje jogosan sokáig tarthat, és egy lassú, de még életjelet adó build megtartja a foglalását.

Az a lépés, amely minden folyamatban lévő deployt sikertelennek jelölt a közzététel előtt, már nem fut le. Csak azokat a sorokat takarítjuk el, amelyeket egy halott folyamat hagyott maga után.

A vesztesnek megmondani az igazat

A kérés, amely veszít, most világos választ kap: publish_in_progress, a futó telepítés azonosítójával együtt. A közzétételt elindító helyek mindegyike kezeli ezt:

  • A munkaterület követi a már futó buildet, ahelyett hogy hibát mutatna fölötte.
  • Az ügynök megtudja, hogy az app közzététele már fut, és várjon rá, ahelyett, hogy hibáról értesülne — ami korábban arra késztethette, hogy egy Dockerfile-t „javítson” és újrapróbáljon.
  • Egy első közzététel linknév-ütközését ellenőrizzük: ha a nevet tartó sor ennek a projektnek a saját futó közzétételének sora, a válasz „már publikálunk”, nem „ez a név foglalt”. Egy valódi ütközés egy másik projekttel továbbra is az átnevezés üzenetet kapja.

Hogyan ellenőriztük

Írtunk egy reprodukciós szkriptet, amely egy valódi adatbázissal és egy csonka orchestrátorral egyszerre három közzétételt futtat ugyanarra az appra, és megszámolja, hány deployt kér az orchestrátor. Lefedi az első közzétételt és egy élő app újraközzétételét. A javítás előtt kettőt számolt, utána egyet.

A szkript az eszkalációs utat is lefedi: tíz percig heartbeat nélkül épülőnek jelöli az app sorát, újra közzétesz, és ellenőrzi, hogy az új közzététel megszerzi a sort, és lefut.

Egységtesztek a zárat a két dologra tartják, amit egy zárnak tennie kell: három egyidejű újraközzétételből pontosan egy jut át, a másik kettőnek pedig megmondják, hogy közzététel fut; és egy halott tulajdonos buildje újra foglalható. Egy másik teszt ellenőrzi, hogy egy új kísérlet nem viszi tovább az előző kísérlet hibaüzenetét.

Mit vittünk ebből magunkkal

  • A takarító kód lehet versenyhelyzet álruhában. „Fail mindent ami fut, aztán indíts” higiéniának tűnik. Két hívóval viszont minden hívó megszakítja a másikat.
  • Hagyd, hogy az adatbázis döntsön. Egy olvasás, amelyet írás követ, rést hagy egy másik kérésnek. Egyetlen feltételes frissítés nem.
  • Minden zárnak lejárat kell, amely az életjelhez kötött. Nélküle egy összeomlásból beragadt app lesz.
  • A hibaüzenet utasítás. „Ez a név foglalt” rossz dologra utasította az embereket. A helyes üzenet egyszerűbb volt, és igaz.

A közzétételről többet a dokumentációban olvashatsz: hogyan tegyél közzé. Egy kapcsolódó javítás: az élő app a közzététel alatt is elérhető marad.

Mythex · Pricing · Építs bármit AI-val · Weboldal- és alkalmazássablonok · A Mythex összehasonlítva · AI-alapú alkalmazásépítési szószedet · Ingyenes eszközök AI-alapú alkalmazásépítéshez · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Հայերեն Bahasa Indonesia Íslenska Italiano 日本語 ქართული Қазақ тілі ಕನ್ನಡ 한국어 Lietuvių Latviešu Македонски മലയാളം Монгол मराठी Bahasa Melayu မြန်မာ Norsk bokmål Nederlands ਪੰਜਾਬੀ Polski Português (Brasil) Português (Portugal) Română Русский Slovenčina Slovenščina Soomaali Shqip Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)