Vela → smart cache til tidsserier og mere

I finanssektoren må vi ofte håndtere ret store mængder data vedrørende valutakurser. Vi henter data fra forskellige kilder, og hver af dem har sin egen måde at ekstrapolere værdierne for kurserne til i morgen, overmorgen, næste måned og endda de næste tre år. Hvis nogen kunne forudsige kurserne, er det vigtigt, ville det være på tide at lukke forretningen og bare skifte penge frem og tilbage. Nogle kilder nyder større tillid, mens andre leverer rent skrammel med sjældne indslag af næsten korrekte værdier, men mest for eksotiske par. Vores opgave er at silke disse titusindvis af værdier per sekund og bestemme, hvad vi egentlig skal vise vores kunder. Vi skal filtrere det ene korrekte værd fra en bunke skidt og mudder, ligesom flamingoer gør ved frokost.

Vela → smart cache til tidsserier og mere

Et særligt kendetegn ved flamingoen er dens massive, nedadvendte næb, som de bruger til at filtrere føde fra vand eller mudder.
 — Wikipedia

Sådan blev biblioteket Vela, som opbevarer cache-tilstanden for flere værdier inden for angivne tidsintervaller, født. Under motorhjelmen sorterer det automatisk dårlige og forældede data og giver også adgang til de seneste N validerede værdier for hver nøgle (valutapar i vores tilfælde).

Lad os antage, at vi indsamler kurser for tre valutapar. Den enkleste definition Vela for at opbevare den aktuelle tilstand vil se nogenlunde sådan ud:

defmodule Pairs do
  use Vela,
    eurusd: [sorter: &Kernel. 0
end

Opdatering af værdierne

Vela.put/3 funktionen vil sekventielt gøre følgende:

  • kalde validator på værdien, hvis en sådan er defineret (se kapitel Validering nedenfor);
  • tilføje værdien enten til rækken af gode værdier, hvis valideringen er blevet bestået, eller til den interne række :__errors__ i modsætning til;
  • kalde sortering, hvis sorter er defineret for denne nøgle, eller bare placere værdien i toppen af listen (LIFO, se kapitel Sortering nedenfor);
  • skære rækken i henhold til parameteren :limit givet ved oprettelsen;
  • returnere den opdaterede struktur Vela.

iex|1 > par = %Pairs{}
iex|2 > Vela.put(par, :eurcad, 1.0)
#⇒ %Pairs{..., eurcad: [1.0], ...}
iex|3 > Vela.put(par, :eurcad, -1.0)
#⇒ %Pairs{__errors__: [eurcad: -1.0], ...}
iex|4 > par |> Vela.put(:eurusd, 2.0) |> Vela.put(:eurusd, 1.0)
#⇒ %Pairs{... eurusd: [1.0, 2.0]}

Derudover Vela implementerer Adgang, så man kan opdatere værdier ved at bruge en hvilken som helst af de standardfunktioner til dyb opdatering af strukturer Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2, og Kernel.get_and_update_in/3.

Validering

Valideren kan defineres som:

  • en ekstern funktion med et argument (&MyMod.my_fun/1), den vil kun modtage værdien til validering;
  • en ekstern funktion med to argumenter, &MyMod.my_fun/2, den vil modtage parret serie, værdi til validering;
  • modul, der implementerer Vela.Validator;
  • konfigurationsparameter grænseværdi, og — valgfrit — compare_by, se kapitel Sammenligning nedenfor.

Hvis valideringen var vellykket, vil værdien blive tilføjet til listen under den relevante nøgle, ellers returneres tuple {serie, værdi} til :__errors_.

Sammenligning

Værdierne, der gemmes i disse rækker, kan være vilkårlige. For at lære Vela dem at sammenligne, skal man give compare_by parameteren i rædefsiniton (medmindre værdierne kan sammenlignes med standard Kernel.<\/2); denne parameter skal have typen (Vela.value() -> number()). Som standard er det simpelthen & &1.

Derudover kan man i rædefiniton overføre parameteren comparator til beregning af delta-værdier (min/max); for eksempel, ved at overføre Date.diff/2 som en comparator, kan man få korrekte deltaløsninger for datoer.

En anden praktisk metode er at give parameteren grænseværdi, der definerer det maksimalt tilladte forhold mellem den nye værdi og {min, max} intervallet. Da den er angivet i procent, bruger tjekket ikke comparator, men bruger stadig compare_by. For eksempel, for at angive en grænseværdi for tidsdatoer, skal man angive compare_by: &DateTime.to_unix/1 (for at få et heltalsværdi) og grænseværdi: 1, hvilket gør, at nye værdier kun er tilladt, hvis de ligger inden for ±bånd intervallet fra de nuværende værdier.

Endelig kan man bruge Vela.equal?/2 compare/2 , hvis værdierne definerer funktionen eller equal?/2compare/2 ==/2.

, så vil disse funktioner blive brugt til sammenligning, ellers bruger vi bare

Hentning af værdier Behandling af den nuværende tilstand begynder normalt med at kaldeVela.purge/1 validator , som fjerner forældede værdier (hvis bundet tiltimestamps. ) Derefter kan man kalde Vela.slice/1, der returnerer nøgleord med rækkerne som nøgler og de første, aktuelle værdier.

Man kan også benytte get_in/2/pop_in/2 til lavniveauadgang til værdierne i hver række.

Applikation

Vela kan vise sig at være ekstremt nyttig som cache til tidsserier i tilstanden af en type GenServer/Agent. Vi ønsker aldrig at bruge forældede valutakurser, og for dette holder vi simpelthen en proces med en tilstand, der behandles Vela, med en validator, der vises nedenfor.

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

og Behandling af den nuværende tilstand begynder normalt med at kalde fint fjerner alle forældede værdier hver gang vi har brug for data. For at tilgå de aktuelle værdier kalder vi simpelthen ) Derefter kan man kalde Vela.slice/1, og når vi har brug for en lille historik over kursen (hele rækken), returnerer vi den bare – allerede sorteret – med validerede værdier.

God caching af tidsserier!

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster