在金融科技领域,我们经常需要处理大量的货币汇率数据。 我们从不同的来源获得数据,每个人对于如何推断明天、后天、下个月甚至未来三年的汇率都有自己的想法。 如果有人能预测利率就好了 正确地,是时候关闭业务并愚蠢地来回换钱了。 有些来源更可靠,有些提供完全垃圾,很少包含几乎正确的值,但对于异国情调的夫妇来说。 我们的工作是每秒筛选这数以万计的值,并确定到底要向客户展示什么。 我们需要从大量的污垢和淤泥中过滤出一个正确的值,就像火烈鸟在午餐时所做的那样。

火烈鸟的一个显着特征是它们巨大的向下弯曲的喙,它们用它从水或泥土中过滤食物。
-
图书馆就这样诞生了 ,它以指定的时间间隔存储多个值的状态缓存。 在幕后,它可以动态过滤掉不良和过时的数据,并提供对最新数据的访问 N 每个键的验证值(在我们的例子中是货币对)。
假设我们收集三种货币对的汇率。 最简单的定义 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更新值
该函数将按顺序执行以下操作:
- 将造成
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 实施 ,因此您可以使用任何标准函数来深度更新武库中的结构来更新值 : , , , 和 .
验证
验证器可以定义为:
- 带一个参数的外部函数 (
&MyMod.my_fun/1),它只会接收用于验证的值; - 有两个参数的外部函数,
&MyMod.my_fun/2,她会得到一双serie, value用于验证; - 模块实现 ;
- 配置参数
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,当需要课程的一小部分历史记录(整个系列)时,我们只需返回它(已经排序)和经过验证的值。
快乐的时间序列缓存!
来源: habr.com
