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.
- Wiki
Tak vznikla knihovna Vela, 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
end
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.
и 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.