کارگران مداوم می توانند ساخت شما را سریعتر کنند. اگر اقدامات مکرری در ساخت خود دارید که هزینه راهاندازی بالایی دارند یا از ذخیرهسازی متقاطع سود میبرند، ممکن است بخواهید کارگر مداوم خود را برای انجام این اقدامات پیادهسازی کنید.
سرور Bazel با استفاده از stdin
/ stdout
با کارگر ارتباط برقرار می کند. از استفاده از بافرهای پروتکل یا رشته های JSON پشتیبانی می کند.
پیاده سازی کارگر دارای دو بخش است:
ساختن کارگر
یک کارگر مداوم چند الزام را رعایت می کند:
- WorkRequests را از
stdin
خود می خواند. - WorkResponses (و فقط
WorkResponse
s) را درstdout
خود می نویسد. - پرچم
--persistent_worker
را می پذیرد. wrapper باید پرچم خط فرمان--persistent_worker
را بشناسد و فقط در صورت پاس شدن آن پرچم، خود را پایدار کند، در غیر این صورت باید یک کامپایل یک شات انجام دهد و از آن خارج شود.
اگر برنامه شما این الزامات را رعایت کند، می توان از آن به عنوان یک کارگر مداوم استفاده کرد!
درخواست های کاری
یک WorkRequest
شامل فهرستی از آرگومانها به کارگر، فهرستی از جفتهای path-digest است که نشاندهنده ورودیهایی است که کارگر میتواند به آن دسترسی داشته باشد (این مورد اعمال نمیشود، اما میتوانید از این اطلاعات برای ذخیرهسازی در حافظه پنهان استفاده کنید) و یک شناسه درخواست، که 0 است. برای کارگران تک پلکس
توجه: در حالی که مشخصات بافر پروتکل از "snake case" ( request_id
) استفاده می کند، پروتکل JSON از "camel case" ( requestId
) استفاده می کند. این سند در نمونههای JSON از کیس شتر استفاده میکند، اما وقتی در مورد میدان بدون توجه به پروتکل صحبت میشود، از حالت مار استفاده میکند.
{
"arguments" : ["--some_argument"],
"inputs" : [
{ "path": "/path/to/my/file/1", "digest": "fdk3e2ml23d"},
{ "path": "/path/to/my/file/2", "digest": "1fwqd4qdd" }
],
"requestId" : 12
}
از فیلد verbosity
اختیاری می توان برای درخواست خروجی رفع اشکال اضافی از کارگر استفاده کرد. این کاملاً به کارگر بستگی دارد که چه چیزی و چگونه خروجی بدهد. مقادیر بالاتر نشان دهنده خروجی پرمخاطب تر است. با ارسال پرچم --worker_verbose
به Bazel، قسمت verbosity
روی 10 تنظیم می شود، اما مقادیر کوچکتر یا بزرگتر را می توان به صورت دستی برای مقادیر مختلف خروجی استفاده کرد.
فیلد اختیاری sandbox_dir
فقط توسط کارگرانی استفاده میشود که از sandboxing چندگانه پشتیبانی میکنند.
پاسخ های کاری
یک WorkResponse
حاوی شناسه درخواست، یک کد خروجی صفر یا غیرصفر و یک رشته خروجی است که خطاهای پیش آمده در پردازش یا اجرای درخواست را توصیف می کند. فیلد output
حاوی توضیحات کوتاهی است. گزارش های کامل ممکن است در stderr
کارگر نوشته شود. از آنجا که کارگران ممکن است فقط WorkResponses
را به stdout
بنویسند، معمولاً کارگر stdout
هر ابزاری را که استفاده میکند به stderr
هدایت میکند.
{
"exitCode" : 1,
"output" : "Action failed with the following message:\nCould not find input
file \"/path/to/my/file/1\"",
"requestId" : 12
}
طبق هنجار پروتوباف ها، همه فیلدها اختیاری هستند. با این حال، Bazel به WorkRequest
و WorkResponse
مربوطه نیاز دارد که شناسه درخواست یکسانی داشته باشند، بنابراین اگر شناسه درخواست غیر صفر باشد باید مشخص شود. این یک WorkResponse
معتبر است.
{
"requestId" : 12,
}
request_id
0 یک درخواست "singlelex" را نشان می دهد، زمانی که این درخواست نمی تواند به موازات سایر درخواست ها پردازش شود استفاده می شود. سرور تضمین میکند که یک کارگر معین درخواستهایی را با درخواستهای فقط request_id
0 یا فقط request_id
بزرگتر از صفر دریافت میکند. درخواستهای Singleplex به صورت سریال ارسال میشوند، برای مثال اگر سرور درخواست دیگری را تا زمانی که پاسخی دریافت نکرده است ارسال نکند (به جز درخواستهای لغو، به زیر مراجعه کنید).
یادداشت
- قبل از هر بافر پروتکل طول آن در قالب
varint
است (بهMessageLite.writeDelimitedTo()
مراجعه کنید. - قبل از درخواستها و پاسخهای JSON نشانگر اندازه وجود ندارد.
- درخواستهای JSON همان ساختار پروتوباف را دارند، اما از JSON استاندارد استفاده میکنند و برای همه نامهای فیلد از camel case استفاده میکنند.
- برای حفظ ویژگیهای سازگاری به عقب و جلو مانند protobuf، کارگران JSON باید فیلدهای ناشناخته را در این پیامها تحمل کنند و از پیشفرضهای protobuf برای مقادیر از دست رفته استفاده کنند.
- Bazel درخواست ها را به عنوان protobuf ذخیره می کند و با استفاده از فرمت JSON protobuf به JSON تبدیل می کند
لغو
کارگران می توانند به صورت اختیاری اجازه دهند درخواست های کاری قبل از اتمام آنها لغو شود. این به ویژه در ارتباط با اجرای پویا مفید است، جایی که اجرای محلی می تواند به طور منظم توسط یک اجرای از راه دور سریعتر قطع شود. برای اجازه لغو، supports-worker-cancellation: 1
را به قسمت execution-requirements
اضافه کنید (به زیر مراجعه کنید) و پرچم --experimental_worker_cancellation
را تنظیم کنید.
درخواست لغو یک WorkRequest
با مجموعه فیلد cancel
است (و به طور مشابه یک پاسخ لغو یک WorkResponse
با مجموعه فیلد was_cancelled
است). تنها فیلد دیگری که باید در درخواست لغو یا پاسخ لغو باشد request_id
است که نشان میدهد کدام درخواست لغو شود. فیلد request_id
برای کارگران singleplex 0 یا غیر 0 request_id
یک WorkRequest
قبلا ارسال شده برای کارگران multiplex خواهد بود. سرور ممکن است برای درخواست هایی که کارگر قبلاً به آنها پاسخ داده است درخواست لغو ارسال کند، در این صورت درخواست لغو باید نادیده گرفته شود.
به هر پیام WorkRequest
بدون لغو باید دقیقاً یک بار پاسخ داده شود، چه لغو شده باشد یا نه. هنگامی که سرور یک درخواست لغو ارسال کرد، کارگر ممکن است با یک WorkResponse
با مجموعه request_id
و فیلد was_cancelled
به true پاسخ دهد. ارسال یک WorkResponse
معمولی نیز پذیرفته می شود، اما فیلدهای output
و exit_code
نادیده گرفته می شوند.
هنگامی که پاسخی برای WorkRequest
ارسال شد، کارگر نباید فایل های موجود در فهرست کاری خود را لمس کند. سرور برای پاکسازی فایل ها، از جمله فایل های موقت، رایگان است.
ایجاد قاعده ای که از کارگر استفاده می کند
شما همچنین باید یک قانون ایجاد کنید که اقداماتی را ایجاد کند که باید توسط کارگر انجام شود. ایجاد یک قانون Starlark که از یک کارگر استفاده می کند درست مانند ایجاد هر قانون دیگری است.
علاوه بر این، این قانون نیاز به ارجاع به خود کارگر دارد، و برخی الزامات برای اقداماتی که ایجاد می کند وجود دارد.
اشاره به کارگر
قاعدهای که از worker استفاده میکند باید حاوی فیلدی باشد که به خود کارگر اشاره دارد، بنابراین باید یک نمونه از یک قانون \*\_binary
برای تعریف کارگر خود ایجاد کنید. اگر کارگر شما MyWorker.Java
نام دارد، ممکن است این قانون مرتبط باشد:
java_binary(
name = "worker",
srcs = ["MyWorker.Java"],
)
این برچسب "کارگر" را ایجاد می کند که به باینری کارگر اشاره دارد. سپس قانونی را تعریف می کنید که از کارگر استفاده می کند. این قانون باید یک ویژگی را تعریف کند که به باینری کارگر اشاره دارد.
اگر باینری کارگری که ساخته اید در بسته ای به نام "work" است که در سطح بالای ساخت قرار دارد، ممکن است این تعریف ویژگی باشد:
"worker": attr.label(
default = Label("//work:worker"),
executable = True,
cfg = "exec",
)
cfg = "exec"
نشان می دهد که کارگر باید برای اجرا بر روی پلت فرم اجرای شما ساخته شود تا روی پلت فرم هدف (یعنی کارگر به عنوان ابزار در طول ساخت استفاده می شود).
الزامات اقدام کار
قاعده ای که از کارگر استفاده می کند، اقداماتی را برای کارگر ایجاد می کند. این اقدامات چند الزام دارند.
فیلد "برهان" . این لیستی از رشته ها را می گیرد که همه آنها به جز آخرین آنها آرگومان هایی هستند که هنگام راه اندازی به کارگر منتقل می شوند. آخرین عنصر در لیست "Arguments" یک آرگومان
flag-file
(@-preceded) است. کارگران آرگومان ها را از فایل پرچم مشخص شده بر اساس هر درخواست کاری می خوانند. قانون شما میتواند آرگومانهای غیر راهاندازی را برای کارگر در این فایل پرچم بنویسد.فیلد "اجرای الزامات" ، که یک فرهنگ لغت حاوی
"supports-workers" : "1"
،"supports-multiplex-workers" : "1"
یا هر دو را می گیرد.فیلدهای "Arguments" و "Execution-Requirements" برای تمامی اقدامات ارسالی به کارگران مورد نیاز است. بعلاوه، اقداماتی که باید توسط کارگران JSON اجرا شوند، باید شامل
"requires-worker-protocol" : "json"
در قسمت الزامات اجرا باشند."requires-worker-protocol" : "proto"
نیز یک الزام اجرایی معتبر است، اگرچه برای کارگران پروتو لازم نیست، زیرا آنها پیش فرض هستند.همچنین می توانید یک
worker-key-mnemonic
در الزامات اجرا تنظیم کنید. اگر از فایل اجرایی برای چندین نوع اقدام استفاده مجدد می کنید و می خواهید اقدامات این کارگر را تشخیص دهید، ممکن است مفید باشد.فایلهای موقتی که در طول عملیات تولید میشوند باید در فهرست کاربر ذخیره شوند. این سندباکس را فعال می کند.
با فرض یک تعریف قانون با ویژگی «worker» که در بالا توضیح داده شد، علاوه بر ویژگی «srcs» که ورودیها را نشان میدهد، یک ویژگی «خروجی» نشاندهنده خروجیها، و یک ویژگی «args» نشاندهنده آرگهای راهاندازی کارگر، فراخوانی ctx.actions.run
ممکن است:
ctx.actions.run(
inputs=ctx.files.srcs,
outputs=[ctx.outputs.output],
executable=ctx.executable.worker,
mnemonic="someMnemonic",
execution_requirements={
"supports-workers" : "1",
"requires-worker-protocol" : "json"},
arguments=ctx.attr.args + ["@flagfile"]
)
برای مثال دیگر، به پیاده سازی کارگران پایدار مراجعه کنید.
مثال ها
پایه کد Bazel از کارگران کامپایلر جاوا ، علاوه بر یک مثال کارگر JSON استفاده می کند که در تست های یکپارچه سازی ما استفاده می شود.
شما می توانید از داربست آنها برای تبدیل هر ابزار مبتنی بر جاوا به یک کارگر با ارسال پاسخ تماس صحیح استفاده کنید.
برای مثالی از قاعدهای که از یک کارگر استفاده میکند، نگاهی به تست ادغام کارگران Bazel بیاندازید.
مشارکتکنندگان خارجی کارگران را به زبانهای مختلف پیادهسازی کردهاند. نگاهی به پیاده سازی Polyglot کارگران پایدار Bazel بیندازید. می توانید نمونه های بسیار بیشتری را در GitHub پیدا کنید!