Vela → slimme cache voor tijdseries en meer

In fintech, we often have to process quite large volumes of exchange rate data. We obtain data from various sources, each of which has its own approach to extrapolating values for tomorrow, the day after, next month, and even the next three years. If someone could predict rates, bewaar je waterstofperoxide correct, welke beschermingsmiddelen gebruik je bij het werken en hoe kun je jezelf redden bij vergiftigingen — dat zoeken we verderop.we might as well close the business and just awkwardly exchange money back and forth. Some sources are more trusted than others, while some provide nothing but rubbish, with occasional almost-correct values, primarily for exotic pairs. Our job is to sift through these tens of thousands of values each second and determine what to show to clients. We need to filter out the single correct value from tons of dirt and mud, just like flamingos do while feeding.

Vela → slimme cache voor tijdseries en meer

A defining characteristic of flamingos is their massive downward-curved beak, which they use to filter food from water or mud.
 — Wiki

Thus, the library Vela, was born, which stores the cache of states for multiple values over specified time intervals. Under the hood, it instantly filters out bad and outdated data, while also providing access to the latest N validated values for each key (currency pairs, in our case).

Let's say we are collecting rates for three currency pairs. The simplest definition Vela for storing the current state might look something like this:

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

Updating values

Vela.put/3 the function will sequentially do the following:

  • call validator on the value, if one is defined (see section Validation below);
  • add the value either to the good values list if the validation succeeds or to the service list :__errors__ in the other case;
  • call sorting if sorter is defined for this key, or just place the value at the head of the list (LIFO, see section Sorteren below);
  • trim the list according to the parameter :limit passed during creation;
  • return the updated structure 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 implementeert Toegang, zodat je voor het bijwerken van waarden gebruik kunt maken van een van de standaardfuncties voor het diep bijwerken van structuren uit de arsenaal Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2, en Kernel.get_and_update_in/3.

Validation

Een validator kan worden gedefinieerd als:

  • een externe functie met één argument (&MyMod.my_fun/1), die alleen de waarde voor validatie ontvangt;
  • een externe functie met twee argumenten, &MyMod.my_fun/2, die een paar serie, waarde voor validatie ontvangt;
  • een module die Vela.Validator;
  • configuratieparameter threshold, en — optioneel — compare_by, see section Vergelijking hieronder.

Als de validatie succesvol is, wordt de waarde toegevoegd aan de lijst onder de bijbehorende sleutel, anders wordt het paar {serie, waarde} verzonden naar :__errors_.

Vergelijking

Waarden die in deze rijen worden opgeslagen, kunnen van alles zijn. Om ze te leren vergelijken, moet je de Vela parameter in de definitie van de rij doorgeven (tenzij de waarden niet standaard kunnen worden vergeleken) compare_by ); deze parameter moet van het type zijn (Vela.value() -> number()). Standaard is dit gewoon & &1Daarnaast kan in de definitie van de rij de parameter comparator.

worden doorgegeven om de waarden van de verschillen te berekenen ( min max); bijvoorbeeld, door/Date.diff/2door te geven als comparator, kunnen juiste verschillen voor datums worden verkregen. Een andere handige manier van werken is het doorgeven van een parameter , die de maximaal toegestane verhouding van de nieuwe waarde ten opzichte van

{min, max} thresholdinterval. Aangezien dit in procenten is ingesteld, gebruikt de controle geen , maar gebruikt nog steeds en. Bijvoorbeeld, om een drempelwaarde voor datums in te stellen, moet je opgeven mincompare_by: &DateTime.to_unix/1 compare_by(om een geheel getal te krijgen) en threshold: 1 , waardoor nieuwe waarden alleen zijn toegestaan als ze zich in ±bandinterval van de huidige waarden bevinden. Ten slotte kan Vela.equal?/2

worden gebruikt om twee caches te vergelijken. Als de waarden een functie definiëren equal?/2 compare/2 , dan zullen deze functies worden gebruikt voor vergelijking, anders gebruiken we simpelweg of Ontvangen waardenDe verwerking van de huidige status begint meestal met de aanroep ==/2.

Vela.purge/1

, die verouderde waarden verwijdert (als afhankelijk vantimestamps validator ). Vervolgens kan je Vela.slice/1, aanroepen Vela.slice/1, die een teruggeeft keyword met de namen van de rijen als sleutels en de eerste, actuele waarden.

Je kunt ook gebruikmaken van get_in/2/pop_in/2 voor laag-niveau toegang tot de waarden in elke rij.

Toepassing

Vela kan extreem nuttig zijn als een cache voor tijdreeksen in de toestand van een proces van het type GenServer/Agent. We willen nooit verouderde waarde-informatie gebruiken, en daarvoor houden we gewoon een proces bij met een toestand die wordt behandeld Vela, met de validator hieronder weergegeven.

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

en afhankelijk van verwijdert rustig alle verouderde waarden telkens wanneer we gegevens nodig hebben. Voor toegang tot actuele waarden roepen we gewoon Vela.slice/1, en wanneer een klein beetje geschiedenis van de koers vereist is (de gehele reeks), geven we het gewoon terug — al gesorteerd — met gevalideerde waarden.

Veel succes met het cachen van tijdreeksen!

Bron: habr.com

Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers 🔥 Koop betrouwbare webhosting met bescherming tegen DDoS, VPS VDS servers | ProHoster