Vela → bộ đệm thông minh cho chuỗi thời gian và hơn thế nữa

Trong fintech, chúng ta thường phải xử lý khối lượng dữ liệu tỷ giá hối đoái khá lớn. Chúng tôi lấy dữ liệu từ nhiều nguồn khác nhau và mỗi nguồn đều có ý tưởng riêng về cách ngoại suy tỷ giá hối đoái cho ngày mai, ngày mốt, tháng tới và thậm chí ba năm tới. Giá như ai đó có thể dự đoán tỷ lệ một cách chính xác, đã đến lúc phải đóng cửa doanh nghiệp và cứ ngu ngốc đổi tiền qua lại. Một số nguồn đáng tin cậy hơn, một số cung cấp rác hoàn chỉnh, với những giá trị hiếm hoi gần như chính xác, nhưng dành cho các cặp đôi kỳ lạ. Công việc của chúng tôi là sàng lọc hàng chục nghìn giá trị mỗi giây này và xác định chính xác những gì cần hiển thị cho khách hàng. Chúng ta cần lọc ra một giá trị chính xác từ hàng tấn bụi bẩn và phù sa, giống như cách chim hồng hạc làm vào bữa trưa.

Vela → bộ đệm thông minh cho chuỗi thời gian và hơn thế nữa

Đặc điểm phân biệt đặc biệt của hồng hạc là chiếc mỏ khổng lồ cong xuống, dùng để lọc thức ăn từ nước hoặc bùn.
 - Wiki

Thế là thư viện ra đời Vela, lưu trữ bộ đệm trạng thái cho nhiều giá trị tại các khoảng thời gian được chỉ định. Dưới mui xe, nó lọc nhanh chóng dữ liệu xấu và lỗi thời, đồng thời cung cấp quyền truy cập vào dữ liệu mới nhất N các giá trị được xác thực cho từng khóa (cặp tiền tệ, trong trường hợp của chúng tôi).

Giả sử chúng tôi thu thập tỷ giá cho ba cặp tiền tệ. Định nghĩa đơn giản nhất Vela để lưu trữ trạng thái hiện tại, nó sẽ trông giống như thế này:

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

Cập nhật giá trị

Vela.put/3 Hàm sẽ thực hiện tuần tự như sau:

  • sẽ gây ra validator về giá trị, nếu một giá trị được xác định (xem chương Thẩm định dưới);
  • sẽ thêm giá trị vào hàng giá trị tốt nếu xác thực thành công hoặc vào hàng dịch vụ :__errors__ nếu không thì;
  • sẽ gây ra sự phân loại nếu sorter được xác định cho một khóa nhất định hoặc chỉ đơn giản là đặt giá trị ở đầu danh sách (LIFO, xem chương Sắp xếp dưới);
  • sẽ cắt hàng theo tham số :limit truyền lại sự sáng tạo;
  • sẽ trả về cấu trúc đã cập nhật 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]}

Ngoài ra Vela dụng cụ Access, vì vậy bạn có thể sử dụng bất kỳ hàm tiêu chuẩn nào để cập nhật sâu các cấu trúc từ kho vũ khí để cập nhật giá trị Kernel: Kernel.get_in/2, Kernel.put_in/3, Kernel.update_in/3, Kernel.pop_in/2Kernel.get_and_update_in/3.

Thẩm định

Trình xác thực có thể được định nghĩa là:

  • hàm bên ngoài với một đối số (&MyMod.my_fun/1), nó sẽ chỉ nhận giá trị để xác thực;
  • hàm ngoài có hai đối số, &MyMod.my_fun/2, cô ấy sẽ nhận được một cặp serie, value để xác nhận;
  • triển khai mô-đun Vela.Validator;
  • tham số cấu hình threshold, và - tùy chọn - compare_by, xem chương sự so sánh bên dưới

Nếu xác thực thành công, giá trị sẽ được thêm vào danh sách theo khóa tương ứng; nếu không, bộ dữ liệu sẽ {serie, value} đi tới :__errors_.

So sánh

Các giá trị được lưu trữ trong các hàng này có thể là bất kỳ giá trị nào. Dạy Vela để so sánh chúng, cần phải chuyển compare_by tham số trong định nghĩa chuỗi (trừ khi các giá trị không thể so sánh với tiêu chuẩn Kernel.</2); tham số này phải thuộc loại (Vela.value() -> number()). Theo mặc định thì đơn giản & &1.

Ngoài ra, bạn có thể truyền tham số cho định nghĩa hàng comparator để tính giá trị delta ​​(min/max); ví dụ, bằng cách truyền Date.diff/2 với tư cách là một công cụ so sánh, bạn có thể nhận được các vùng đồng bằng chính xác cho ngày tháng.

Một cách thuận tiện khác để làm việc là truyền tham số threshold, xác định tỷ lệ tối đa cho phép của giá trị mới với {min, max} khoảng thời gian. Vì nó được chỉ định dưới dạng phần trăm nên việc kiểm tra không sử dụng comparatornhưng vẫn sử dụng compare_by. Ví dụ: để chỉ định giá trị ngưỡng cho thời gian ngày, bạn phải chỉ định compare_by: &DateTime.to_unix/1 (để lấy giá trị số nguyên) và threshold: 1, khiến các giá trị mới chỉ được phép nếu chúng nằm trong ±band khoảng cách từ các giá trị hiện tại.

Cuối cùng, bạn có thể sử dụng Vela.equal?/2 để so sánh hai bộ đệm. Nếu các giá trị xác định một hàm equal?/2 hoặc compare/2, thì các hàm này sẽ được dùng để so sánh, nếu không chúng ta sẽ sử dụng một cách ngu ngốc ==/2.

Nhận giá trị

Xử lý trạng thái hiện tại thường bắt đầu bằng việc gọi Vela.purge/1, loại bỏ các giá trị lỗi thời (nếu validator Bị ràng buộc với timestamps). Sau đó bạn có thể gọi Vela.slice/1cái nào sẽ trở lại keyword với tên hàng làm khóa và giá trị thực tế đầu tiên.

Bạn cũng có thể dùng get_in/2/pop_in/2 để truy cập cấp thấp vào các giá trị trong mỗi hàng.

Ứng dụng

Vela có thể cực kỳ hữu ích như một bộ đệm chuỗi thời gian ở trạng thái xử lý như GenServer/Agent. Chúng tôi muốn không bao giờ sử dụng các giá trị khóa học cũ và để làm được điều này, chúng tôi chỉ cần giữ lại quy trình với trạng thái được xử lý Vela, với trình xác nhận được hiển thị bên dưới.

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

и Vela.purge/1 lặng lẽ loại bỏ mọi giá trị cũ mỗi khi chúng ta cần dữ liệu. Để truy cập các giá trị thực tế chúng ta chỉ cần gọi Vela.slice/1và khi cần có một lịch sử nhỏ của khóa học (toàn bộ chuỗi), chúng tôi chỉ cần trả lại nó - đã được sắp xếp - với các giá trị được xác thực.

Chúc mừng chuỗi thời gian lưu vào bộ nhớ đệm!

Nguồn: www.habr.com

Thêm một lời nhận xét