أمثلة على بروتوكول إنشاء الحدث

يمكن العثور على المواصفات الكاملة لبروتوكول أحداث الإصدار في تعريف المخزن المؤقت للبروتوكول الخاص بها. وقد يكون من المفيد بناء بعض المشاعر قبل الاطّلاع على المواصفات.

ننصحك باستخدام مساحة عمل Bazel بسيطة تتألف من نصَين برمجيَين فارغَين لتطبيق Shell foo.sh وfoo_test.sh وملف BUILD التالي:

sh_library(
    name = "foo_lib",
    srcs = ["foo.sh"],
)

sh_test(
    name = "foo_test",
    srcs = ["foo_test.sh"],
    deps = [":foo_lib"],
)

عند تنفيذ bazel test ... في هذا المشروع، سيشبه الرسم البياني الخاص بإصدار أحداث الإصدار التي تم إنشاؤها الرسم البياني أدناه. يشير السهمان إلى العلاقة بين الطفل والوالدَين المذكورَين أعلاه. يُرجى العِلم أنه قد تم حذف بعض أحداث الإصدار ومعظم الحقول بغرض الإيجاز.

رسم بياني

الشكل 1. BEP رسم بياني.

في البداية، يتم نشر حدث BuildStarted. يخبرنا الحدث بأن الإصدار تم استدعاؤه من خلال الأمر bazel test والإعلان عن أحداث فرعية:

  • OptionsParsed
  • WorkspaceStatus
  • CommandLine
  • UnstructuredCommandLine
  • BuildMetadata
  • BuildFinished
  • PatternExpanded
  • Progress

الأحداث الثلاثة الأولى تقدم معلومات عن كيفية استدعاء Bazel.

ويقدّم حدث الإصدار PatternExpanded إحصاءات حول الاستهدافات المحدّدة التي يتم توسيع نمط ... إليها: //foo:foo_lib و//foo:foo_test. وينفّذ ذلك عن طريق الإعلان عن حدثَين (TargetConfigured) باعتبارهما أطفالاً. تجدر الإشارة إلى أن الفعالية TargetConfigured تُعلن أنّ الحدث Configuration هو فعالية فرعية، على الرغم من نشر السمة Configuration قبل فعالية TargetConfigured.

بالإضافة إلى العلاقة بين الوالدَين والطفل، قد تشير الأحداث أيضًا إلى بعضها البعض باستخدام معرّفات أحداث الإصدار الخاصة بها. على سبيل المثال، في الرسم البياني أعلاه، يشير الحدث TargetComplete إلى الحدث NamedSetOfFiles في حقل fileSets.

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

في ما يلي مثال على حدث TargetComplete للهدف //foo:foo_lib من الرسم البياني أعلاه المطبوع في تمثيل JSON للمخزن المؤقت للبروتوكولات. يحتوي معرّف حدث الإصدار على الهدف كسلسلة مبهمة، ويشير إلى حدث Configuration باستخدام معرّف حدث الإصدار. ولا يعلن الحدث عن أي أحداث فرعية. تحتوي البيانات الأساسية على معلومات عمّا إذا تم إنشاء الهدف بنجاح ومجموعة ملفات الناتج ونوع الاستهداف الذي تم إنشاؤه.

{
  "id": {
    "targetCompleted": {
      "label": "//foo:foo_lib",
      "configuration": {
        "id": "544e39a7f0abdb3efdd29d675a48bc6a"
      }
    }
  },
  "completed": {
    "success": true,
    "outputGroup": [{
      "name": "default",
      "fileSets": [{
        "id": "0"
      }]
    }],
    "targetKind": "sh_library rule"
  }
}

عرض نسبة العرض إلى الارتفاع في لوحة اللمس

تُقيِّم الإصدارات العادية الإجراءات المرتبطة بعمليات إقران (target, configuration). وعند إنشاء مواقع إلكترونية مفعّلة، يقيّم البازيل أيضًا الأهداف المرتبطة بثلاث مرات (target, configuration, aspect)، في كل هدف متأثر جانب معيّن تم تفعيله.

تتوفر نتائج التقييم للجوانب في BEP على الرغم من عدم وجود أنواع أحداث محددة. لكل زوج من (target, configuration) له جانب ينطبق، تنشر Bazel حدث TargetConfigured وTargetComplete إضافيًا يحمل النتيجة من تطبيق الجانب على الهدف. على سبيل المثال، إذا تم إنشاء //:foo_lib باستخدام --aspects=aspects/myaspect.bzl%custom_aspect، سيظهر هذا الحدث أيضًا في ملف BEP:

{
  "id": {
    "targetCompleted": {
      "label": "//foo:foo_lib",
      "configuration": {
        "id": "544e39a7f0abdb3efdd29d675a48bc6a"
      },
      "aspect": "aspects/myaspect.bzl%custom_aspect"
    }
  },
  "completed": {
    "success": true,
    "outputGroup": [{
      "name": "default",
      "fileSets": [{
        "id": "1"
      }]
    }]
  }
}

استهلاك NamedSetOfFiles

ويُعدّ تحديد القطع الأثرية الناتجة عن هدف (أو جانب) معيّن حالة استخدام شائعة يمكن تنفيذها بشكل فعّال مع بعض الاستعدادات. يناقش هذا القسم البنية المتكررة والمتكررة التي يقدمها حدث NamedSetOfFiles، والتي تطابق بنية ستارلارك Depset.

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

cannot translate

الشكل 2. رسم بياني لـ BEP NamedSetOfFiles.

تظهر الفعالية NamedSetOfFiles دائمًا في بث BEP قبل الحدث TargetComplete أو NamedSetOfFiles الذي يشير إليه. ويكون هذا هو عكس الحدث "&&;;Child-child" حيث يظهر الكل ولكن الحدث الأول بعد حدث واحد على الأقل يعلن عنه. يتم الإعلان عن فعالية NamedSetOfFiles من خلال فعالية Progress لا تتضمّن دلالات.

نظرًا لقيود الترتيب والمشاركة هذه، على المستهلك العادي تخزين كل NamedSetOfFiles أحداث حتى يتم استنفاد ساحة مشاركات BEP. يوضّح تدفق حدث JSON ورمز Python التالي كيفية تعبئة خريطة من العناصر المستهدفة/النسبية إلى العناصر المُصمَّمة في مجموعة الإخراج ومضمونة وكيفية استخراج النتائج لمجموعة فرعية من الأهداف/الجوانب المنشأة:

named_sets = {}  # type: dict[str, NamedSetOfFiles]
outputs = {}     # type: dict[str, dict[str, set[str]]]

for event in stream:
  kind = event.id.WhichOneof("id")
  if kind == "named_set":
    named_sets[event.id.named_set.id] = event.named_set_of_files
  elif kind == "target_completed":
    tc = event.id.target_completed
    target_id = (tc.label, tc.configuration.id, tc.aspect)
    outputs[target_id] = {}
    for group in event.completed.output_group:
      outputs[target_id][group.name] = {fs.id for fs in group.file_sets}

for result_id in relevant_subset(outputs.keys()):
  visit = outputs[result_id].get("default", [])
  seen_sets = set(visit)
  while visit:
    set_name = visit.pop()
    s = named_sets[set_name]
    for f in s.files:
      process_file(result_id, f)
    for fs in s.file_sets:
      if fs.id not in seen_sets:
        visit.add(fs.id)
        seen_sets.add(fs.id)