在金融科技領域,我們經常需要處理大量的貨幣匯率資料。 我們從不同的來源獲得數據,每個人對於如何推論明天、後天、下個月甚至未來三年的匯率都有自己的想法。 如果有人能預測利率就好了 正確地,是時候關閉業務並愚蠢地來回換錢了。 有些來源更可靠,有些提供完全垃圾,很少包含幾乎正確的值,但對於異國情調的夫婦來說。 我們的工作是每秒鐘篩選這數以萬計的數值,並確定到底要向客戶展示什麼。 我們需要從大量的污垢和淤泥中過濾出一個正確的值,就像火烈鳥在午餐時所做的那樣。
火烈鳥的一個顯著特徵是它們巨大的向下彎曲的喙,它們用它從水或泥土中過濾食物。
-維基
圖書館就這樣誕生了 Vela
假設我們收集三種貨幣對的匯率。 最簡單的定義 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
驗證
驗證器可以定義為:
- 帶一個參數的外部函數 (
&MyMod.my_fun/1
),它只會接收用於驗證的值; - 有兩個參數的外部函數,
&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
作為比較器,您可以獲得正確的日期增量。
另一種方便的工作方式是傳遞參數 threshold
,它定義了新值與 {min, max}
間隔。 由於它被指定為百分比,因此檢查不使用 comparator
但仍使用 compare_by
。 例如,要指定日期時間的閾值,您必須指定 compare_by: &DateTime.to_unix/1
(得到整數值)和 threshold: 1
,導致只有在新值存在的情況下才允許使用新值 ±band
與目前值的間隔。
最後,您可以使用 Vela.equal?/2
比較兩個快取。 如果值定義了一個函數 equal?/2
或 compare/2
,那麼就用這些函數來進行比較,不然我們就傻乎乎的用 ==/2
.
獲取值
處理當前狀態通常從呼叫開始 Vela.purge/1
,這會刪除過時的值(如果 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
,當需要課程的一小部分歷史記錄(整個系列)時,我們只需返回它(已經排序)和經過驗證的值。
快樂的時間序列快取!
來源: www.habr.com