Vela → ذاكرة التخزين المؤقت الذكية للسلاسل الزمنية والمزيد

في مجال التكنولوجيا المالية، يتعين علينا في كثير من الأحيان معالجة كميات هائلة من بيانات أسعار صرف العملات. نحصل على البيانات من مصادر مختلفة، ولكل منها فكرته الخاصة عن كيفية استقراء أسعار الصرف ليوم غد، وبعد غد، والشهر المقبل، وحتى السنوات الثلاث المقبلة. إذا كان شخص ما فقط يستطيع التنبؤ بالمعدلات بشكل صحيح، سيكون الوقت قد حان لإغلاق العمل وتغيير الأموال بغباء ذهابًا وإيابًا. بعض المصادر أكثر موثوقية، وبعضها يقدم نفايات كاملة، مع تضمينات نادرة لقيم صحيحة تقريبًا، ولكن للأزواج الغريبين. مهمتنا هي التدقيق في عشرات الآلاف من القيم في الثانية وتحديد ما سيتم عرضه للعملاء بالضبط. نحن بحاجة إلى تصفية القيمة الصحيحة من أطنان الأوساخ والطمي، تمامًا كما تفعل طيور النحام في الغداء.

Vela → ذاكرة التخزين المؤقت الذكية للسلاسل الزمنية والمزيد

السمة المميزة الخاصة لطيور النحام هي منقارها الضخم المنحني للأسفل، والذي تقوم بتصفية الطعام من الماء أو الطين.
 - ويكي

وهكذا ولدت المكتبة Vela، الذي يقوم بتخزين ذاكرة التخزين المؤقت للحالة لقيم متعددة على فترات زمنية محددة. تحت الغطاء، يقوم بتصفية البيانات السيئة والقديمة بسرعة، كما يوفر إمكانية الوصول إلى الأحدث 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

تحديث القيم

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، الذي يزيل القيم القديمة (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، وعندما تكون هناك حاجة إلى تاريخ صغير للدورة (السلسلة بأكملها)، فإننا ببساطة نعيدها - التي تم فرزها بالفعل - بالقيم التي تم التحقق من صحتها.

التخزين المؤقت لسلسلة زمنية سعيدة!

المصدر: www.habr.com

إضافة تعليق