Blog

Shtypja e Publish dy herë tani publikon vetëm një herë

Tre kërkesa publikimi për të njëjtin aplikacion arritën te API-ja jonë 84 milisekonda larg njëra-tjetrës, dhe secila nisi një deploy të plotë të atij aplikacioni. Ato u përplasën për të njëjtin hosting, disa nga release-et që rezultuan dështuan sepse një tjetër kishte arritur më parë, dhe i vetmi shenjë e dukshme ishte një email “release failed”. Aplikacioni vetë përfundoi mirë. Tani, një publikim që arrin ndërsa një tjetër po ndodh për të njëjtin aplikacion nuk nis një build të dytë. Baza e të dhënave vendos cili kërkesë fiton, dhe të tjerat marrin të vërtetën: një publikim tashmë po ndodh.

Çfarë ndodhi

Kur publikon një aplikacion në Mythex, API-ja regjistron një deployment për të dhe i kërkon orkestratorit tonë, shërbimit që kryen build-et, ta ndërtojë dhe ta lëshojë. Publikimi mund të nisë nga butoni Publish, nga një skedë tjetër shfletuesi, ose nga agjenti kur i kërkon ta publikojë. Një klikim i dyfishtë, dy skeda, ose një kërkesë e agjentit që arrin dy herë mund të prodhojnë më shumë se një publikim për të njëjtin aplikacion në të njëjtin moment.

Në këtë rast, tre arritën brenda 84 ms. Secili nisi një deploy të plotë. Në platformën e hostingut, release-et për të njëjtin aplikacion u krijuan në të njëjtën sekondë, dhe tre prej tyre dështuan sepse të tjerët ishin tashmë në progres. Një release më vonë u ngec, dhe aplikacioni funksionoi më pas.

Kjo e bëri të lehtë të mos e vinte kush re. Përdoruesi pa një aplikacion që punonte. Dështimet dukeshin vetëm si email-e release-failure.

Pse asgjë nuk e ndalonte

Kodi i publikimit kishte me të vërtetë një hap që shikonte deploy-et në progres për projektin. Por ajo që bënte ishte të shënonte çdo deploy në progres si të dështuar përpara se të niste, me arsyen “zëvendësuar nga një publikim i ri”. Ishte menduar për të pastruar build-e të lëna pas nga një proces që u rrëzua.

Në praktikë, një publikim i dytë që arrinte gjatë një build-i e shpallte të parin të vdekur dhe nisej vetë. Të dy ekzekutoheshin deri në fund kundër të njëjtit aplikacion. Nuk kishte kyçje; kishte një hap që aktivisht e pastronte rrugën për një garë.

Kishte edhe një simptomë më të çuditshme për publikimin e parë të një aplikacioni. Pa një regjistrim deployment-i për ta ripërdorur ende, dy publikime të parë njëkohësisht përpiqeshin të fusnin një të tillë. Baza e të dhënave ka një indeks unik mbi emrin e lidhjes së aplikacionit (slug-un, si your-app në your-app.mythex.ai), kështu që futja e dytë dështonte. API-ja e përktheu këtë në “ai emër lidhjeje është i zënë”, duke sugjeruar përdoruesit të riemërtonte një aplikacion që në atë moment po publikohej me sukses nën atë emër.

Rregullimi: kyçja është vetë kërkesa

Tani marrja e regjistrimit të deployment-it është një përditësim i vetëm i kushtëzuar në bazën e të dhënave: merr këtë rresht dhe shëno si duke u ndërtuar vetëm nëse askush nuk po e publikon. Meqenëse është një deklaratë e vetme, baza e të dhënave zgjidh kërkesat që arrijnë në të njëjtën milisekondë. Saktësisht një prej tyre ndryshon rreshtin. Të tjerat shohin që asnjë rresht nuk u ndryshua, ndalen, dhe kurrë nuk arrijnë te orkestratori.

Një kyçje duhet gjithashtu një rrugëdalje kur mbajtësi i saj vdes. Nëse API-ja u rinis në mes të një publikimi, rreshti do të mbetej i shënuar “duke u ndërtuar” përgjithmonë dhe aplikacioni nuk mund të publikohej më. Kështu që një rresht, pronari i të cilit ka pushuar së dërguari heartbeat-e, mund të merret sërish. Publikimi në punë dërgon përditësim të rreshtit çdo 30 sekonda, dhe pesë minuta heshtje llogariten si të vdekur. Ky prag vjen nga heartbeat-i, jo nga një hamendje për sa zgjat një build. Ndërtimi i Dockerfile-it të vet të një përdoruesi mund të zgjasë me të vërtetë shumë, dhe një build i ngadaltë që ende dërgon heartbeat e mban kyçjen e vet.

Hapi që shënonte si të dështuar çdo deploy në progres nuk ekzekutohet më përpara një publikimi. Pastrohen vetëm rreshtat që i la pas një proces i vdekur.

T’i themi të humburit të vërtetën

Kërkesa që humb tani merr një përgjigje të qartë: publish_in_progress, bashkë me ID-në e deployment-it që po ekzekutohet. Çdo vend që mund të nisë një publikim e trajton këtë:

  • Hapësira e punës ndjek build-in që po ekzekutohet në vend që të shfaqë një gabim mbi të.
  • Agjenti i thuhet se një publikim i këtij aplikacioni po ndodh tashmë dhe të presë atë, në vend që t’i thuhet se diçka dështoi, gjë që më parë mund ta nxiste të “rregullojë” një Dockerfile dhe të provojë përsëri.
  • Një përplasje në publikimin e parë për emrin e lidhjes kontrollohet: nëse rreshti që mban emrin është publikimi në progres i këtij projekti, përgjigja është “po publikohet tashmë”, jo “ai emër është i zënë”. Një përplasje reale me një projekt tjetër ende merr mesazhin për riemërim.

Si e kontrolluam

Shkruam një skript riprodhimi që ekzekuton tre publikime të të njëjtit aplikacion njëkohësisht kundër një baze të dhënash reale dhe një orkestratori stub, dhe numëron sa deploy-e i kërkohen orkestratorit. Mbulon një publikim të parë dhe një ripublikim të një aplikacioni live. Përpara rregullimit, numëronte dy deploy-e. Pas tij, një.

Skripti mbulon edhe rrugëdaljen: shënon rreshtin e aplikacionit si duke u ndërtuar pa heartbeat për dhjetë minuta, publikon përsëri, dhe kontrollon që publikimi i ri merr rreshtin dhe ekzekutohet.

Testet njësi mbajnë kyçjen te dy gjërat që duhet të bëjë një kyçje: nga tre ripublikime njëkohësisht, saktësisht një kalon dhe dy të tjerat njoftohen se po ndodh një publikim; dhe një build që pronari i tij vdiq mund të merret nga një tjetër. Një test tjetër kontrollon që një përpjekje e re nuk merr me vete mesazhin e gabimit të përpjekjes së mëparshme.

Çfarë morëm nga kjo

  • Kodi i pastrimit mund të jetë garë e maskuar. “Dështo çdo gjë që është në progres, pastaj nis” duket si higjienë. Me dy thirrës, është secili që anulon tjetrin.
  • Lëre bazën e të dhënave të arbitrojë. Një lexim i ndjekur nga një shkrim lë një boshllëk për një kërkesë tjetër. Një përditësim i vetëm i kushtëzuar nuk lë.
  • Çdo kyçje ka nevojë për skadim të lidhur me gjallërinë. Pa të, një rrëzim kthehet në një aplikacion të ngecur.
  • Mesazhet e gabimit janë udhëzime. “Ai emër është i zënë” i drejtonte njerëzit drejt gabimit. Mesazhi i duhur ishte më i thjeshtë dhe i vërtetë.

Më shumë për publikimin në dokumentacion: si të publikosh. Dhe një rregullim i lidhur: aplikacioni yt i publikuar qëndron gjallë ndërsa e ripublikon.

Mythex · Pricing · Ndërtoni çdo gjë me AI · Shablone faqesh dhe aplikacionesh · Mythex në krahasim · Fjalori i ndërtimit të aplikacioneve me AI · Mjete falas për ndërtimin e aplikacioneve me AI · English

English አማርኛ العربية Български বাংলা Bosanski Català Čeština Dansk Deutsch Ελληνικά Español Español (España) Eesti فارسی Suomi Français Français (Canada) ગુજરાતી हिन्दी Hrvatski Magyar Հայերեն 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 Srpski Svenska Kiswahili தமிழ் తెలుగు ไทย Tagalog Türkçe Українська اردو Tiếng Việt 简体中文 繁體中文(香港) 繁體中文(台灣)