Vela → 時系列などのスマート キャッシュ

フィンテックでは、非常に大量の為替レートデータを処理する必要があることがよくあります。 私たちはさまざまなソースからデータを取得し、それぞれが明日、明後日、来月、さらには今後 XNUMX 年間の為替レートを推定する方法について独自のアイデアを持っています。 誰かが金利を予測できれば 正しく、ビジネスを閉じて、ただ愚かにお金を行き来する時が来ます。 より信頼できるソースもあれば、ほとんど正しい値がまれに含まれる完全なゴミを提供するソースもありますが、エキゾチックなカップル向けです。 私たちの仕事は、これらの毎秒数万の価値をふるいにかけて、顧客に正確に何を表示するかを決定することです。 フラミンゴが昼食時に行うのと同じように、大量の土や泥から XNUMX つの正しい値をフィルタリングする必要があります。

Vela → 時系列などのスマート キャッシュ

フラミンゴの特別な際立った特徴は、下向きに湾曲した巨大なくちばしで、水や泥から食べ物をろ過します。
  -  ウィキ

こうして図書館が誕生しました Vela、指定された時間間隔で複数の値の状態キャッシュを保存します。 内部では、不良データや古いデータをその場でフィルタリングして除外し、最新のデータへのアクセスも提供します。 N 各キーの検証された値 (この場合は通貨ペア)。

XNUMX つの通貨ペアのレートを収集するとします。 最も単純な定義 Vela 現在の状態を保存するには、次のようになります。

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

値の更新

Vela.put/3 この関数は次のことを順番に実行します。

  • 原因になります validator 値が定義されている場合は、値に基づいて (章を参照) 検証 下に);
  • 検証が成功した場合は値を適切な値の行に追加するか、サービス行に値を追加します :__errors__ さもないと;
  • ソートが発生する場合 sorter 指定されたキーに対して定義されるか、単に値をリストの先頭に置きます (LIFOの章を参照 Сортировка 下に);
  • パラメータに従って行をトリミングします :limit 創造に渡されました。
  • 更新された構造を返します 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]}

また Vela 実装する Accessしたがって、値を更新するためにアーセナルから構造を深く更新するための標準関数のいずれかを使用できます。 Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2, Kernel.get_and_update_in/3.

検証

バリデータは次のように定義できます。

  • XNUMX つの引数を持つ外部関数 (&MyMod.my_fun/1)、検証のための値のみを受け取ります。
  • XNUMX つの引数を持つ外部関数、 &MyMod.my_fun/2、彼女はペアを手に入れます serie, value 検証のため。
  • モジュールの実装 Vela.Validator;
  • 構成パラメータ threshold、そして - オプションで - compare_byの章を参照 比較 以下。

検証が成功した場合は、対応するキーの下のリストに値が追加されます。そうでない場合は、タプルが追加されます。 {serie, value} に行く :__errors_.

比較

これらの行に格納される値は何でも構いません。 教えるために Vela それらを比較するには、転送する必要があります compare_by シリーズ定義のパラメータ(値が標準と比較できない場合を除く) Kernel.</2); このパラメータは次のタイプでなければなりません (Vela.value() -> number())。 デフォルトではシンプルです & &1.

また、行定義にパラメータを渡すこともできます。 comparator デルタ値を計算するには(min/max); たとえば、送信することによって Date.diff/2 コンパレーターとして、日付の正しいデルタを取得できます。

もう XNUMX つの便利な作業方法は、パラメーターを渡すことです。 threshold、新しい値に対する最大許容比率を定義します。 {min, max} 間隔。 パーセンテージで指定されるため、チェックでは使用されません。 comparatorしかしまだ使用しています compare_by。 たとえば、日時のしきい値を指定するには、次のように指定する必要があります。 compare_by: &DateTime.to_unix/1 (整数値を取得するため) そして threshold: 1、新しい値が次の値にある場合にのみ許可されます。 ±band 現在の値からの間隔。

最後に、使用できます Vela.equal?/2 XNUMX つのキャッシュを比較します。 値が関数を定義する場合 equal?/2 または compare/2、その場合、これらの関数は比較に使用されます。そうでない場合は、愚かにも使用します。 ==/2.

値の取得

現在の状態の処理は通常、呼び出しから始まります。 Vela.purge/1、古い値を削除します (if validator に縛ら timestamps)。 その後、電話をかけることができます Vela.slice/1どれが戻ってきますか keyword 行名をキーとして使用し、最初の実際の値を使用します。

また使用することができます get_in/2/pop_in/2 各行の値への低レベルのアクセス用。

アプリケーション

Vela 次のようなプロセス状態の時系列キャッシュとして非常に便利です。 GenServer/Agent。 古いコース値は決して使用したくありません。そのためには、プロセスを処理済みの状態に維持するだけです。 Vela、以下に示すバリデータを使用します。

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

и Vela.purge/1 データが必要になるたびに、古い値をすべて静かに削除します。 実際の値にアクセスするには、単に呼び出します Vela.slice/1、コースの小さな履歴 (シリーズ全体) が必要な場合は、検証済みの値を含む単純な履歴を返します。

時系列キャッシュを楽しんでください。

出所: habr.com

コメントを追加します