Vela β†’ smart cache para sa serye ng oras at higit pa

Sa fintech, madalas nating kailangang iproseso ang napakalaking volume ng data ng currency exchange rate. Nakakakuha kami ng data mula sa iba't ibang mga mapagkukunan, at bawat isa sa kanila ay may sariling ideya kung paano i-extrapolate ang mga halaga ng palitan para bukas, makalawa, sa susunod na buwan at maging sa susunod na tatlong taon. Kung may makapaghuhula lang ng mga rate wasto, oras na para isara ang negosyo at katangahan na lang magpalit ng pera pabalik-balik. Ang ilang mga mapagkukunan ay mas maaasahan, ang ilan ay nagbibigay ng kumpletong basura, na may mga bihirang pagsasama ng halos tamang mga halaga, ngunit para sa mga kakaibang mag-asawa. Ang aming trabaho ay suriin ang sampu-sampung libong halaga sa bawat segundo at tukuyin kung ano ang eksaktong ipapakita sa mga customer. Kailangan nating salain ang isang tamang halaga mula sa toneladang dumi at banlik, tulad ng ginagawa ng mga flamingo sa tanghalian.

Vela β†’ smart cache para sa serye ng oras at higit pa

Ang isang natatanging tampok ng mga flamingo ay ang kanilang napakalaking pababang hubog na tuka, kung saan sinasala nila ang pagkain mula sa tubig o putik.
 - Wiki

Kaya ipinanganak ang aklatan Vela, na nag-iimbak ng cache ng estado para sa maraming halaga sa mga tinukoy na agwat ng oras. Sa ilalim ng hood, sinasala nito ang masama at hindi napapanahong data sa mabilisang, at nagbibigay din ng access sa pinakabago N napatunayan na mga halaga para sa bawat key (mga pares ng pera, sa aming kaso).

Sabihin nating nangongolekta kami ng mga rate para sa tatlong pares ng pera. Pinakasimpleng kahulugan Vela upang iimbak ang kasalukuyang estado ito ay magiging ganito:

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

Pag-update ng mga Halaga

Vela.put/3 Gagawin ng function ang sumusunod sa pagkakasunud-sunod:

  • magdudulot validator sa halaga, kung ang isa ay tinukoy (tingnan ang kabanata Pagpapatunay sa ibaba);
  • ay magdaragdag ng halaga sa hanay ng mga mahuhusay na halaga kung matagumpay ang pagpapatunay, o sa hanay ng serbisyo :__errors__ kung hindi man;
  • magdudulot ng pag-uuri kung sorter tinukoy para sa isang ibinigay na susi, o ilalagay lamang ang halaga sa ulo ng listahan (LIFO, tingnan ang kabanata Pagsunud-sunod sa ibaba);
  • ay trim ang hilera ayon sa parameter :limit ipinasa sa paglikha;
  • ibabalik ang na-update na istraktura 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]}

Rin Vela nagpapatupad Access, para magamit mo ang alinman sa mga karaniwang function para sa malalim na pag-update ng mga istruktura mula sa arsenal upang i-update ang mga halaga Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2, at Kernel.get_and_update_in/3.

Pagpapatunay

Ang isang validator ay maaaring tukuyin bilang:

  • panlabas na function na may isang argumento (&MyMod.my_fun/1), matatanggap lamang nito ang halaga para sa pagpapatunay;
  • panlabas na function na may dalawang argumento, &MyMod.my_fun/2, makakakuha siya ng isang pares serie, value para sa pagpapatunay;
  • pagpapatupad ng modyul Vela.Validator;
  • parameter ng pagsasaayos threshold, at - opsyonal - compare_by, tingnan ang kabanata paghahambing sa ibaba.

Kung matagumpay ang pagpapatunay, idaragdag ang halaga sa listahan sa ilalim ng kaukulang key; kung hindi, ang tuple {serie, value} pumupunta sa :__errors_.

Paghahambing

Ang mga halaga na nakaimbak sa mga hilera na ito ay maaaring maging anuman. Magturo Vela upang ihambing ang mga ito, ito ay kinakailangan upang ilipat compare_by parameter sa kahulugan ng serye (maliban kung ang mga halaga ay hindi maihahambing sa pamantayan Kernel.</2); ang parameter na ito ay dapat na uri (Vela.value() -> number()). Bilang default, ito ay simple & &1.

Gayundin, maaari kang magpasa ng isang parameter sa kahulugan ng row comparator upang kalkulahin ang mga halaga ng delta (min/max); halimbawa, sa pamamagitan ng pagpapadala Date.diff/2 bilang comparator, maaari mong makuha ang tamang delta para sa mga petsa.

Ang isa pang maginhawang paraan upang gumana ay ang pagpasa ng isang parameter threshold, na tumutukoy sa maximum na pinapayagang ratio ng bagong halaga sa {min, max} pagitan. Dahil ito ay tinukoy bilang isang porsyento, ang tseke ay hindi gumagamit comparatorpero gumagamit pa rin compare_by. Halimbawa, upang tumukoy ng halaga ng threshold para sa mga oras ng petsa, dapat mong tukuyin compare_by: &DateTime.to_unix/1 (upang makakuha ng integer value) at threshold: 1, na nagiging sanhi ng mga bagong value na payagan lamang kung sila ay nasa Β±band pagitan mula sa kasalukuyang mga halaga.

Sa wakas, maaari mong gamitin Vela.equal?/2 upang ihambing ang dalawang cache. Kung ang mga halaga ay tumutukoy sa isang function equal?/2 o compare/2, kung gayon ang mga pag-andar na ito ay gagamitin para sa paghahambing, kung hindi man ay tanga naming ginagamit ==/2.

Pagkuha ng mga halaga

Ang pagpoproseso sa kasalukuyang estado ay karaniwang nagsisimula sa pagtawag Vela.purge/1, na nag-aalis ng mga hindi na ginagamit na halaga (kung validator nakatali sa timestamps). Maaari kang tumawag Vela.slice/1na babalik keyword na may mga pangalan ng row bilang mga susi at ang una, aktwal na mga halaga.

Maaari mo ring gamitin get_in/2/pop_in/2 para sa mababang antas ng pag-access sa mga halaga sa bawat hilera.

App

Vela ay maaaring maging lubhang kapaki-pakinabang bilang isang cache ng serye ng oras sa isang estado ng proseso tulad ng GenServer/Agent. Gusto naming hindi kailanman gumamit ng mga lipas na halaga ng kurso, at para magawa ito ay pinapanatili lang namin ang proseso na naproseso ng estado Vela, kasama ang validator na ipinapakita sa ibaba.

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

ΠΈ Vela.purge/1 tahimik na inaalis ang lahat ng mga stale value sa tuwing kailangan namin ang data. Upang ma-access ang aktwal na mga halaga, tawagan lang namin Vela.slice/1, at kapag ang isang maliit na kasaysayan ng kurso ay kinakailangan (ang buong serye), ibinabalik lang namin ito - nakaayos na - na may mga napatunayang halaga.

Maligayang pag-cache ng serye ng oras!

Pinagmulan: www.habr.com

Magdagdag ng komento