Vela → pametni predpomnilnik za časovne vrste in drugo

V fintechu moramo pogosto obdelati precej velike količine podatkov o menjalnih tečajih valut. Podatke pridobivamo iz različnih virov in vsak od njih ima svojo predstavo o tem, kako ekstrapolirati menjalne tečaje za jutri, pojutrišnjem, naslednji mesec in celo naslednja tri leta. Ko bi le kdo znal predvideti tečaje pravilno, bi bil čas, da zaprete podjetje in samo neumno menjate denar sem ter tja. Nekateri viri so bolj zanesljivi, nekateri ponujajo popolne smeti, z redkimi vključki skoraj pravilnih vrednosti, vendar za eksotične pare. Naša naloga je presejati teh deset tisoč vrednosti na sekundo in določiti, kaj točno pokazati strankam. Iz ton umazanije in mulja moramo filtrirati eno pravilno vrednost, tako kot to počnejo flamingi pri kosilu.

Vela → pametni predpomnilnik za časovne vrste in drugo

Posebna značilnost flamingov je masiven navzdol zakrivljen kljun, s katerim filtrirajo hrano iz vode ali blata.
  - Wiki

Tako je nastala knjižnica Vela, ki shrani predpomnilnik stanja za več vrednosti v določenih časovnih intervalih. Pod pokrovom sproti filtrira slabe in zastarele podatke ter omogoča tudi dostop do najnovejših N potrjene vrednosti za vsak ključ (v našem primeru valutni pari).

Recimo, da zbiramo tečaje za tri valutne pare. Najenostavnejša definicija Vela za shranjevanje trenutnega stanja bo videti nekako takole:

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

Posodabljanje vrednosti

Vela.put/3 Funkcija bo naredila naslednje v zaporedju:

  • bo povzročil validator na vrednost, če je definirana (glejte poglavje Validacija spodaj);
  • bo dodal vrednost bodisi v vrstico dobrih vrednosti, če je bila validacija uspešna, bodisi v storitveno vrstico :__errors__ drugače;
  • bo povzročilo razvrščanje, če sorter definirana za dani ključ, ali pa bo vrednost preprosto postavila na čelo seznama (LIFO, glejte poglavje Сортировка spodaj);
  • bo obrezal vrstico glede na parameter :limit preneseno ob ustvarjanju;
  • bo vrnil posodobljeno strukturo 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]}

Tudi Vela pripomočke Access, tako da lahko za posodobitev vrednosti uporabite katero koli standardno funkcijo za globoko posodabljanje struktur iz arzenala Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2in Kernel.get_and_update_in/3.

Validacija

Validator je mogoče opredeliti kot:

  • zunanja funkcija z enim argumentom (&MyMod.my_fun/1), bo prejel samo vrednost za preverjanje;
  • zunanja funkcija z dvema argumentoma, &MyMod.my_fun/2, dobila bo par serie, value za validacijo;
  • izvajanje modula Vela.Validator;
  • konfiguracijski parameter thresholdin - neobvezno - compare_by, glejte poglavje Primerjava spodaj.

Če je preverjanje uspešno, je vrednost dodana na seznam pod ustreznim ključem; v nasprotnem primeru pa torka {serie, value} gre v :__errors_.

Primerjava

Vrednosti, shranjene v teh vrsticah, so lahko karkoli. Učiti Vela jih primerjati, je treba prenesti compare_by parameter v definiciji serije (razen če vrednosti ni mogoče primerjati s standardom Kernel.</2); ta parameter mora biti tipa (Vela.value() -> number()). Privzeto je preprosto & &1.

Prav tako lahko posredujete parameter definiciji vrstice comparator za izračun delta vrednosti (min/max); na primer s prenosom Date.diff/2 kot primerjalnik lahko dobite pravilne delte za datume.

Drug priročen način dela je posredovanje parametra threshold, ki določa največje dovoljeno razmerje novo vrednost do {min, max} interval. Ker je naveden kot odstotek, se ček ne uporablja comparatorvendar še vedno uporablja compare_by. Na primer, če želite podati vrednost praga za datume in ure, morate podati compare_by: &DateTime.to_unix/1 (za pridobitev celoštevilske vrednosti) in threshold: 1, zaradi česar so nove vrednosti dovoljene le, če so v ±band interval od trenutnih vrednosti.

Končno lahko uporabite Vela.equal?/2 za primerjavo dveh predpomnilnikov. Če vrednosti definirajo funkcijo equal?/2 ali compare/2, potem bodo te funkcije uporabljene za primerjavo, sicer neumno uporabljamo ==/2.

Pridobivanje vrednosti

Obdelava trenutnega stanja se običajno začne s klicanjem Vela.purge/1, ki odstrani zastarele vrednosti (če validator privezan na timestamps). Nato lahko pokličete Vela.slice/1ki se bo vrnil keyword z imeni vrstic kot ključi in prvimi, dejanskimi vrednostmi.

Lahko tudi uporabite get_in/2/pop_in/2 za dostop na nizki ravni do vrednosti v vsaki vrstici.

Vloga

Vela je lahko izjemno uporaben kot predpomnilnik časovnih vrst v stanju procesa, kot je GenServer/Agent. Želimo, da nikoli ne uporabimo zastarelih vrednosti tečaja in da to naredimo, preprosto ohranjamo proces z obdelanim stanjem Vela, s spodaj prikazanim validatorjem.

@impl Vela.Validator
def valid?(_key, %Rate{} = rate),
  do: Rate.age(rate) < @death_age

и Vela.purge/1 tiho odstrani vse zastarele vrednosti vsakič, ko potrebujemo podatke. Za dostop do dejanskih vrednosti preprosto pokličemo Vela.slice/1, in ko je potrebna majhna zgodovina tečaja (celotna serija), jo preprosto vrnemo - že razvrščeno - s potrjenimi vrednostmi.

Veselo predpomnjenje časovnih vrst!

Vir: www.habr.com

Dodaj komentar