ইভেন্ট প্রোটোকল উদাহরণ তৈরি করুন

বিল্ড ইভেন্ট প্রোটোকলের সম্পূর্ণ স্পেসিফিকেশন এর প্রোটোকল বাফার সংজ্ঞাতে পাওয়া যাবে। যাইহোক, স্পেসিফিকেশন দেখার আগে কিছু অন্তর্দৃষ্টি তৈরি করা সহায়ক হতে পারে।

একটি সাধারণ বেজেল ওয়ার্কস্পেস বিবেচনা করুন যাতে দুটি খালি শেল স্ক্রিপ্ট 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 ... এই প্রকল্পে তৈরি হওয়া বিল্ড ইভেন্টগুলির বিল্ড গ্রাফ নীচের গ্রাফের অনুরূপ হবে। তীরগুলি পূর্বোক্ত পিতামাতা এবং সন্তানের সম্পর্ক নির্দেশ করে। মনে রাখবেন কিছু বিল্ড ইভেন্ট এবং বেশিরভাগ ক্ষেত্র সংক্ষিপ্ততার জন্য বাদ দেওয়া হয়েছে।

bep-graph

চিত্র 1. BEP গ্রাফ।

প্রাথমিকভাবে, একটি BuildStarted ইভেন্ট প্রকাশিত হয়। ইভেন্টটি আমাদের জানায় যে বিল্ডটি bazel test কমান্ডের মাধ্যমে আহ্বান করা হয়েছিল এবং শিশু ইভেন্টগুলি ঘোষণা করে:

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

প্রথম তিনটি ইভেন্ট কিভাবে Bazel আহ্বান করা হয়েছিল সে সম্পর্কে তথ্য প্রদান করে।

PatternExpanded বিল্ড ইভেন্ট অন্তর্দৃষ্টি প্রদান করে কোন নির্দিষ্ট লক্ষ্যগুলি ... প্যাটার্ন প্রসারিত হয়েছে: //foo:foo_lib এবং //foo:foo_test । এটি শিশুদের হিসাবে দুটি TargetConfigured ইভেন্ট ঘোষণা করে তা করে। লক্ষ্য করুন যে TargetConfigured ইভেন্ট Configuration ইভেন্টটিকে চাইল্ড ইভেন্ট হিসাবে ঘোষণা করে, যদিও TargetConfigured ইভেন্টের আগে Configuration পোস্ট করা হয়েছে।

পিতামাতা এবং সন্তানের সম্পর্কের পাশাপাশি, ইভেন্টগুলি তাদের বিল্ড ইভেন্ট শনাক্তকারী ব্যবহার করে একে অপরকে উল্লেখ করতে পারে। উদাহরণস্বরূপ, উপরের গ্রাফে TargetComplete ইভেন্টটি তার fileSets ক্ষেত্রে NamedSetOfFiles ইভেন্টকে নির্দেশ করে।

ফাইলগুলিকে নির্দেশ করে এমন ইভেন্টগুলি তৈরি করুন সাধারণত ইভেন্টে ফাইলের নাম এবং পাথগুলি এম্বেড করে না। পরিবর্তে, তারা একটি NamedSetOfFiles ইভেন্টের বিল্ড ইভেন্ট শনাক্তকারী ধারণ করে, যেটিতে প্রকৃত ফাইলের নাম এবং পাথ থাকবে। NamedSetOfFiles ইভেন্ট ফাইলগুলির একটি সেটকে একবার রিপোর্ট করার এবং অনেকগুলি লক্ষ্য দ্বারা উল্লেখ করার অনুমতি দেয়। এই কাঠামোটি প্রয়োজনীয় কারণ অন্যথায় কিছু ক্ষেত্রে বিল্ড ইভেন্ট প্রোটোকল আউটপুট আকার ফাইলের সংখ্যার সাথে চতুর্মুখীভাবে বৃদ্ধি পাবে। একটি NamedSetOfFiles ইভেন্টে এর সমস্ত ফাইল এম্বেড নাও থাকতে পারে, তবে পরিবর্তে তাদের বিল্ড ইভেন্ট শনাক্তকারীর মাধ্যমে অন্যান্য NamedSetOfFiles ইভেন্টগুলি দেখুন৷

নীচে উপরের গ্রাফ থেকে //foo:foo_lib টার্গেটের জন্য TargetComplete ইভেন্টের একটি উদাহরণ, প্রোটোকল বাফারের 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) জোড়ার সাথে যুক্ত কর্মের মূল্যায়ন করে। সক্রিয় দিকগুলির সাথে নির্মাণ করার সময়, Bazel অতিরিক্তভাবে একটি প্রদত্ত সক্ষম দিক দ্বারা প্রভাবিত প্রতিটি লক্ষ্যের জন্য (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

একটি নির্দিষ্ট লক্ষ্য (বা দিক) দ্বারা উত্পাদিত নিদর্শনগুলি নির্ধারণ করা একটি সাধারণ BEP ব্যবহারের ক্ষেত্রে যা কিছু প্রস্তুতির সাথে দক্ষতার সাথে করা যেতে পারে। এই বিভাগে NamedSetOfFiles ইভেন্ট দ্বারা অফার করা পুনরাবৃত্ত, ভাগ করা কাঠামো নিয়ে আলোচনা করা হয়েছে, যা একটি Starlark Depset এর কাঠামোর সাথে মেলে।

NamedSetOfFiles ইভেন্টগুলি প্রক্রিয়া করার সময় ভোক্তাদের অবশ্যই কোয়াড্র্যাটিক অ্যালগরিদম এড়াতে যত্ন নিতে হবে কারণ বড় বিল্ডে এমন হাজার হাজার ইভেন্ট থাকতে পারে, যার জন্য দ্বিঘাত জটিলতার সাথে ট্রাভার্সালে কয়েক মিলিয়ন অপারেশনের প্রয়োজন হয়।

namedsetoffiles-bep-graph

চিত্র 2. NamedSetOfFiles BEP গ্রাফ।

একটি NamedSetOfFiles ইভেন্ট সর্বদা BEP স্ট্রীমে একটি TargetComplete বা NamedSetOfFiles ইভেন্টের আগে প্রদর্শিত হয় যা এটির উল্লেখ করে। এটি "পিতা-মাতা-সন্তান" ইভেন্ট সম্পর্কের বিপরীত, যেখানে প্রথম ইভেন্ট বাদে বাকি সবগুলি অন্তত একটি ইভেন্ট ঘোষণা করার পরে উপস্থিত হয়৷ একটি NamedSetOfFiles ইভেন্ট কোন শব্দার্থ ছাড়াই একটি Progress ইভেন্ট দ্বারা ঘোষণা করা হয়।

এই অর্ডার এবং ভাগ করে নেওয়ার সীমাবদ্ধতার প্রেক্ষিতে, BEP স্ট্রীম শেষ না হওয়া পর্যন্ত একজন সাধারণ ভোক্তাকে অবশ্যই সমস্ত NamedSetOfFiles ইভেন্টগুলিকে বাফার করতে হবে। নিম্নলিখিত JSON ইভেন্ট স্ট্রীম এবং পাইথন কোড প্রদর্শন করে যে কীভাবে একটি মানচিত্রকে লক্ষ্য/দৃষ্টি থেকে "ডিফল্ট" আউটপুট গোষ্ঠীতে নির্মিত আর্টিফ্যাক্টে পপুলেট করতে হয়, এবং কীভাবে বিল্ট টার্গেট/দক্ষগুলির একটি উপসেটের জন্য আউটপুটগুলি প্রক্রিয়া করতে হয়:

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)