Vela → intelligenter Cache für Zeitreihen und mehr

Im Fintech-Bereich müssen wir häufig große Mengen an Wechselkursdaten verarbeiten. Wir beziehen Daten aus verschiedenen Quellen, und jede von ihnen hat ihre eigene Vorstellung davon, wie man Wechselkurse für morgen, übermorgen, nächsten Monat und sogar die nächsten drei Jahre extrapoliert. Wenn nur jemand die Zinssätze vorhersagen könnte richtig, wäre es an der Zeit, das Geschäft zu schließen und einfach dummerweise Geld hin und her zu wechseln. Einige Quellen sind zuverlässiger, andere liefern kompletten Müll mit seltenen Einschlüssen fast korrekter Werte, allerdings für exotische Paare. Unsere Aufgabe ist es, diese Zehntausende Werte pro Sekunde zu sichten und zu bestimmen, was wir den Kunden genau zeigen möchten. Wir müssen aus Tonnen von Schmutz und Schlick den einzig richtigen Wert herausfiltern, so wie es Flamingos beim Mittagessen tun.

Vela → intelligenter Cache für Zeitreihen und mehr

Ein besonderes Erkennungsmerkmal der Flamingos ist ihr massiver, nach unten gebogener Schnabel, mit dem sie Nahrung aus Wasser oder Schlamm filtern.
 - Wiki

So wurde die Bibliothek geboren Vela, der einen Zustandscache für mehrere Werte in bestimmten Zeitintervallen speichert. Unter der Haube filtert es im Handumdrehen fehlerhafte und veraltete Daten heraus und bietet außerdem Zugriff auf die neuesten N validierte Werte für jeden Schlüssel (in unserem Fall Währungspaare).

Nehmen wir an, wir sammeln Kurse für drei Währungspaare. Einfachste Definition Vela Um den aktuellen Zustand zu speichern, sieht es etwa so aus:

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

Werte aktualisieren

Vela.put/3 Die Funktion führt nacheinander Folgendes aus:

  • wird verursachen validator auf den Wert, falls einer definiert ist (siehe Kapitel Validierung unten);
  • fügt den Wert entweder zur Zeile mit guten Werten hinzu, wenn die Validierung erfolgreich war, oder zur Servicezeile :__errors__ ansonsten;
  • führt zu einer Sortierung, wenn sorter für einen bestimmten Schlüssel definiert oder setzt den Wert einfach an den Anfang der Liste (LIFO, siehe Kapitel Sortierung unten);
  • kürzt die Zeile entsprechend dem Parameter :limit bei der Schöpfung weitergegeben;
  • gibt die aktualisierte Struktur zurück 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]}

Auch Vela implementiert Access, so dass Sie zum Aktualisieren von Werten alle Standardfunktionen für tiefgreifende Aktualisierungsstrukturen aus dem Arsenal verwenden können Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2 und Kernel.get_and_update_in/3.

Validierung

Ein Validator kann wie folgt definiert werden:

  • externe Funktion mit einem Argument (&MyMod.my_fun/1), erhält es nur den Wert zur Validierung;
  • externe Funktion mit zwei Argumenten, &MyMod.my_fun/2, sie wird ein Paar bekommen serie, value zur Validierung;
  • Modulimplementierung Vela.Validator;
  • Konfigurationsparameter threshold, und – optional – compare_by, siehe Kapitel Vergleich unten.

Wenn die Validierung erfolgreich ist, wird der Wert zur Liste unter dem entsprechenden Schlüssel hinzugefügt, andernfalls zum Tupel {serie, value} eingereicht :__errors_.

Vergleich

Die in diesen Zeilen gespeicherten Werte können beliebig sein. Lehren Vela Um sie zu vergleichen, ist eine Übertragung erforderlich compare_by Parameter in der Seriendefinition (es sei denn, die Werte können nicht mit dem Standard verglichen werden). Kernel.</2); Dieser Parameter muss vom Typ sein (Vela.value() -> number()). Standardmäßig ist es einfach & &1.

Sie können auch einen Parameter an die Zeilendefinition übergeben comparator Delta-Werte berechnen (min/max); zum Beispiel durch Übermittlung Date.diff/2 Als Komparator können Sie die korrekten Deltas für Datumsangaben ermitteln.

Eine weitere bequeme Arbeitsweise ist die Übergabe eines Parameters threshold, das das maximal zulässige Verhältnis des neuen Werts zu definiert {min, max} Intervall. Da die Angabe in Prozent erfolgt, entfällt die Prüfung comparatoraber immer noch verwendet compare_by. Um beispielsweise einen Schwellenwert für Datum und Uhrzeit anzugeben, müssen Sie Folgendes angeben compare_by: &DateTime.to_unix/1 (um einen ganzzahligen Wert zu erhalten) und threshold: 1, was dazu führt, dass neue Werte nur dann zulässig sind, wenn sie vorhanden sind ±band Intervall von den aktuellen Werten.

Endlich können Sie es verwenden Vela.equal?/2 um zwei Caches zu vergleichen. Wenn die Werte eine Funktion definieren equal?/2 oder compare/2Dann werden diese Funktionen zum Vergleich verwendet, andernfalls verwenden wir sie dumm ==/2.

Werte gewinnen

Die Bearbeitung des aktuellen Zustands beginnt in der Regel mit dem Aufruf Vela.purge/1, wodurch veraltete Werte entfernt werden (falls validator gebunden timestamps). Dann können Sie anrufen Vela.slice/1was zurückkommen wird keyword mit Zeilennamen als Schlüssel und den ersten tatsächlichen Werten.

Sie können auch verwenden get_in/2/pop_in/2 für den Low-Level-Zugriff auf die Werte in jeder Zeile.

Anwendung

Vela kann als Zeitreihen-Cache in einem Prozesszustand wie … äußerst nützlich sein GenServer/Agent. Wir möchten niemals veraltete Kurswerte verwenden und lassen dazu den Prozess einfach mit dem Status verarbeitet Vela, mit dem unten gezeigten Validator.

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

и Vela.purge/1 Entfernt stillschweigend alle veralteten Werte, wann immer wir die Daten benötigen. Um auf die tatsächlichen Werte zuzugreifen, rufen wir einfach auf Vela.slice/1, und wenn ein kleiner Verlauf des Kurses erforderlich ist (die gesamte Serie), geben wir ihn einfach – bereits sortiert – mit validierten Werten zurück.

Viel Spaß beim Zeitreihen-Caching!

Source: habr.com

Kommentar hinzufügen