Vela → slimme cache voor tijdreeksen en meer

Bij fintech moeten we vaak behoorlijk grote hoeveelheden wisselkoersgegevens verwerken. We krijgen gegevens uit verschillende bronnen, en elk van hen heeft zijn eigen idee over hoe de wisselkoersen voor morgen, overmorgen, volgende maand en zelfs de komende drie jaar moeten worden geëxtrapoleerd. Als iemand de koersen maar kon voorspellen juist, zou het tijd zijn om het bedrijf te sluiten en gewoon dom geld heen en weer te wisselen. Sommige bronnen zijn betrouwbaarder, andere leveren complete onzin, met zeldzame insluitsels van bijna correcte waarden, maar dan voor exotische koppels. Het is onze taak om deze tienduizenden waarden per seconde te doorzoeken en te bepalen wat we precies aan klanten moeten laten zien. We moeten uit tonnen vuil en slib de enige juiste waarde filteren, net zoals flamingo's dat tijdens de lunch doen.

Vela → slimme cache voor tijdreeksen en meer

Een bijzonder onderscheidend kenmerk van flamingo's is hun enorme naar beneden gebogen snavel, waarmee ze voedsel uit water of modder filteren.
 - Vicki

Zo werd de bibliotheek geboren Vela, die op gespecificeerde tijdsintervallen een statuscache voor meerdere waarden opslaat. Onder de motorkap filtert het on-the-fly slechte en verouderde gegevens uit en biedt het ook toegang tot de nieuwste gegevens N gevalideerde waarden voor elke sleutel (valutaparen, in ons geval).

Laten we zeggen dat we koersen verzamelen voor drie valutaparen. Eenvoudigste definitie Vela om de huidige status op te slaan, ziet het er ongeveer zo uit:

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

Waarden bijwerken

Vela.put/3 De functie zal achtereenvolgens het volgende doen:

  • zal veroorzaken validator op de waarde, als deze is gedefinieerd (zie hoofdstuk Geldigmaking onderstaand);
  • zal de waarde toevoegen aan de rij met goede waarden als de validatie succesvol was, of aan de servicerij :__errors__ anders;
  • zal sortering veroorzaken als sorter gedefinieerd voor een bepaalde sleutel, of plaatst eenvoudigweg de waarde bovenaan de lijst (LIFO, zie hoofdstuk sorteer- onderstaand);
  • zal de rij trimmen volgens de parameter :limit doorgegeven bij de schepping;
  • zal de bijgewerkte structuur retourneren 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]}

Ook Vela werktuigen Access, zodat u alle standaardfuncties kunt gebruiken voor het diepgaand bijwerken van structuren uit het arsenaal om waarden bij te werken Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2 en Kernel.get_and_update_in/3.

Geldigmaking

Een validator kan worden gedefinieerd als:

  • externe functie met één argument (&MyMod.my_fun/1), ontvangt het alleen de waarde ter validatie;
  • externe functie met twee argumenten, &MyMod.my_fun/2, ze krijgt een paar serie, value ter validatie;
  • module implementeren Vela.Validator;
  • configuratieparameter threshold, en - optioneel - compare_by, zie hoofdstuk Vergelijk hieronder.

Als de validatie succesvol is, wordt de waarde toegevoegd aan de lijst onder de overeenkomstige sleutel; anders de tupel {serie, value} ingestuurd :__errors_.

Сравнение

De waarden die in deze rijen zijn opgeslagen, kunnen van alles zijn. Leren Vela om ze te vergelijken, is het noodzakelijk om over te dragen compare_by parameter in de reeksdefinitie (tenzij de waarden niet kunnen worden vergeleken met de standaard Kernel.</2); deze parameter moet van het type zijn (Vela.value() -> number()). Standaard is het eenvoudig & &1.

U kunt ook een parameter doorgeven aan de rijdefinitie comparator deltawaarden berekenen (min/max); bijvoorbeeld door zenden Date.diff/2 als vergelijker kunt u de juiste delta's voor datums verkrijgen.

Een andere handige manier om te werken is het doorgeven van een parameter threshold, die de maximaal toegestane verhouding van de nieuwe waarde tot definieert {min, max} interval. Omdat het als een percentage is opgegeven, wordt er geen gebruik gemaakt van de cheque comparatormaar gebruikt nog steeds compare_by. Als u bijvoorbeeld een drempelwaarde voor datumtijden wilt opgeven, moet u dit opgeven compare_by: &DateTime.to_unix/1 (om een ​​geheel getal te krijgen) en threshold: 1, waardoor nieuwe waarden alleen worden toegestaan ​​als ze binnen zijn ±band interval vanaf de huidige waarden.

Eindelijk kunt u gebruiken Vela.equal?/2 om twee caches te vergelijken. Als de waarden een functie definiëren equal?/2 of compare/2, dan zullen deze functies ter vergelijking worden gebruikt, anders gebruiken we domweg ==/2.

Waarden verkrijgen

Het verwerken van de huidige status begint meestal met bellen Vela.purge/1, waarmee verouderde waarden worden verwijderd (if validator gelinkt aan timestamps). U kunt dan bellen Vela.slice/1die zal terugkeren keyword met rijnamen als sleutels en de eerste, werkelijke waarden.

U kunt ook gebruiken get_in/2/pop_in/2 voor toegang op laag niveau tot de waarden in elke rij.

toepassing

Vela kan uiterst nuttig zijn als tijdreekscache in een processtatus zoals GenServer/Agent. We willen nooit oude koerswaarden gebruiken, en om dit te doen laten we het proces gewoon met de status verwerkt Vela, met de onderstaande validator.

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

и Vela.purge/1 verwijdert stilletjes alle verouderde waarden elke keer dat we de gegevens nodig hebben. Om toegang te krijgen tot de werkelijke waarden bellen we gewoon Vela.slice/1, en wanneer een kleine geschiedenis van de cursus nodig is (de hele reeks), retourneren we deze eenvoudigweg - al gesorteerd - met gevalideerde waarden.

Veel plezier met het cachen van tijdreeksen!

Bron: www.habr.com

Voeg een reactie