Ve fintech musíme často zpracovávat poměrně masivní objemy dat o směnných kurzech měn. Získáváme data z různých zdrojů a každý z nich má svou vlastní představu o tom, jak extrapolovat směnné kurzy na zítřek, pozítří, příští měsíc a dokonce i další tři roky. Kdyby tak někdo dokázal odhadnout sazby správně, bylo by načase zavřít živnost a jen hloupě měnit peníze tam a zpět. Některé zdroje jsou spolehlivější, některé dodávají úplný odpad, se vzácnými inkluzemi téměř správných hodnot, ale pro exotické páry. Naším úkolem je prosít tyto desítky tisíc hodnot za sekundu a určit, co přesně ukázat zákazníkům. Musíme odfiltrovat jednu správnou hodnotu z tuny špíny a bahna, stejně jako to dělají plameňáci při obědě.

Zvláštním poznávacím znakem plameňáků je jejich mohutný dolů zahnutý zobák, kterým filtrují potravu z vody nebo bahna.
-
Tak vznikla knihovna , která ukládá stavovou mezipaměť pro více hodnot v určených časových intervalech. Pod kapotou za chodu filtruje špatná a zastaralá data a také poskytuje přístup k nejnovějším N ověřené hodnoty pro každý klíč (v našem případě páry měn).
Řekněme, že shromažďujeme kurzy pro tři měnové páry. Nejjednodušší definice Vela pro uložení aktuálního stavu to bude vypadat nějak takto:
defmodule Pairs do
use Vela,
eurusd: [sorter: &Kernel.<=/2],
eurgbp: [limit: 3, errors: 1],
eurcad: [validator: Pairs]
@behaviour Vela.Validator
@impl Vela.Validator
def valid?(:eurcad, rate), do: rate > 0
endAktualizace hodnot
Funkce provede následující v pořadí:
- způsobí
validatorna hodnotě, pokud je definována (viz kapitola Validace níže); - přidá hodnotu buď do řádku dobrých hodnot, pokud bylo ověření úspěšné, nebo do řádku služby
:__errors__v opačném případě; - způsobí třídění, pokud
sorterdefinovaný pro daný klíč, nebo jednoduše umístí hodnotu na začátek seznamu (LIFO, viz kapitola Třídit níže); - ořízne řádek podle parametru
:limitpředán stvoření; - vrátí aktualizovanou strukturu
Vela.
iex|1 > pairs = %Pairs{}
iex|2 > Vela.put(pairs, :eurcad, 1.0)
#⇒ %Pairs{..., eurcad: [1.0], ...}
iex|3 > Vela.put(pairs, :eurcad, -1.0)
#⇒ %Pairs{__errors__: [eurcad: -1.0], ...}
iex|4 > pairs |> Vela.put(:eurusd, 2.0) |> Vela.put(:eurusd, 1.0)
#⇒ %Pairs{... eurusd: [1.0, 2.0]}Také Vela nářadí , takže k aktualizaci hodnot můžete použít kteroukoli ze standardních funkcí pro hlubokou aktualizaci struktur z arzenálu : , , , , a .
Validace
Validátor lze definovat jako:
- externí funkce s jedním argumentem (
&MyMod.my_fun/1), obdrží hodnotu pouze pro ověření; - externí funkce se dvěma argumenty,
&MyMod.my_fun/2, dostane párserie, valuepro validaci; - implementace modulu ;
- konfigurační parametr
thresholda - volitelně -compare_by, viz kapitola Porovnání níže.
Pokud je ověření úspěšné, hodnota je přidána do seznamu pod odpovídající klíč, v opačném případě n-tice {serie, value} poslal v :__errors_.
Porovnání
Hodnoty uložené v těchto řádcích mohou být jakékoli. Učit Vela pro jejich porovnání je nutné přenést compare_by parametr v definici série (pokud hodnoty nelze porovnat se standardem Kernel.</2); tento parametr musí být typu (Vela.value() -> number()). Ve výchozím nastavení je to jednoduché & &1.
Také můžete předat parametr definici řádku comparator vypočítat hodnoty delta (min/max); například vysíláním Date.diff/2 jako komparátor můžete získat správné delty pro data.
Dalším pohodlným způsobem práce je předání parametru threshold, který definuje maximální přípustný poměr nové hodnoty k {min, max} interval. Protože je zadána v procentech, kontrola se nepoužívá comparatorale stále používá compare_by. Chcete-li například zadat prahovou hodnotu pro datum a čas, musíte zadat compare_by: &DateTime.to_unix/1 (pro získání celočíselné hodnoty) a threshold: 1, což způsobí, že nové hodnoty budou povoleny pouze v případě, že jsou v ±band interval od aktuálních hodnot.
Nakonec můžete použít Vela.equal?/2 pro porovnání dvou keší. Pokud hodnoty definují funkci equal?/2 nebo compare/2, pak budou tyto funkce použity pro srovnání, jinak hloupě používáme ==/2.
Získávání hodnot
Zpracování aktuálního stavu obvykle začíná voláním Vela.purge/1, který odstraňuje zastaralé hodnoty (pokud validator vázáno na timestamps). Pak můžete zavolat Vela.slice/1která se vrátí keyword s názvy řádků jako klíči a prvními skutečnými hodnotami.
Můžete také použít get_in/2/pop_in/2 pro nízkoúrovňový přístup k hodnotám v každém řádku.
Aplikace
Vela může být velmi užitečná jako mezipaměť časových řad ve stavu procesu, jako je GenServer/Agent. Chceme nikdy nepoužívat zastaralé hodnoty kurzu, a proto jednoduše udržujeme proces se stavem zpracovaný Vela, s validátorem zobrazeným níže.
@impl Vela.Validator
def valid?(_key, %Rate{} = rate),
do: Rate.age(rate) < @death_ageи Vela.purge/1 tiše odstraní všechny zastaralé hodnoty pokaždé, když data potřebujeme. Pro přístup ke skutečným hodnotám jednoduše zavoláme Vela.slice/1, a když je vyžadována malá historie kurzu (celá řada), jednoduše ji vrátíme - již seřazenou - s ověřenými hodnotami.
Šťastné ukládání časových řad do mezipaměti!
Zdroj: www.habr.com
