{"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\/sl\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","title":{"rendered":"Kako Dark izvaja kodo v 50 ms","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Kako Dark izvaja kodo v 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/c159a36eb52bf488f3a70ea511690366.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>\u010c\u00edm rychlej\u0161\u00ed je v\u00fdvojov\u00fd proces, t\u00edm rychleji se rozv\u00edj\u00ed technologick\u00e1 spole\u010dnost.<\/p>\n<p><\/p>\n<p>Bohu\u017eel modern\u00ed aplikace pracuj\u00ed proti n\u00e1m \u2014 na\u0161e syst\u00e9my mus\u00ed b\u00fdt aktualizov\u00e1ny v re\u00e1ln\u00e9m \u010dase a z\u00e1rove\u0148 nikomu nep\u0159ek\u00e1\u017eet a nevedou k v\u00fdpadk\u016fm. Nasazen\u00ed v takov\u00fdch syst\u00e9mech se st\u00e1v\u00e1 slo\u017eit\u00fdm \u00fakolem a vy\u017eaduje slo\u017eit\u00e9 kan\u00e1ly kontinu\u00e1ln\u00ed dod\u00e1vky i v mal\u00fdch t\u00fdmech.<\/p>\n<p><\/p>\n<p>Tyto kan\u00e1ly obvykle maj\u00ed \u00fazk\u00e9 vyu\u017eit\u00ed, pracuj\u00ed pomalu a nejsou spolehliv\u00e9. V\u00fdvoj\u00e1\u0159i je mus\u00ed nejd\u0159\u00edve vytvo\u0159it ru\u010dn\u011b a pot\u00e9 je spravovat, a spole\u010dnosti \u010dasto naj\u00edmaj\u00ed cel\u00e9 t\u00fdmy DevOps, aby se o to postaraly.<\/p>\n<p><\/p>\n<p>Rychlost t\u011bchto kan\u00e1l\u016f ovliv\u0148uje rychlost v\u00fdvoje. U nejlep\u0161\u00edch t\u00fdm\u016f nasazen\u00ed zabere 5\u201310 minut, ale obvykle trv\u00e1 mnohem d\u00e9le a jedno nasazen\u00ed m\u016f\u017ee trvat n\u011bkolik hodin.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>Ve spole\u010dnosti Dark to zabere 50 ms. <em>Pades\u00e1t. Milisekund.<\/em>. Dark \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">je komplexn\u00ed \u0159e\u0161en\u00ed s programovac\u00edm jazykem, editorem a infrastrukturou<\/a><\/noindex>, vytvo\u0159en\u00e9 speci\u00e1ln\u011b pro kontinu\u00e1ln\u00ed dod\u00e1vku, a v\u0161echny aspekty Dark, v\u010detn\u011b samotn\u00e9ho jazyka, jsou navr\u017eeny s ohledem na bezpe\u010dn\u00e9 okam\u017eit\u00e9 nasazen\u00ed.<\/p>\n<p><\/p>\n<h3 id=\"pochemu-konveyery-nepreryvnoy-postavki-takie-medlennye\">Pro\u010d jsou kan\u00e1ly kontinu\u00e1ln\u00ed dod\u00e1vky tak pomal\u00e9?<\/h3>\n<p><\/p>\n<p>P\u0159edstavme si, \u017ee m\u00e1me webovou aplikaci Python a ji\u017e jsme vytvo\u0159ili skv\u011bl\u00fd a modern\u00ed kan\u00e1l kontinu\u00e1ln\u00ed dod\u00e1vky. Pro v\u00fdvoj\u00e1\u0159e, kter\u00fd se touto \u010dinnost\u00ed zab\u00fdv\u00e1 ka\u017ed\u00fd den, bude nasazen\u00ed jedin\u00e9 drobn\u00e9 zm\u011bny vypadat p\u0159ibli\u017en\u011b takto:<\/p>\n<p><\/p>\n<h3 id=\"vnesenie-izmeneniy\">Prov\u00e1d\u011bn\u00ed zm\u011bn<\/h3>\n<p><\/p>\n<ul>\n<li>Vytvo\u0159en\u00ed nov\u00e9ho v\u011btven\u00ed v gitu<\/li>\n<li>Prov\u00e1d\u011bn\u00ed zm\u011bn za p\u0159ep\u00edna\u010dem funkc\u00ed<\/li>\n<li>Modulov\u00e9 testov\u00e1n\u00ed k ov\u011b\u0159en\u00ed zm\u011bn s p\u0159ep\u00edna\u010dem funkc\u00ed i bez n\u011bj<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pul-rekvest\">Pull request<\/h3>\n<p><\/p>\n<ul>\n<li>Z\u00e1znam zm\u011bn<\/li>\n<li>Odesl\u00e1n\u00ed zm\u011bn do vzd\u00e1len\u00e9ho repozit\u00e1\u0159e na githubu<\/li>\n<li>Pull request<\/li>\n<li>Sestaven\u00ed CI se prov\u00e1d\u00ed automaticky na pozad\u00ed<\/li>\n<li>Kontrola k\u00f3du<\/li>\n<li>Dal\u0161\u00ed kontroly k\u00f3du, pokud jsou pot\u0159eba<\/li>\n<li>Slou\u010den\u00ed zm\u011bn s v\u011btv\u00ed git master.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"ci-vypolnyaetsya-na-mastere\">CI se prov\u00e1d\u00ed na v\u011btvi master<\/h3>\n<p><\/p>\n<ul>\n<li>Instalace frontendov\u00fdch z\u00e1vislost\u00ed p\u0159es npm<\/li>\n<li>Sestaven\u00ed a optimalizace zdroj\u016f HTML+CSS+JS<\/li>\n<li>Proveden\u00ed modulov\u00fdch a funk\u010dn\u00edch test\u016f na frontendu<\/li>\n<li>Instalace z\u00e1vislost\u00ed Pythonu z PyPI<\/li>\n<li>Proveden\u00ed modulov\u00fdch a funk\u010dn\u00edch test\u016f na backendu<\/li>\n<li>Testov\u00e1n\u00ed integrace na obou konc\u00edch<\/li>\n<li>Odesl\u00e1n\u00ed zdroj\u016f frontendu do CDN<\/li>\n<li>Sestaven\u00ed kontejneru pro program Python<\/li>\n<li>Po\u0161iljanje kontejnerja v register<\/li>\n<li>Posodobitev manifestov Kubernetes<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"zamena-starogo-koda-novym\">Zamenjava stare kode z novo<\/h3>\n<p><\/p>\n<ul>\n<li>Kubernetes za\u017eene ve\u010d primerkov novega kontejnerja<\/li>\n<li>Kubernetes \u010daka, da postanejo primerki operativni<\/li>\n<li>Kubernetes dodaja primerke v HTTP uravnote\u017eevalnik obremenitve<\/li>\n<li>Kubernetes \u010daka, da se starej\u0161i primerki prenehajo uporabljati<\/li>\n<li>Kubernetes ustavi starej\u0161e primerke<\/li>\n<li>Kubernetes ponavlja te operacije, dokler novi primerki ne zamenjajo vseh starih<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"vklyuchenie-novogo-pereklyuchatelya-funkcii\">Vklju\u010ditev novega stikala funkcij<\/h3>\n<p><\/p>\n<ul>\n<li>Nova koda se vklopi le za sebe, da se prepri\u010da, da je vse v redu<\/li>\n<li>Nova koda se vklopi za 10 % uporabnikov, spremljajo se operativne in poslovne metrike<\/li>\n<li>Nova koda se vklopi za 50 % uporabnikov, spremljajo se operativne in poslovne metrike<\/li>\n<li>Nova koda se vklopi za 100 % uporabnikov, spremljajo se operativne in poslovne metrike<\/li>\n<li>Nazadnje ponovite celoten postopek, da odstranite staro kodo in stikalo<\/li>\n<\/ul>\n<p><\/p>\n<p>Postopek je odvisen od orodij, jezika in uporabe arhitektur, usmerjenih na storitve, vendar v splo\u0161nem izgleda tako. Nisem omenil uvajanja z migracijo baz podatkov, ker to zahteva skrbno na\u010drtovanje, toda spodaj bom razlo\u017eil, kako s tem ravna Dark.<\/p>\n<p><\/p>\n<p>Tukaj je veliko komponent in mnoge od njih lahko zlahka ustavijo sistem, povzro\u010dijo te\u017eave, spro\u017eijo za\u010dasno konkurenco ali zru\u0161ijo delovni sistem.<\/p>\n<p><\/p>\n<p>Ker so ti cevovodi skoraj vedno ustvarjeni za posebne primere, nanje te\u017eko ra\u010dunamo. Veliko ljudi ima dni, ko kode ni mogo\u010de uvesti, ker je v Dockerfile te\u017eava, eden od desetih storitev je odpovedal ali pa je potreben strokovnjak na dopustu.<\/p>\n<p><\/p>\n<p>\u0160e huje, mnogi od teh korakov sploh ne prina\u0161ajo koristnega. Bili so potrebni prej, ko smo uvajali kodo neposredno za uporabnike, zdaj pa imamo stikalnike za novo kodo in so ti procesi lo\u010deni. Na koncu je korak, kjer se koda uvaja (stara se nadomesti z novo), zdaj preprosto odve\u010dna tveganja.<\/p>\n<p><\/p>\n<p>Seveda, to je zelo premi\u0161ljen cevovod. Ekipa, ki ga je ustvarila, ni skoparila s \u010dasom in denarjem za hitro uvajanje. Obi\u010dajno so cevovodi za uvajanje veliko po\u010dasnej\u0161i in manj zanesljivi.<\/p>\n<p><\/p>\n<h3 id=\"realizaciya-nepreryvnoy-postavki-v-dark\">Izvedba neprekinjene oskrbe v Dark<\/h3>\n<p><\/p>\n<p>Neprekinjena dostava je za Dark toliko va\u017ena da smo od samog po\u010detka ciljali na vreme ispod jedne sekunde. Pro\u0161li smo kroz sve korake u lancu opskrbe kako bismo uklonili sve suvi\u0161ne, a ostalo doveli do savr\u0161enstva. Evo kako smo uklonili korake.<\/p>\n<p><\/p>\n<blockquote><p>D\u017eesi Frazel (<noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex>) je smislila novu re\u010d deployless (ne zahteva implementaciju) na konferenciji Future of Software Development u Rejkjaviku.<\/p><\/blockquote>\n<p>Odmah smo odlu\u010dili da \u0107e Dark biti zasnovan na konceptu \u201edeployless\u201c (hvala <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">D\u017eesi Frazel<\/a><\/noindex> na neologizmu). Deployless zna\u010di da se svaki kod momentalno implementira i spreman je za proizvodnju. Naravno, ne\u0107emo propustiti neispravan ili nepotpun kod (principi bezbednosti bi\u0107e obja\u0161njeni u nastavku).<\/p>\n<p><\/p>\n<p>Na demonstraciji Dark \u010desto su nas pitali kako smo uspeli tako da ubrzamo implementaciju. \u010cudan pitanje. Ljudi verovatno misle da smo smislili neku super tehnologiju koja poredi kod, kompajlira ga, upakuje u kontejner, pokre\u0107e virtuelnu ma\u0161inu, pokre\u0107e kontejner hladno i sve to za 50 ms. To je malo verovatno. Ali smo stvorili poseban motor za implementaciju kome to nije ni potrebno.<\/p>\n<p><\/p>\n<p>Dark pokre\u0107e interpretere u oblaku. Recimo, pi\u0161ete kod u funkciji ili HTTP ili doga\u0111ajnom handleru. \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 kada dobijemo zahteve. Tako da implementacija izgleda kao skromni unos u bazu podataka \u2014 momentalna i jednostavna. Implementacija se odvija tako brzo jer uklju\u010duje minimum.<\/p>\n<p><\/p>\n<p>U budu\u0107nosti planiramo da od Dark napravimo kompajler infrastrukture koji \u0107e kreirati i pokretati savr\u0161enu infrastrukturu za visoke performanse i pouzdanost aplikacija. Momentna 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 Dark pi\u0161e se u ure\u0111iva\u010du Dark. Strukturirani ure\u0111iva\u010d ne dozvoljava sintakti\u010dke gre\u0161ke. U su\u0161tini, u Dark \u010dak i nema analizira\u010da. Dok kucate tekst, direktno radimo sa 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> in <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jetbrains.com\/mps\/\">MPS<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Svi nedovr\u0161eni kodovi u Dark imaju dozvoljenu semantiku izvr\u0161avanja, otprilike kao <noindex><a rel=\"nofollow\" href=\"https:\/\/hazel.org\/\">tipizovane rupe 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 Darku ima svoju svrhu, stoga nedovr\u0161eni 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>Kod u Darku pi\u0161ete u dva slu\u010daja. Prvi: pi\u0161ete novi kod i jedini ste korisnik. Na primjer, to je u REPL-u, a drugi korisnici nikada ne\u0107e imati pristup njemu, ili je to nova HTTP staza na koju se nigdje ne pozivate. Ovde mo\u017eete raditi bez ikakvih mjera opreza, a sada upravo tako radite u razvojnom 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 itd.), trebate biti oprezni. Zbog toga blokiramo sav kori\u0161teni kod i zahtijevamo kori\u0161tenje strukturiranijih alata za njegovo ure\u0111ivanje. O strukturiranim alatima \u0107u govoriti u nastavku: prekida\u010di funkcija za HTTP i doga\u0111aje, mo\u0107na platforma za migraciju baza podataka i nova metoda upravljanja verzijama za funkcije i tipove.<\/p>\n<p><\/p>\n<h3 id=\"pereklyuchateli-funkciy\">Prekida\u010di 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\">uklanjanja suvi\u0161ne slo\u017eenosti<\/a><\/noindex> u Darku je rije\u0161iti nekoliko problema jednim rje\u0161enjem. Prekida\u010di funkcija obavljaju mnoge razli\u010dite zadatke: zamjena lokalnog razvojnog okru\u017eenja, git grane, implementacija koda i naravno, tradicionalno sporo i kontrolisano pu\u0161tanje novog koda.<\/p>\n<p><\/p>\n<p>Kreiranje i implementacija prekida\u010da funkcija vr\u0161i se u na\u0161em ure\u0111iva\u010du u jednoj operaciji. On stvara prazno mjesto za novi kod i pru\u017ea kontrole pristupa starom i novom kodu, kao i dugmad i komande za postepeno prebacivanje na novi kod ili njegovu isklju\u010denje.<\/p>\n<p><\/p>\n<p>Prekida\u010di funkcija ugra\u0111eni su u jezik Dark, i \u010dak i nedovr\u0161eni prekida\u010di obavljaju svoju funkciju \u2013 ako uslov u prekida\u010du nije ispunjen, izvr\u0161i\u0107e se stari blokirani kod.<\/p>\n<p><\/p>\n<h3 id=\"sreda-razrabotki\">Razvojno okolje<\/h3>\n<p><\/p>\n<p>Preklopniki funkcij nadome\u0161\u010dajo lokalno razvojno okolje. Danes je ekipam te\u017eko poskrbeti, da vsi uporabljajo enake razli\u010dice orodij in knji\u017enic (orodja za oblikovanje kode, linters, upravljalniki paketov, prevajalniki, predprocesorji, orodja za testiranje itd.). S Dark ni treba lokalno namestiti odvisnosti, upravljati z lokalno namestitvijo Dockerja ali sprejeti drugih ukrepov, da bi zagotovili vsaj nekak\u0161no enakost med razvojnim okoljem in produkcijo. <noindex><a rel=\"nofollow\" href=\"https:\/\/thenewstack.io\/honeycombs-charity-majors-go-ahead-test-in-production\/\">Glede na to, da taka enakost kljub vsemu ni mogo\u010da,<\/a><\/noindex>, se niti pretvarjati ne bomo, da si prizadevamo zanjo.<\/p>\n<p><\/p>\n<p>Namesto da bi ustvarili klonirano lokalno okolje, preklopniki v Dark ustvarjajo novo peskovnik v produkciji, ki zamenja razvojno okolje. V prihodnosti na\u010drtujemo tudi ustvarjanje peskovnika za druge dele aplikacije (na primer trenutne klone baz podatkov), \u010deprav se to trenutno ne zdi tako pomembno.<\/p>\n<p><\/p>\n<h3 id=\"vetki-i-razvertyvaniya\">Veje in razmestitev<\/h3>\n<p><\/p>\n<p>Trenutno obstaja ve\u010d na\u010dinov za vnos nove kode v sisteme: git veje, faza razmestitve in preklopniki funkcij. Re\u0161ujejo enak problem na razli\u010dnih delih delovnega toka: git \u2013 na fazah pred razmestitvijo, razmestitev \u2013 ob prehodu s stare kode na novo, preklopniki funkcij \u2013 za nadzorovano izdajo nove kode.<\/p>\n<p><\/p>\n<p>Najbolj u\u010dinkovit na\u010din so preklopniki funkcij (hkrati tudi najla\u017eje razumeti in uporabljati). Z njimi se lahko popolnoma odre\u010demo ostalim dvema metodama. \u0160e posebej koristno je odstraniti razmestitev \u2013 \u010de \u017ee uporabljamo preklopnike funkcij, da vklju\u010dimo kodo, potem korak prenosa stre\u017enikov na novo kodo povzro\u010da le dodatna tveganja.<\/p>\n<p><\/p>\n<p>Git je te\u017eko uporabljati, \u0161e posebej novakom, kar ga zelo omejuje, a ima priro\u010dne veje. Odpravili smo mnoge pomanjkljivosti gita. Dark se ureja v realnem \u010dasu in omogo\u010da sodelovanje v slogu Google Dokumentov, da ni treba po\u0161iljati kode in da je manj pogosto potrebno izvajati rebase in merge.<\/p>\n<p><\/p>\n<p>Funkcijski prekida\u010di su temelj sigurnog implementiranja. Zajedno s trenutnim implementacijama, omogu\u0107uju brzo testiranje koncepata u malim fragmentima s niskim rizikom umjesto primjene jedne velike promjene koja bi mogla sru\u0161iti sustav.<\/p>\n<p><\/p>\n<h3 id=\"versionirovanie\">\u0412\u0435\u0440\u0437\u0438\u043e\u043d\u0438\u0441\u0430\u045a\u0435<\/h3>\n<p><\/p>\n<p>Za promjenu funkcija i tipova koristimo verzioniranje. Ako \u017eelite promijeniti funkciju, Dark stvara novu verziju te funkcije. Nakon toga, tu verziju mo\u017eete pozvati putem prekida\u010da u HTTP handleru ili doga\u0111aju. (Ako je ta funkcija duboko u grafu poziva, usput se stvara nova verzija svake funkcije. Mo\u017ee se \u010diniti da je to prekomjerno, ali funkcije se ne sudaraju kad ih ne koristite, tako da to niti ne primijetite.)<\/p>\n<p><\/p>\n<p>Iz istih razloga verzioniramo i tipove. O na\u0161em sustavu tipova detaljno smo govorili <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 pojedina\u010dni handler radi s novom verzijom, a nije potrebno odmah provesti sve promjene u aplikaciji (ali imamo alate koji omogu\u0107uju brzo to ako \u017eelite).<\/p>\n<p><\/p>\n<p>To je mnogo sigurnije od potpunog implementiranja svega odjednom, kao \u0161to se to doga\u0111a sada.<\/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 Darku, 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 putem 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 izvaja kodo v 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/54fdb566b4bcbc10e06e51c47a3820f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Snimak dijela automatskog procesa u Darku, koji pokazuje dvije verzije funkcije Dict::get. Dict::get_v0 je vra\u0107ao tip Any (od kojeg odustajemo), dok Dict::get_v1 vra\u0107a tip Option.<\/em><\/p>\n<p><\/p>\n<p>\u010cesto pru\u017eamo novu funkciju u standardnoj biblioteci i isklju\u010dujemo stare verzije. Korisnici sa starim verzijama koda zadr\u017eat \u0107e pristup njima, ali novi korisnici ih ne\u0107e mo\u0107i dobiti. Planiramo pru\u017eiti alate koji \u0107e omogu\u0107iti prijelaz korisnika sa starih verzija na nove u 1 koraku, opet putem prekida\u010da funkcija.<\/p>\n<p><\/p>\n<p>Dark prav tako ponuja edinstveno prilo\u017enost: ker izvajamo va\u0161o delovno kodo, lahko sami testiramo nove razli\u010dice in primerjamo izhodne podatke za nove in stare poizvedbe, da vas obvestimo o spremembah. Posledi\u010dno posodobitev paketov, ki se pogosto izvaja na slepo (ali zahteva natan\u010dno testiranje iz varnostnih razlogov), predstavlja veliko manj tveganj in se lahko izvaja samodejno.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-dark\">Nove razli\u010dice Dark<\/h3>\n<p><\/p>\n<p>Prehod s Pythona 2 na Python 3 se je raztezal \u010dez desetletje in \u0161e vedno predstavlja te\u017eavo. Ker ustvarjamo Dark za neprekinjeno dostavo, je treba upo\u0161tevati te spremembe jezika.<\/p>\n<p><\/p>\n<p>Ko vna\u0161amo majhne spremembe v jezik, ustvarjamo novo razli\u010dico Dark. Stara koda ostane v stari razli\u010dici Dark, nova koda pa se uporablja v novi razli\u010dici. Za prehod na novo razli\u010dico Dark lahko uporabite preklopnike ali razli\u010dice funkcij.<\/p>\n<p><\/p>\n<p>To je \u0161e posebej koristno, ker je Dark nastal \u0161ele nedavno. Mnoge spremembe v jeziku ali knji\u017enici se lahko izka\u017eejo za neuspe\u0161ne. Postopno verzioniranje jezika nam omogo\u010da, da delamo majhne posodobitve, kar pomeni, da se lahko ne mudi in odlo\u017eimo \u0161tevilne odlo\u010ditve o jeziku, dokler ne bomo imeli ve\u010d uporabnikov in torej ve\u010d informacij.<\/p>\n<p><\/p>\n<h3 id=\"migracii-baz-dannyh\">Migracije baz podatkov<\/h3>\n<p><\/p>\n<p>Za varno migracijo baze podatkov obstaja <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 kodo za podporo novim in starim formatom<\/li>\n<li>Pretvoriti vse podatke v nov format<\/li>\n<li>Odstraniti star dostop do podatkov<\/li>\n<\/ul>\n<p><\/p>\n<p>Zaradi tega se migracija baze podatkov zamakne in zahteva veliko virov. In nagomilamo zastarele sheme, saj tudi preproste naloge, kot je popravilo imena tabele ali stolpca, ne upravi\u010dujejo stro\u0161kov.<\/p>\n<p><\/p>\n<p>Dark ima u\u010dinkovito platformo za migracijo baz podatkov, ki (upamo) tako poenostavi postopek, da se ga ne boste ve\u010d bali. Vse shrambe podatkov v Dark (hranilniki parov \u201eklju\u010d-vrednost\u201c ali trajne hasho-tabele) imajo tip. Da bi prenesli shrambo podatkov, ji preprosto dodelite nov tip in funkcijo za povratno in napredno operacijo za pretvorbo vrednosti med obema tipoma.<\/p>\n<p><\/p>\n<p>Dostop do podatkovnih skladi\u0161\u010d v Darku se izvaja prek verzioniranih imen spremenljivk. Na primer, podatkovno skladi\u0161\u010de Users se sprva imenuje Users-v0. Ko je ustvarjena nova razli\u010dica z druga\u010dnim tipom, se ime spremeni v Users-v1. \u010ce so podatki shranjeni prek Users-v0, ko pa dostopate do njih prek Users-v1, se uporabi funkcija vra\u010danja. \u010ce so podatki shranjeni prek Users-v1, ko dostopate do njih prek Users-v0, se uporabi 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 izvaja kodo v 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/35743ba246f327ca9e8b71f0069a3800.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Zaslon za migracijo baze podatkov s trenutnimi imeni polj stare baze podatkov, izrazi vra\u010danja in povratka ter navodili za vklju\u010ditev migracije.<\/em><\/p>\n<p><\/p>\n<p>Uporabite stikala za funkcije, da usmerite klice z Users-v0 na razli\u010dico Users-v1. To lahko storite enega HTTP obdelovalnika naenkrat, kar zmanj\u0161a tveganja, poleg tega stikala delujejo za posamezne uporabnike, s \u010dimer lahko preverite, da vse deluje, kot je bilo pri\u010dakovano. Ko uporabnikov Users-v0 ne bo ve\u010d, Dark vse preostale podatke v ozadju pretvori iz starega formata v novega. Tega sploh ne boste opazili.<\/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 s stati\u010dno tipizacijo<\/a><\/noindex> in nespremenljivimi vrednostmi, zato je povr\u0161ina testiranja precej manj\u0161a v primerjavi z objektno usmerjenimi jeziki z dinami\u010dno tipizacijo. Vendar testiranje ostaja nujno.<br \/>\nV Darku samodejno za\u017eene modulne teste v ozadju za urejen kodo in privzeto izvaja te teste za vsa stikala funkcij. V prihodnosti \u017eelimo z uporabo stati\u010dnih tipov samodejno izvajati fuzzing kode za iskanje napak.<\/p>\n<p><\/p>\n<p>Poleg tega Dark obsega va\u0161o infrastrukturo v produkciji, kar odpira nove mo\u017enosti. Samodejno shranjujemo HTTP zahteve v infrastrukturi Dark (zaenkrat shranjujemo vse zahteve, pozneje pa \u017eelimo preiti na vzor\u010denje). Testiramo nov kod glede na te zahteve in izvajamo modulne teste, ter po \u017eelji lahko enostavno pretvorite zanimive zahteve v modulne teste.<\/p>\n<p><\/p>\n<h3 id=\"ot-chego-my-izbavilis\">Od \u010desar smo se odpovedali<\/h3>\n<p><\/p>\n<p>Ker nimamo nalaganja, imamo pa stikala funkcij, pribli\u017eno 60% procesa nalaganja ostane neizkori\u0161\u010denih. Ne potrebujemo git vejah ali pull zahtevkov, gradnje backend virov in kontejnerjev, po\u0161iljanja virov in kontejnerjev v registre ali korakov nalaganja v 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 izvaja kodo v 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/d584b13a1f91e9eef1e2e40c25e90052.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Primerjava standardnega pipelinea neprekinjenega oskrbovanja (levo) in neprekinjeno oskrbovanje Dark (desno). V Dark oskrba obsega 6 korakov in en cikel, medtem ko tradicionalna razli\u010dica vklju\u010duje 35 korakov in 3 cikle.<\/em><\/p>\n<p><\/p>\n<p>V Dark je razporeditev sestavljena le iz 6 korakov in 1 cikla (koraki, ki se ponavljajo ve\u010dkrat), medtem ko sodoben pipeline neprekinjenega oskrbovanja obsega 35 korakov in 3 cikle. V Dark se testi izvajajo samodejno, kar vam ne pride niti na misel; odvisnosti se name\u0161\u010dajo samodejno; vse, kar je povezano z git ali Github, ve\u010d ni potrebno; zbiranje, testiranje in po\u0161iljanje Docker kontejnerjev ni potrebno; razporejanje v Kubernetes ni ve\u010d potrebno.<\/p>\n<p><\/p>\n<p>Tudi preostali koraki v Dark so postali enostavnej\u0161i. Ker je mogo\u010de upravljati s preklopniki funkcij z eno akcijo, ni treba znova prehajati skozi celoten razporedilni pipeline, da bi odstranili stari kodo.<\/p>\n<p><\/p>\n<p>Po najbolj\u0161ih mo\u010deh smo poenostavili dostavo kode, skraj\u0161ali \u010das in tveganja neprekinjenega oskrbovanja. Poleg tega smo mo\u010dno poenostavili posodobitve paketov, migracije baz podatkov, testiranje, obvladovanje razli\u010dic, namestitev odvisnosti, usklajenost med razvojnim in produkcijskim okoljem ter hitre in varne nadgradnje jezikovnih razli\u010dic.<\/p>\n<p><\/p>\n<p>O tem odgovarjam na <noindex><a rel=\"nofollow\" href=\"https:\/\/news.ycombinator.com\/item?id=20394166\">HackerNews<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Da bi izvedeli ve\u010d o napravi Dark, preberite <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">\u010dlanek o Dark<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/darklang?source=post_page---------------------------\">sledite nam na Twitterju<\/a><\/noindex> (ali na <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/paulbiggar?source=post_page---------------------------\">meni<\/a><\/noindex>) nebo <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/subscribe?source=post_page---------------------------\">prijavite se na beta razli\u010dico in prejemajte obvestila o prihodnjih objavah<\/a><\/noindex>. \u010ce se v septembru odpravite na StrangeLoop, <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/launch\">pridite na na\u0161 zagon<\/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.4 - 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\/sl\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.4\" \/>\n\t\t<meta property=\"og:locale\" content=\"sl_SI\" \/>\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\/sl\/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 razporeja kodo v 50 ms | ProHoster","description":"Hitrej\u0161i kot je postopek razvoja, hitreje je.","canonical_url":"https:\/\/prohoster.info\/sl\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"sl_SI","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\/sl\/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\/sl\/wp-json\/wp\/v2\/posts\/36721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/comments?post=36721"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/posts\/36721\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media\/27506"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/media?parent=36721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/categories?post=36721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/sl\/wp-json\/wp\/v2\/tags?post=36721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}