{"id":36721,"date":"2019-10-31T22:13:20","date_gmt":"2019-10-31T19:13:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-dark-razvertyvaet-kod-za-50-ms\/"},"modified":"2019-10-31T22:13:20","modified_gmt":"2019-10-31T19:13:20","slug":"kak-dark-razvertyvaet-kod-za-50-ms","status":"publish","type":"post","link":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","title":{"rendered":"Kako Dark implementira kod za 50 ms","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Kako Dark implementira kod za 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/c159a36eb52bf488f3a70ea511690366.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u0160to je br\u017ei razvojni proces, to se br\u017ee razvija tehnolo\u0161ka tvrtka.<\/p>\n<p><\/p>\n<p>Na\u017ealost, moderna aplikacija radi protiv nas \u2014 na\u0161i sustavi moraju se a\u017eurirati u stvarnom vremenu i pritom nikome ne smetati i ne uzrokovati prekide i zastoje. Implementacija u takvim sustavima postaje te\u017eak zadatak i zahtijeva slo\u017eene cjevovode kontinuirane isporuke \u010dak i u malim timovima.<\/p>\n<p><\/p>\n<p>Ovi cjevovodi obi\u010dno imaju usku primjenu, sporo rade i nisu pouzdani. Programeri ih prvo moraju stvoriti ru\u010dno, a zatim njima upravljati, zbog \u010dega tvrtke \u010desto zapo\u0161ljavaju cijele DevOps timove.<\/p>\n<p><\/p>\n<p>Brzina ovih cjevovoda odre\u0111uje brzinu razvoja. U najboljim timovima implementacija traje 5\u201310 minuta, ali obi\u010dno se sve odvija mnogo sporije, a za jednu implementaciju potrebno je nekoliko sati.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>U Darku to traje 50 ms. <em>Pedeset. Milisekundi<\/em>. Dark \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">to je sveobuhvatno rje\u0161enje s programskim jezikom, ure\u0111iva\u010dem i infrastrukturom<\/a><\/noindex>, stvoreno posebno za kontinuiranu isporuku, a svi aspekti Darka, uklju\u010duju\u0107i sam jezik, izgra\u0111eni su s ciljem sigurnog trenutnog implementiranja.<\/p>\n<p><\/p>\n<h3 id=\"pochemu-konveyery-nepreryvnoy-postavki-takie-medlennye\">Za\u0161to su cjevovodi kontinuirane isporuke tako spori?<\/h3>\n<p><\/p>\n<p>Pretpostavimo da imamo web-aplikaciju u Pythonu i ve\u0107 smo stvorili fantasti\u010dan i suvremen cjevovod kontinuirane isporuke. Za programera koji se svakodnevno bavi ovim projektom, implementacija jedne male promjene izgledat \u0107e otprilike ovako:<\/p>\n<p><\/p>\n<h3 id=\"vnesenie-izmeneniy\">Unos promjena<\/h3>\n<p><\/p>\n<ul>\n<li>Stvaranje nove grane u gitu<\/li>\n<li>Unos promjena preko preklopnog prekida\u010da<\/li>\n<li>Modularno testiranje za provjeru promjena s i bez preklopnog prekida\u010da<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pul-rekvest\">Pull zahtjev<\/h3>\n<p><\/p>\n<ul>\n<li>Commit promjena<\/li>\n<li>Slanje promjena u udaljeni repozitorij na githubu<\/li>\n<li>Pull zahtjev<\/li>\n<li>CI se automatski izvodi u pozadini<\/li>\n<li>Recenzija koda<\/li>\n<li>Jo\u0161 nekoliko recenzija, ako je potrebno<\/li>\n<li>Spajanje promjena s master gitom.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"ci-vypolnyaetsya-na-mastere\">CI se izvodi na masteru<\/h3>\n<p><\/p>\n<ul>\n<li>Instalacija frontend ovisnosti preko npm-a<\/li>\n<li>Gradnja i optimizacija HTML+CSS+JS resursa<\/li>\n<li>Pokretanje modularnih i funkcionalnih testova na frontendu<\/li>\n<li>Instalacija ovisnosti Pythona iz PyPI<\/li>\n<li>Pokretanje modularnih i funkcionalnih testova na backendu<\/li>\n<li>Testiranje integracije na oba kraja<\/li>\n<li>Slanje frontend resursa u CDN<\/li>\n<li>Gradnja kontejnera za program Python<\/li>\n<li>Slanje kontejnera u registar<\/li>\n<li>A\u017euriranje Kubernetes manifesta<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"zamena-starogo-koda-novym\">Zamjena starog koda novim<\/h3>\n<p><\/p>\n<ul>\n<li>Kubernetes pokre\u0107e vi\u0161e instanci novog kontejnera<\/li>\n<li>Kubernetes \u010deka da instance postanu operativne<\/li>\n<li>Kubernetes dodaje instance u HTTP ravnote\u017enik optere\u0107enja<\/li>\n<li>Kubernetes \u010deka da se stare instance prestanu koristiti<\/li>\n<li>Kubernetes zaustavlja stare instance<\/li>\n<li>Kubernetes ponavlja ove operacije sve dok nove instance ne zamijene sve stare<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"vklyuchenie-novogo-pereklyuchatelya-funkcii\">Aktivacija novog prekida\u010da funkcionalnosti<\/h3>\n<p><\/p>\n<ul>\n<li>Novi kod se aktivira samo za sebe kako bi se osiguralo da sve funkcioni\u0161e ispravno<\/li>\n<li>Novi kod se aktivira za 10% korisnika, prate se operativne i poslovne metrike<\/li>\n<li>Novi kod se aktivira za 50% korisnika, prate se operativne i poslovne metrike<\/li>\n<li>Novi kod se aktivira za 100% korisnika, prate se operativne i poslovne metrike<\/li>\n<li>Na kraju, ponavljate cijeli postupak kako biste uklonili stari kod i prekida\u010d<\/li>\n<\/ul>\n<p><\/p>\n<p>Proces ovisi o alatima, jeziku i kori\u0161tenju arhitektura usmjerenih na usluge, ali u na\u010delu izgleda ovako. Nije spomenuto implementiranje s migracijom baza podataka, jer to zahtijeva detaljno planiranje, ali dalje \u0107u objasniti kako se time bavi Dark.<\/p>\n<p><\/p>\n<p>Ovdje ima mnogo komponenti, a mnoge od njih lako mogu usporiti, sru\u0161iti se, izazvati privremenu konkurenciju ili oboriti radni sustav.<\/p>\n<p><\/p>\n<p>A po\u0161to su ovi ciklusi gotovo uvijek kreirani za posebne slu\u010dajeve, na njih je te\u0161ko osloniti se. Mnogi imaju dane kada kod nije mogu\u0107e implementirati jer postoje problemi u Dockerfileu, neki od desetaka servisa se sru\u0161e ili je potreban stru\u010dnjak na odmoru.<\/p>\n<p><\/p>\n<p>\u0160tavi\u0161e, mnogi od ovih koraka zapravo ne \u010dine ni\u0161ta korisno. Bili su potrebni ranije, kada smo implementirali kod odmah za korisnike, ali sada imamo prekida\u010de za novi kod, a ovi procesi su se razdvojili. Kao rezultat toga, korak koji implementira kod (stari se zamjenjuje novim) sada je postao samo nepotreban rizik.<\/p>\n<p><\/p>\n<p>Naravno, ovo je vrlo promi\u0161ljen pipeline. Tim koji ga je stvorio nije \u0161tedio vrijeme i novac za brzo implementiranje. Obi\u010dno su pipeline-ovi implementacije mnogo sporiji i nepouzdaniji.<\/p>\n<p><\/p>\n<h3 id=\"realizaciya-nepreryvnoy-postavki-v-dark\">Implementacija kontinuirane isporuke u Dark<\/h3>\n<p><\/p>\n<p>Kontinuirana isporuka je toliko va\u017ena za Dark da smo od samog po\u010detka ciljali na vrijeme kra\u0107e od jedne sekunde. Pregledali smo sve korake u procesu kako bismo uklonili sve suvi\u0161ne, a ostalo dovedeno do savr\u0161enstva. Evo kako smo uklonili korake.<\/p>\n<p><\/p>\n<blockquote><p>Jessie Frazelle (<noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex>) je smislila novu rije\u010d deployless (bez potrebe za implementacijom) na konferenciji Future of Software Development u Rejkjaviku.<\/p><\/blockquote>\n<p>Odmah smo odlu\u010dili da \u0107e Dark biti zasnovan na konceptu 'deployless' (hvala <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex> za neologizam). Deployless ozna\u010dava da se svaki kod trenuta\u010dno implementira i spreman je za kori\u0161tenje u produkciji. Naravno, ne\u0107emo propustiti neispravan ili nepotpun kod (principi sigurnosti \u0107u opisati u nastavku).<\/p>\n<p><\/p>\n<p>Na demonstraciji Dark \u010desto su nas pitali kako smo uspjeli ubrzati implementaciju. \u010cudan \u0432\u043e\u043f\u0440\u043e\u0441. Ljudi vjerojatno misle da smo smislili neku super tehnologiju koja uspore\u0111uje kod, kompajlira ga, pakira u kontejner, pokre\u0107e virtualnu ma\u0161inu, pokre\u0107e kontejner hladno i sve to za 50 ms. Mogu\u0107nost tog tipa je malo vjerojatna. Ali smo razvili poseban motor implementacije kojemu to sve i nije potrebno.<\/p>\n<p><\/p>\n<p>Dark pokre\u0107e interpretere u oblaku. Recimo, pi\u0161ete kod u funkciji ili HTTP-handleru ili doga\u0111aju. \u0160aljemo diff u apstraktno sintakti\u010dko stablo (implementaciju koda koju interno koristi na\u0161 ure\u0111iva\u010d i serveri) na na\u0161e servere, a zatim pokre\u0107emo taj kod kad dobijemo zahtjeve. Tako da implementacija izgleda kao skromni unos u bazu podataka \u2014 trenutna i jednostavna. Implementacija se odvija tako brzo jer uklju\u010duje minimum.<\/p>\n<p><\/p>\n<p>U budu\u0107nosti planiramo u\u010diniti od Darka kompajler infrastrukture koji \u0107e stvarati i pokretati idealnu infrastrukturu za visoke performanse i pouzdanost aplikacija. Trenutna implementacija, naravno, ne\u0107e nestati.<\/p>\n<p><\/p>\n<h2 id=\"bezopasnoe-razvertyvanie\">Sigurna implementacija<\/h2>\n<p><\/p>\n<h3 id=\"strukturirovannyy-redaktor\">Strukturirani ure\u0111iva\u010d<\/h3>\n<p><\/p>\n<p>Kod u Darku pi\u0161e se u ure\u0111iva\u010du Dark. Strukturirani ure\u0111iva\u010d ne dopu\u0161ta sintakti\u010dke gre\u0161ke. U su\u0161tini, u Darku nema ni analizatora. Dok unosite tekst, direktno radimo s apstraktnim sintakti\u010dkim stablom (AST), kao <noindex><a rel=\"nofollow\" href=\"http:\/\/danmidwood.com\/content\/2014\/11\/21\/animated-paredit.html\">Paredit<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ravichugh.github.io\/sketch-n-sketch\/\">Sketch-n-Sketch<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/gregoor.github.io\/tofu\/\">Tofu<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/notes\/kent-beck\/prune-a-code-editor-that-is-not-a-text-editor\/1012061842160013\/\">Prune<\/a><\/noindex> i <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jetbrains.com\/mps\/\">MPS<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Svaki nedovr\u0161eni kod u Darku ima valjanu semantiku izvr\u0161avanja, otprilike kao <noindex><a rel=\"nofollow\" href=\"https:\/\/hazel.org\/\">typed holes u Hazelu<\/a><\/noindex>. Na primjer, ako promijenite poziv funkcije, \u010duvamo staru funkciju dok nova ne postane spremna.<\/p>\n<p><\/p>\n<p>Svaki program u Dark ima svoj smisao, tako da nekompletan kod ne ometa rad zavr\u0161enog.<\/p>\n<p><\/p>\n<h3 id=\"rezhimy-redaktirovaniya\">Na\u010dini ure\u0111ivanja<\/h3>\n<p><\/p>\n<p>K\u00f4d u Darku pi\u0161ete u dva slu\u010daja. Prvi: pi\u0161ete novi k\u00f4d i jedini ste korisnik. Na primjer, radi se u REPL-u, a ostali korisnici nikada ne\u0107e imati pristup tome, ili je to nova HTTP ruta kojoj se nigde ne referencirate. U tom slu\u010daju mo\u017eete raditi bez ikakvih mjera opreza i sada upravo tako radite u razvojnim okru\u017eenju.<\/p>\n<p><\/p>\n<p>Druga situacija: kod se ve\u0107 koristi. Ako kroz kod prolazi promet (funkcije, obrada doga\u0111aja, baze podataka, tipa), treba biti oprezan. U tu svrhu blokiramo sav kori\u0161teni kod i zahtijevamo kori\u0161tenje strukturiranijih alata za njegovo ure\u0111ivanje. O strukturiranim alatima \u0107u govoriti u nastavku: preklopnici funkcija za HTTP obradu i doga\u0111aje, mo\u0107na platforma za migraciju za baze podataka i nova metoda upravljanja verzijama za funkcije i tipove.<\/p>\n<p><\/p>\n<h3 id=\"pereklyuchateli-funkciy\">Preklopnici funkcija<\/h3>\n<p><\/p>\n<p>Jedan od na\u010dina <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">ukloniti suvi\u0161nu slo\u017eenost<\/a><\/noindex> u Darku je rije\u0161iti nekoliko problema jednim rje\u0161enjem. Preklopnici funkcija izvr\u0161avaju mnogo razli\u010ditih zadataka: zamjena lokalnog razvojnog okru\u017eenja, git grane, implementacija koda i, naravno, tradicionalno sporo i kontrolirano objavljivanje novog koda.<\/p>\n<p><\/p>\n<p>Kreiranje i implementacija preklopnika funkcija obavlja se u na\u0161em ure\u0111iva\u010du u jednom koraku. Stvara prazno polje za novi k\u00f4d i pru\u017ea kontrole pristupa starom i novom kodu, kao i gumbe i naredbe za postepeno prelazak na novi kod ili njegovo isklju\u010divanje.<\/p>\n<p><\/p>\n<p>Preklopnici funkcija ugra\u0111eni su u jezik Dark, a \u010dak i nekompletni preklopnici obavljaju svoju funkciju \u2014 ako uvjet u preklopniku nije ispunjen, izvr\u0161it \u0107e se stari blokirani kod.<\/p>\n<p><\/p>\n<h3 id=\"sreda-razrabotki\">Razvojno okru\u017eenje<\/h3>\n<p><\/p>\n<p>Preklopnici funkcija zamjenjuju lokalno razvojno okru\u017eenje. Danas je timovima te\u0161ko pratiti da svi koriste iste verzije alata i knji\u017enica (alati za formatiranje koda, linters, upravitelji paketa, kompajleri, preprocesori, alati za testiranje itd.). S Darkom nije potrebno instalirati ovisnosti lokalno, upravljati lokalnom instalacijom Dockera ili poduzimati druge mjere kako bi se osiguralo barem neko podudaranje izme\u0111u razvojnog i produkcijskog okru\u017eenja. <noindex><a rel=\"nofollow\" href=\"https:\/\/thenewstack.io\/honeycombs-charity-majors-go-ahead-test-in-production\/\">S obzirom na to da je takvo podudaranje ionako nemogu\u0107e,<\/a><\/noindex>, \u010dak se ni ne pretvaramo da te\u017eimo tome.<\/p>\n<p><\/p>\n<p>Umjesto da stvorimo klonirano lokalno okru\u017eenje, preklopnici u Darku stvaraju novu pje\u0161\u010danik u produkciji koja zamjenjuje razvojno okru\u017eenje. U budu\u0107nosti tako\u0111er planiramo stvoriti pje\u0161\u010danik za druge dijelove aplikacije (na primjer, trenutne klonove baza podataka), iako to trenutno ne izgleda toliko va\u017eno.<\/p>\n<p><\/p>\n<h3 id=\"vetki-i-razvertyvaniya\">Grane i implementacije<\/h3>\n<p><\/p>\n<p>Trenutno postoji nekoliko na\u010dina unosa novog koda u sustave: git grane, faza implementacije i preklopnici funkcija. Oni rje\u0161avaju jedan problem u razli\u010ditim dijelovima radnog procesa: git \u2014 u fazama prije implementacije, implementacija \u2014 u trenutku prelaska s starog na novi kod, a preklopnici funkcija \u2014 za kontrolirano pu\u0161tanje novog koda.<\/p>\n<p><\/p>\n<p>Najefikasniji na\u010din su preklopnici funkcija (uz to, najjednostavniji za razumjeti i koristiti). S njima se mo\u017ee potpuno odustati od preostalih dvaju metoda. Osobito je korisno ukloniti implementaciju \u2014 ako ionako koristimo preklopnike funkcija za aktivaciju koda, tada korak prebacivanja servera na novi kod samo stvara dodatne rizike.<\/p>\n<p><\/p>\n<p>Git je te\u0161ko koristiti, posebno po\u010detnicima, i to ozbiljno ograni\u010dava, ali zato ima zgodne grane. Ispravili smo mnoge nedostatke git-a. Dark se mo\u017ee ure\u0111ivati u stvarnom vremenu i omogu\u0107uje suradnju u stilu Google Dokumenata, tako da nije potrebno slati kod i rje\u0111e se mo\u017ee izvoditi rebaziranje i spajanje.<\/p>\n<p><\/p>\n<p>Prekida\u010di funkcija predstavljaju osnovu sigurnog implementiranja. Zajedno s trenuta\u010dnim implementacijama omogu\u0107uju brzo testiranje koncepata u malim dijelovima s niskim rizikom umjesto primjene jedne velike promjene koja mo\u017ee sru\u0161iti sustav.<\/p>\n<p><\/p>\n<h3 id=\"versionirovanie\">Verzionarstvo<\/h3>\n<p><\/p>\n<p>Za promjenu funkcija i tipova koristimo verzioniranje. Ako \u017eelite promijeniti funkciju, Dark stvara novu verziju te funkcije. Zatim mo\u017eete pozvati tu verziju putem prekida\u010da u HTTP ili doga\u0111ajnom handleru. (Ako je ta funkcija duboko u stablu poziva, tijekom toga se stvara nova verzija svake funkcije. \u010cini se kao da je to prekomjerno, ali funkcije se ne mije\u0161aju ako ih ne koristite, tako da to \u010dak ni ne primijetite.)<\/p>\n<p><\/p>\n<p>Iz istih razloga verzioniramo tipove. O na\u0161em sistemu tipova detaljno smo pisali <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">u prethodnom postu<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Zahvaljuju\u0107i verzioniranju funkcija i tipova mo\u017eete postupno uvoditi promjene u aplikaciju. Mo\u017eete provjeriti da svaki pojedini handler radi s novom verzijom, ne morate odmah unijeti sve promjene u aplikacije (ali imamo alate da to brzo u\u010dinite ako to po\u017eelite).<\/p>\n<p><\/p>\n<p>To je mnogo sigurnije nego potpuno implementirati sve odjednom, kako se to trenutno doga\u0111a.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-paketov-i-standartnaya-biblioteka\">Nove verzije paketa i standardna biblioteka<\/h3>\n<p><\/p>\n<p>Kada a\u017eurirate paket u Dark, ne zamjenjujemo odmah kori\u0161tenje svake funkcije ili tipa u cijeloj bazi koda. To nije sigurno. Kod nastavlja koristiti istu verziju koju je koristio, a vi a\u017eurirate kori\u0161tenje funkcija i tipova na novu verziju za svaki pojedina\u010dni slu\u010daj pomo\u0107u prekida\u010da.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/rh\/t3\/4w\/rht34wyibolrgracbz88tnqqhg0.png\"><img decoding=\"async\" alt=\"Kako Dark implementira kod za 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/54fdb566b4bcbc10e06e51c47a3820f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Snimka ekrana dijela automatskog procesa u Darku koja prikazuje dvije verzije funkcije Dict::get. Dict::get_v0 vra\u0107a tip Any (od kojeg se odri\u010demo), a Dict::get_v1 vra\u0107a tip Option.<\/em><\/p>\n<p><\/p>\n<p>\u010cesto pru\u017eamo novu funkciju standardne biblioteke i isklju\u010dujemo stare verzije. Korisnici sa starim verzijama u kodu zadr\u017eavaju pristup njima, ali novi korisnici ih ne\u0107e mo\u0107i dobiti. Planiramo pru\u017eiti alate za prebacivanje korisnika sa starih verzija na nove u jednom koraku, opet uz pomo\u0107 prekida\u010da funkcija.<\/p>\n<p><\/p>\n<p>Dark tako\u0111er pru\u017ea jedinstvenu priliku: dok izvr\u0161avamo va\u0161 radni kod, mo\u017eemo sami testirati nove verzije, uspore\u0111uju\u0107i izlaze za nove i stare zahtjeve, kako bismo vas obavijestili o promjenama. Na kraju, a\u017euriranje paketa, koje se \u010desto izvodi nasumi\u010dno (ili zahtijeva pa\u017eljivo testiranje iz sigurnosnih razloga), predstavlja znatno manje rizika i mo\u017ee se odvijati automatski.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-dark\">Nove verzije Dark<\/h3>\n<p><\/p>\n<p>Prijelaz s Pythona 2 na Python 3 protegao se kroz desetlje\u0107e i jo\u0161 uvijek ostaje problem. Budu\u0107i da kreiramo Dark za kontinuiranu isporuku, potrebno je uzeti u obzir te promjene jezika.<\/p>\n<p><\/p>\n<p>Kada provedemo manje promjene u jeziku, stvaramo novu verziju Dark. Stari kod ostaje u staroj verziji Dark, a novi kod se koristi u novoj verziji. Za prelazak na novu verziju Dark mo\u017eete koristiti preklopnike ili verzije funkcija.<\/p>\n<p><\/p>\n<p>To je osobito korisno, s obzirom na to da je Dark nedavno nastao. Mnoge promjene u jeziku ili biblioteci mogu se pokazati neuspje\u0161nima. Postepeno verzioniranje jezika omogu\u0107uje nam da provodimo manje nadogradnje, odnosno mo\u017eemo ne \u017euriti i odgoditi mnoga jezi\u010dna rje\u0161enja dok ne budemo imali vi\u0161e korisnika, \u0161to podrazumijeva i vi\u0161e informacija.<\/p>\n<p><\/p>\n<h3 id=\"migracii-baz-dannyh\">Migracije baza podataka<\/h3>\n<p><\/p>\n<p>Za sigurnu migraciju baze podataka postoji <noindex><a rel=\"nofollow\" href=\"http:\/\/www.brunton-spall.co.uk\/post\/2014\/05\/06\/database-migrations-done-right\/\">standardna formula<\/a><\/noindex>:<\/p>\n<p><\/p>\n<ul>\n<li>Prepisati kod za podr\u0161ku novim i starim formatima<\/li>\n<li>Pretvoriti sve podatke u novi format<\/li>\n<li>Ukloniti stari pristup podacima<\/li>\n<\/ul>\n<p><\/p>\n<p>Na kraju, migracija baze podataka se produ\u017eava i zahtijeva mnogo resursa. A mi akumuliramo zastarjele sheme, jer \u010dak i jednostavni zadaci, poput ispravljanja imena tablice ili stupca, ne vrijede ulo\u017eenih napora.<\/p>\n<p><\/p>\n<p>Dark ima u\u010dinkovitu platformu za migraciju baza podataka koja (nadamo se) toliko pojednostavljuje proces da \u0107ete prestati strahovati od njega. Sva skladi\u0161ta podataka u Darku (skladi\u0161ta parova \"klju\u010d-vrijednost\" ili trajne he\u0161-tablice) imaju tip. Da biste premjestili skladi\u0161te podataka, jednostavno mu dodijelite novi tip i funkciju povratka i napretka za pretvorbu vrijednosti izme\u0111u dva tipa.<\/p>\n<p><\/p>\n<p>Pristup podacima u Darku odvija se preko verzioniranih imena varijabli. Na primjer, spremi\u0161te podataka Users prvotno \u0107e se zvati Users-v0. Kada se stvori nova verzija s drugim tipom, ime se mijenja u Users-v1. Ako su podaci spremljeni putem Users-v0, a vi im pristupate putem Users-v1, primjenjuje se funkcija vra\u0107anja. Ako su podaci spremljeni putem Users-v1, a vi im pristupate putem Users-v0, primjenjuje se funkcija povratka.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/ui\/sl\/wd\/uislwdrfrvact0d1ts5icnk-4ka.png\"><img decoding=\"async\" alt=\"Kako Dark implementira kod za 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/35743ba246f327ca9e8b71f0069a3800.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Ekran migracije baze podataka s imenima polja stare baze podataka, izrazima vra\u0107anja i povratka te uputama za pokretanje migracije.<\/em><\/p>\n<p><\/p>\n<p>Koristite prekida\u010de zna\u010dajki za usmjeravanje poziva s Users-v0 na verziju Users-v1. To mo\u017eete raditi jedan HTTP handler u isto vrijeme kako biste smanjili rizike, a prekida\u010di tako\u0111er djeluju za pojedina\u010dne korisnike, tako da mo\u017eete testirati da sve radi kako je o\u010dekivano. Kada korisnika Users-v0 vi\u0161e ne bude, Dark automatski u pozadini pretvara sve preostale podatke iz starog formata u novi. \u010cak to ne\u0107ete ni primijetiti.<\/p>\n<p><\/p>\n<h3 id=\"testirovanie\">Testiranje<\/h3>\n<p><\/p>\n<p>Dark je <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">funkcionalni programski jezik sa stati\u010dkim tipiziranjem<\/a><\/noindex> i nepromjenjivim vrijednostima, stoga je povr\u0161ina za testiranje znatno manja u usporedbi s objektno-orijentiranim jezicima s dinami\u010dkim tipiziranjem. No, testirati se mora.<br \/>\nU Darku, ure\u0111iva\u010d automatski pokre\u0107e modularne testove u pozadini za ure\u0111eni kod i prema zadanim postavkama pokre\u0107e te testove za sve prekida\u010de zna\u010dajki. U budu\u0107nosti \u017eelimo automatski provoditi fuzz testing koda koriste\u0107i stati\u010dke tipove kako bismo prona\u0161li gre\u0161ke.<\/p>\n<p><\/p>\n<p>Osim toga, Dark izvr\u0161ava va\u0161u infrastrukturu u produkciji, \u0161to otvara nove mogu\u0107nosti. Automatski pohranjujemo HTTP zahtjeve unutar Dark infrastrukture (dok trenutno pohranjujemo sve zahtjeve, no kasnije se planiramo prebaciti na uzorkovanje). Testiramo novi kod na njima i provodimo modularne testove, a ako \u017eelite, lako mo\u017eete pretvoriti zanimljive zahtjeve u modularne testove.<\/p>\n<p><\/p>\n<h3 id=\"ot-chego-my-izbavilis\">Od \u010dega smo se rije\u0161ili<\/h3>\n<p><\/p>\n<p>Budu\u0107i da nemamo implementaciju, ali imamo prekida\u010de zna\u010dajki, oko 60% pipeline-a implementacije ostaje izvan upotrebe. Ne trebaju nam git grane ili pull requesti, izgradnja backend resursa i kontejnera, slanje resursa i kontejnera u registracije ili koraci implementacije u Kubernetes.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/gc\/9e\/g-\/gc9eg-szouq0dtrxxr8jd6c6dyo.jpeg\"><img decoding=\"async\" alt=\"Kako Dark implementira kod za 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/d584b13a1f91e9eef1e2e40c25e90052.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Usporedba standardnog kontinuiranog isporu\u010dnog lanca (slijeva) i Dark kontinuirane isporuke (sdesna). U Dark isporuci sastoji se od 6 koraka i jednog ciklusa, dok tradicionalna verzija uklju\u010duje 35 koraka i 3 ciklusa.<\/em><\/p>\n<p><\/p>\n<p>U Dark razvoju postoji samo 6 koraka i 1 ciklus (koraci koji se ponavljaju vi\u0161e puta), dok moderni kontinuirani isporu\u010dni lanac sastoji se od 35 koraka i 3 ciklusa. U Dark testovi se pokre\u0107u automatski, a vi to \u010dak ni ne primje\u0107ujete; ovisnosti se instaliraju automatski; sve \u0161to se odnosi na git ili Github vi\u0161e nije potrebno; graditi, testirati i slati Docker kontejnere nije potrebno; razdeployment u Kubernetes vi\u0161e nije potrebno.<\/p>\n<p><\/p>\n<p>\u010cak su i preostali koraci u Dark postali lak\u0161i. Budu\u0107i da se prekida\u010dima funkcija mo\u017ee upravljati jednim akcijom, ne morate ponovno prolaziti kroz cijeli lanac isporuke kako biste uklonili stari kod.<\/p>\n<p><\/p>\n<p>Poku\u0161ali smo pojednostaviti isporuku koda, skra\u0107uju\u0107i vrijeme i rizike povezane s kontinuiranom isporukom. Tako\u0111er smo zna\u010dajno pojednostavili a\u017euriranje paketa, migracije baza podataka, testiranje, upravljanje verzijama, instalaciju ovisnosti, jednakost izme\u0111u razvojne i produkcijske okoline i brze i sigurne nadogradnje verzija jezika.<\/p>\n<p><\/p>\n<p>Odgovaram na pitanja o tome na <noindex><a rel=\"nofollow\" href=\"https:\/\/news.ycombinator.com\/item?id=20394166\">HackerNews<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Da biste saznali vi\u0161e o Dark ure\u0111aju, pro\u010ditajte <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">\u010dlanak o Dark<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/darklang?source=post_page---------------------------\">pratite nas na Twitteru<\/a><\/noindex> (ili na <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/paulbiggar?source=post_page---------------------------\">mene<\/a><\/noindex>) ili <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/subscribe?source=post_page---------------------------\">prijavite se za beta verziju i primajte obavijesti o sljede\u0107im postovima<\/a><\/noindex>. Ako idete na StrangeLoop u rujnu, <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/launch\">do\u0111ite na na\u0161u prezentaciju<\/a><\/noindex>.<\/p>\n<p>Izvor: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/462027\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u0441 \u2014 \u043d\u0430\u0448\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043c\u0435\u0448\u0430\u0442\u044c \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u0440\u043e\u0441\u0442\u043e\u044f\u043c \u0438 \u043f\u0435\u0440\u0435\u0440\u044b\u0432\u0430\u043c. \u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0432 \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0430\u0436\u0435 \u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27506,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.5 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"hr_HR\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Kako Dark implementira kod za 50 ms | ProHoster","description":"\u0160to je proces razvoja br\u017ei, to su br\u017ee.","canonical_url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"hr_HR","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster","og:description":"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.","og:url":"https:\/\/prohoster.info\/hr\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:20+00:00","article:modified_time":"2019-10-31T19:13:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36721","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:34:22","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:40:22","updated":"2026-01-22 04:34:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/36721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/comments?post=36721"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/posts\/36721\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media\/27506"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/media?parent=36721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/categories?post=36721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/hr\/wp-json\/wp\/v2\/tags?post=36721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}