poutave napsano, vecne popsano, neni to prilis rozvlacne, je to strucne, ale zduraznene dulezite body. Presne takto si predstavuji tutorialy - clovek pochopi princip, a kdyz chce se ponorit hloubeji, ma se ceho chytnout aby mohl najit relevantni odkazy na netu.
Opravdu dik za takovou polopaticnost.
Mala technicka:
echo_proc.erl radek 20, chybi '.'
:)
Super tutoriál. Opravdu diky za něj. Chci se zeptat. Může být vhodné použít erlang na serverovou implementaci obousměrné synchronizace mezi mobilními zařízeními? Mam aplikaci na androidu a jeji data chci syncovat mezi vice telefony přes backend server. Na tomto serveru je napojeni na db kde jsou uložena data všech uživatelů.
Erlang lze použít na socketovou část různých serverových backendů aplikací. Tj. uržovat hodně spojení, přijmat z nich zprávy, dekódovat je, kódovat je a odesílat odpovědi. Na to je stavěný. Hodně nezávislých vstupů co je třeba obsluhovat tak aby co spolu nesouvisí se pokud možno neovlivňovalo. Aplikační logika serverové části pochopitelně může být v Erlangu také, ale lze ji napsat v jiném jazyce a využít nějakou z forem propojení Erlangu s jinými programy.
Na ukádáni většího množství dat má Erlang svoje prostředky, ale lze použit klasické databáze. Ve standartních knihovnách je na připojování se k databázím ODBC driver a pro většinu bežných databází existují knihovny na přímý přístup (praktické zkušenosti nemám).
> a pro většinu bežných databází existují knihovny na přímý přístup (praktické zkušenosti nemám).
Ruzne SQL knihovny funguji dobre. Akorat je obcas potreba trochu pohlidat, jak knihovna koduje datove typy. Napr. pracuju s jednou knihovnou, ktera typ timestamp koduje jako klasicky {{Y,M,D},{h,m,s}}, coz je draha operace, takze cteni vetsiho mnozstvi dat timhle zpusobem je pomale. Ale to neni zadne specifikum Erlangu, v jinych jazycich by to bylo stejny.
Pro Elixir pak jeste existuji vselijake knihovny, ktere poskytuji funkce vyssi urovne nez jenom klasicke SQL dotazovani (nejake ty modely, DSL pro dotazovani apod.) - napr. https://github.com/elixir-lang/ecto nebo https://github.com/meh/amnesia
Vubec mnesia je hodne zajimava databaze, ta by stala za samostatny dil :)
A to, že proces obsahuje chybu, díky které vyžere celej VM, ze které se nezotaví smysl dává?
Ale mám pocit, že si nerozumíme. Tady nejde o to, že přijde zpráva, na kterou nezná odpověď, ale to, že tato nepodporovaná zpráva se bude stále dokola zpracovávat, přestože není důvod si myslet, že příště by to mělo matchnout.
To že příkaz receive nepracuje jen s první zprávou ve frontě, ale zkouší i následující (a pak případně čeká), přináší riziko, že se díky nějaké chybě v programu mohou ve frontě hromadit nevyzvednuté zprávy, které budou pokaždé přeskakovány. To není dobré, neboť nevyzvednuté zprávy obsahují data, která se nikdy neuvolní (memory leak) a tím, že se neustále porovnávají se vzory, při každé příchozí zprávě postupně snižují výkon systému.
Nedochází mi pointa proč je to takto navrženo.
> A to, že proces obsahuje chybu, díky které vyžere celej VM, ze které se nezotaví smysl dává?
To z toho neplyne. Aby k tomu vubec mohlo dojit, jsou potreba dalsi podminky.
> tato nepodporovaná zpráva se bude stále dokola zpracovávat, přestože není důvod si myslet, že příště by to mělo matchnout.
Nebude. Matchovani je optimalizovane - jednou vyzkousene zpravy se uz nematchuji (v tom stejnem receivu). Testuji se jenom nove prisedsi zpravy.
> Nedochází mi pointa proč je to takto navrženo.
Jsou k tomu ruzne duvody, ktere neni snadne vysvetlit. Proste tak, jak to je, to dava nejvetsi smysl. V nejvetsim moznem zestrucneni bych asi rekl, ze tohle je nejobecnejsi mozny zpusob, ktery nevytvari limitace a potencialni problemy, ktere ma, se daji snadno vyresit.
Je potreba si uvedomit, ze zpravy chodi asynchronne - tj. jakakoli kdykoli. Nikde neni receno, ze musim cekat na odpoved. Muzu odpalit task, mezitim delat neco jineho (tj. odesilat a prijimat jine zpravy) a az nekdy pozdeji se kouknout, jestli uz mi prisla odpoved. A v ramci toho "delani neceho jineho" chci taky cekat na zpravy. Tj. chci mit moznost zablokovat proces, dokud zprava neprijde.
Cili chci zaroven:
1. chci, aby mi mohla prijit odpoved predtim odpaleneho tasku (RESP1) a zustala cekat, az me bude zajimat
2. nechci, aby mi RESP1 jakkoli ovlivnila to, co delam ted
3. chci blokovat dokud nedojde zprava, na kterou ted cekam (RESP2)
Tohle jde zaraz splnit prave jenom tak, jak je to udelano (mailbox se selektivnim matchovanim, defaultni blokovani).
To, co te tak desi, jde velice snadno resit:
1. v okamziku, kdy vim, ze na zadne odpovedi predchozich tasku necekam, muzu vybrat nezname zpravy a zalogovat je, ze jsou nezname - bohate staci to delat zridka
2. pokud tohle z nejakeho duvodu delat nechci, muzu sledovat delku front. To je ale extremni reseni, v praxi fakt neni potreba.
> To z toho neplyne. Aby k tomu vubec mohlo dojit, jsou potreba dalsi podminky.
Budu posílat procesu zprávy, které zaručeně nezná. To jsou všechny nutné podmínky. A nebo mi něco uniká.
> To, co te tak desi, jde velice snadno resit:...
Otázka nezněla, jak to řešit. To vím. Otázka zněla proč zvolili tuto variantu řešení.
Když by proces nematchnutelné zprávy zahazoval, tak se to bude chovat stejně, a lépe, protože k té chybě vyžrání nebude moct dojít.
> Budu posílat procesu zprávy, které zaručeně nezná. To jsou všechny nutné podmínky. A nebo mi něco uniká.
Asi unika. Pokud proces aspon obcas vybira *vsechny* zpravy (a nezname treba loguje), muzes mu posilat co chces a nedosahnes niceho (krome narustani logu). A tohle je obvykly zpusob, jak se procesy pisou.
Cili dalsi nutna podminka je, ze proces *nikdy* nevybira vsechny zpravy.
Navic je treba si uvedomit, ze Erlang neni staveny na to, aby se umel branit protit utocnikovi, ktery ma k danemu nodu pristup. Pokud muzes posilat zpravy, mas daleko jednodussi zpusoby, jak node slozit.
> Otázka zněla proč zvolili tuto variantu řešení.
No dyt jsem psal: je to nejlepsi mozny zpusob. jestli chces, muzes popsat jiny a ja ti ukazu, ze ma daleko vetsi problemy/limity.
> Když by proces nematchnutelné zprávy zahazoval, tak se to bude chovat stejně
Nebude. Neslo by tam udelat to, co jsem psal vys (asinchronni odpaleni tasku a vybrani vysledku az se mi to bude hodit).
Proč zablokování?
Myslel jsem tohle:
1. proces P1 pošle procesu P2 nějakou žádost s tím, že P2 má zpátky poslat odpověď O1 až ji bude mít
2. proces P1 mezi tím dělá něco jiného (což znamená posílá a přijímá zprávy - konkrétně nějakou odpověď O2)
3. až se to procesu P1 hodí, koukne se, jestli mu náhodou mezitím nepřišla O1
Pokud by se neznámé zprávy zahazovaly, tak by se O1 mohla zahodit někde v průběhu bodu 2 - tam ji totiž neočekávám, dělám něco jiného, očekávám jiné zprávy (O2).
Něcodělání v bodu 2 může být toho druhu, že odešlu zprávu procesu P3 a čekám (zablokován) na O2 (ale *ne* na O1).
Jak souvisí zaneprázdněnost procesu s tím, že té zprávě nerozumí?
Já přece nemluvím o tom, že má proces zahazovat zprávy když na ně nemá čas. Já mluvím o tom, že by je zahazoval, když jim nerozumí. Protože takovej scénář má dle mého smysl jen v případě, když by někdy v průběhu času se "naučil" rozpoznat a zpracovat tu zprávu. Zatím jsem nabyl dojmu, že něco takového nejde. A pokud je to pravda, tak by mé řešení se zahazováním zpráv bylo lepší.
No, zkouším to blokování, možná by to mohlo jít. Uvidím.
Ahááá, já už to chápu :) Ty mluvíš o tom, že ten proces té zprávě jakoby "globálně nerozumí" - představuješ si, že je nějakej globální seznam zpráv, kterým proces rozumí a zpráva do něj může zapadat nebo ne.
Tak to je zcela mylná představa :) Za prvé není žádný "(pro proces) globální seznam", jsou jenom jednotlivé receivy, rozeseté všudemožně po kódu.
Za druhé takový seznam ani být nemůže, protože ty ani předem nevíš, v jakém kódu se proces může ocitnout. Kód se dá v Erlangu (un)loadovat za běhu, takže procesu můžeš snadno říct, aby skočil do něčeho, co naloaduješ až za běhu z disku.
No a za třetí, zprávy se můžou matchovat něčím parametrizovaným. Např. součástí vzoru může být proměnná, takže se pokaždé namatchuje něco jiného, předem nevíš co. A taky tam můžou být všelijaké guards apod.
Takže sečteno podtrženo, proces se může "naučit rozumět" zprávám velice snadno a používá se to velice často, prakticky pořád - minimálně proto, že zprávy mají skoro vždycky nějaké parametry, které můžou mít libovolnou strukturu (Erlang nemá typy, takže nevíš, jestli parametrem je integer nebo kompletní slovník spisovné češtiny ;) - tzn. neumíš rozhodnout, jestli proces danou zprávu "umí" nebo ne).
Za prvé - nemluvím. Nic takového si nepředstavuji.
Za druhé - proces má neměnitelný seznam. Když změním proces, ztratím frontu. Takže v tomto to není.
Ale to třetí jsem si právě vyzkoušel a je to ono. Ten vzor se sice měnit nedá, ale dá se napsat něco jako:
{_, _, Pause} = StateData,
receive
{request, increment} when (Pause == false) ->
...
A Erlang to when bere jako součást matchování. To Pause se mi může změnit, a pak se ty zprávy donačtou.
Takže v takovémhle případě to má smysl. Asi.
Něčemu velmi zásadnímu asi nerozumíš, neumím přesně poznat čemu.
> Za prvé - nemluvím. Nic takového si nepředstavuji.
No operuješ s pojmem "proces rozumí", "proces nerozumí". Nic takového prostě není. Ty prostě nevíš, jakou zprávu bude proces matchovat za dvě vteřiny. Víš maximálně to, jaké zprávy matchuje v tom konkrétním receivu, ve kterým se zrovna teď nachází.
> Za druhé - proces má neměnitelný seznam. Když změním proces, ztratím frontu. Takže v tomto to není.
To ale vůbec není pravda. Proces není nijak svázaný s žádným konkrétním kódem. Proces je jenom *vlákno* a předem vůbec nevíš, jaký kód bude vykonávat. Můžeš mu klidně z klávesnice zadat, do jaké funkce jakého modulu má skočit (a pořád je to ten *jeden proces* - není to nějaký "nový" s novou frontou, jenom proto, že skočil někam).
> Takže v takovémhle případě to má smysl. Asi.
Dá se použít i jiný příklad:
receive
X when X==SomeVar -> ...
end
- v SomeVar můžeš mít cokoli. Matchuješ sice jenom jednu konkrétní hodnotu, ale nevíš, jaká to je -> nevíš předem, jakým zprávám bude proces rozumět.
Jo mimochodem, v Erlangu se dají i volat funkce z modulů, jejichž název máš uložený v proměnné - takže už vůbec nevíš, v jakém kódu se proces ocitne (a tímpádem jakým zprávám bude rozumět). Prostě udělat seznam zpráv, kterým v dané době proces rozumí je dost sci-fi a navíc by to nebylo moc k ničemu dobré. Tak, jak to je, to funguje dobře ;)
No samozřejmě. Vždyť je to v článku hned na začátku :-)
Pro mě byla zajímavá informace jen to, že fronta se může zablokovat "schválně"; v patternu receive může být proměnná, a tedy se tento pattern může programově měnit a když se změní, tak se fronta vybere. OK, supr. To je vše.
Zbytek byla jen zbytná vata vzniklá z toho, že apriori předpokládáš, že určitě něčemu nerozumím :-)
> Zbytek byla jen zbytná vata vzniklá z toho, že apriori předpokládáš, že určitě něčemu nerozumím :-)
To ne, ale ptal ses způsobem, kterej tomu nasvědčoval a ostatně jsi to i sám napsal:
Nedochází mi pointa proč je to takto navrženo.
:)
Ono je to totiž navrženo až dechberoucně dobře. A pokud člověku přijde, že ne, tak mu chybí nějaký střípek do mozaiky :) Ostatně to přece není žádná ostuda něco nevědět, ne?
> Ono je to totiž navrženo až dechberoucně dobře.
Snažíš se narvat do otevřených dveří :-)
> chybí nějaký střípek do mozaiky :) Ostatně to přece není žádná ostuda něco nevědět, ne?
Ano. A ten střípek bylo tvůj příspěvek:
> > Nebude. Neslo by tam udelat to, co jsem psal vys (asinchronni odpaleni tasku a vybrani vysledku az se mi to bude hodit).
> Můžeš mi prosím ukázat jak vypadá takové zablokování?
V tom okamžiku mě napadlo ověřit si, zde nejde do těch vzorů narvat nějaký proměnný prvek, pak by to bylo vysvětlení.
Sice to bylo trochu za trest probírat se tvejma příspěvkama, ale jsem rád, že jsi alespoň vůbec reagoval. Přišel jsem na další detail Erlangu. Takže díky.