ผู้ปฏิบัติงานแบบถาวรจะช่วยให้บิลด์เร็วขึ้น หากคุณมีการดำเนินการซ้ำๆ ในบิลด์ที่มีต้นทุนเริ่มต้นสูงหรือจะได้รับประโยชน์จากการแคชข้ามการดำเนินการ คุณอาจต้องใช้ Worker แบบถาวรของคุณเองเพื่อดำเนินการเหล่านี้
เซิร์ฟเวอร์ Bazel สื่อสารกับ Worker โดยใช้ stdin/stdout ซึ่งรองรับการใช้บัฟเฟอร์โปรโตคอลหรือสตริง JSON
การใช้งาน Worker มี 2 ส่วน ดังนี้
การสร้างผู้ปฏิบัติงาน
Worker ที่ทำงานอย่างต่อเนื่องจะปฏิบัติตามข้อกำหนด 2-3 ข้อต่อไปนี้
- โดยจะอ่านWorkRequestsจากstdin
- โดยจะเขียน
WorkResponses 
(และเฉพาะ WorkResponses) ไปยังstdout
- โดยรับธง --persistent_workerWrapper ต้องรู้จัก--persistent_workerแฟล็กบรรทัดคำสั่ง และต้องทำให้ตัวเองคงอยู่เฉพาะในกรณีที่มีการส่งแฟล็กนั้น ไม่เช่นนั้นจะต้องทำการคอมไพล์แบบครั้งเดียวและออก
หากโปรแกรมของคุณเป็นไปตามข้อกำหนดเหล่านี้ ก็สามารถใช้เป็น Worker ที่ทำงานตลอดเวลาได้
คำของาน
WorkRequest มีรายการอาร์กิวเมนต์สำหรับ Worker, รายการคู่เส้นทาง-แฮชที่แสดงอินพุตที่ Worker เข้าถึงได้ (ระบบไม่ได้บังคับ แต่คุณใช้ข้อมูลนี้สำหรับการแคชได้) และรหัสคำขอ ซึ่งเป็น 0 สำหรับ Worker แบบ Singleplex
หมายเหตุ: แม้ว่าข้อกำหนดของบัฟเฟอร์โปรโตคอลจะใช้ "snake case" (request_id)
แต่โปรโตคอล JSON จะใช้ "camel case" (requestId) เอกสารนี้ใช้ camel case
ในตัวอย่าง JSON แต่ใช้ snake case เมื่อพูดถึงฟิลด์โดยไม่คำนึงถึง
โปรโตคอล
{
  "arguments" : ["--some_argument"],
  "inputs" : [
    { "path": "/path/to/my/file/1", "digest": "fdk3e2ml23d"},
    { "path": "/path/to/my/file/2", "digest": "1fwqd4qdd" }
 ],
  "requestId" : 12
}
ฟิลด์ verbosity ที่ไม่บังคับใช้เพื่อขอเอาต์พุตการแก้ไขข้อบกพร่องเพิ่มเติม
จาก Worker โดยผู้ปฏิบัติงานจะเป็นผู้กำหนดเอาต์พุตและวิธีการเอาต์พุตทั้งหมด ค่าที่สูงขึ้น
บ่งบอกถึงเอาต์พุตที่ละเอียดมากขึ้น การส่งแฟล็ก --worker_verbose ไปยัง
Bazel จะตั้งค่าฟิลด์ verbosity เป็น 10 แต่คุณสามารถใช้ค่าที่เล็กกว่าหรือใหญ่กว่า
ด้วยตนเองสำหรับเอาต์พุตจำนวนต่างๆ ได้
sandbox_dirฟิลด์ที่ไม่บังคับใช้โดยผู้ปฏิบัติงานที่รองรับแซนด์บ็อกซ์แบบมัลติเพล็กซ์เท่านั้น
การตอบกลับที่ทำงาน
WorkResponseมีรหัสคำขอ รหัสออกเป็น 0 หรือไม่ใช่ 0 และข้อความเอาต์พุตที่อธิบายข้อผิดพลาดที่พบในการประมวลผลหรือการดำเนินการคำขอ
 Worker ควรบันทึกstdoutและstderrของเครื่องมือที่เรียกใช้ และรายงานผ่านWorkResponse การเขียนไปยัง stdout ของ
กระบวนการ Worker ไม่ปลอดภัยเนื่องจากจะรบกวนโปรโตคอล Worker
การเขียนไปยัง stderr ของกระบวนการ Worker นั้นปลอดภัย แต่ระบบจะรวบรวมผลลัพธ์ในไฟล์บันทึกต่อ Worker แทนที่จะระบุเป็นการดำเนินการแต่ละรายการ
{
  "exitCode" : 1,
  "output" : "Action failed with the following message:\nCould not find input
    file \"/path/to/my/file/1\"",
  "requestId" : 12
}
ตามมาตรฐานของ Protobufs คุณไม่จำเป็นต้องกรอกข้อมูลครบทุกช่อง อย่างไรก็ตาม Bazel กำหนดให้ WorkRequest และ WorkResponse ที่เกี่ยวข้องต้องมีรหัสคำขอเดียวกัน ดังนั้นต้องระบุรหัสคำขอหากไม่ใช่ 0 นี่คือ
WorkResponse ที่ถูกต้อง
{
  "requestId" : 12,
}
request_id ที่มีค่าเป็น 0 แสดงถึงคำขอ "ซิงเกิลเพล็กซ์" ซึ่งใช้เมื่อประมวลผลคำขอนี้
แบบขนานกับคำขออื่นๆ ไม่ได้ เซิร์ฟเวอร์รับประกันว่า
ผู้ปฏิบัติงานที่กำหนดจะได้รับคำขอที่มี request_id 0 เท่านั้นหรือมี
request_id มากกว่า 0 เท่านั้น คำขอ Singleplex จะส่งเป็นชุด ตัวอย่างเช่น หากเซิร์ฟเวอร์ไม่ส่งคำขออื่นจนกว่าจะได้รับการตอบกลับ (ยกเว้นคำขอยกเลิก โปรดดูด้านล่าง)
หมายเหตุ
- แต่ละบัฟเฟอร์โปรโตคอลจะมีคำนำหน้าเป็นความยาวในรูปแบบ varint(ดูMessageLite.writeDelimitedTo()
- คำขอและการตอบกลับ JSON จะไม่มีตัวบ่งชี้ขนาดนำหน้า
- คำขอ JSON จะคงโครงสร้างเดียวกับ Protobuf แต่ใช้ JSON มาตรฐาน และใช้รูปแบบ Camel Case สำหรับชื่อฟิลด์ทั้งหมด
- เพื่อให้คงคุณสมบัติความเข้ากันได้แบบย้อนกลับและไปข้างหน้าเช่นเดียวกับ Protobuf ผู้ปฏิบัติงาน JSON ต้องยอมรับฟิลด์ที่ไม่รู้จักในข้อความเหล่านี้ และใช้ค่าเริ่มต้นของ Protobuf สำหรับค่าที่ขาดหายไป
- Bazel จัดเก็บคำขอเป็น Protobuf และแปลงเป็น JSON โดยใช้รูปแบบ JSON ของ Protobuf
การยกเลิก
ผู้ปฏิบัติงานสามารถเลือกอนุญาตให้ยกเลิกคำของานก่อนที่จะเสร็จสิ้นได้
ซึ่งมีประโยชน์อย่างยิ่งในการเชื่อมต่อกับการดำเนินการแบบไดนามิก ซึ่งการดำเนินการในเครื่องอาจถูกขัดจังหวะเป็นประจำด้วยการดำเนินการจากระยะไกลที่เร็วกว่า หากต้องการอนุญาตให้ยกเลิก ให้เพิ่ม supports-worker-cancellation: 1 ลงในช่อง
execution-requirements (ดูด้านล่าง) และตั้งค่าแฟล็ก
--experimental_worker_cancellation
คำขอยกเลิกคือ WorkRequest ที่ตั้งค่าฟิลด์ cancel (และในทำนองเดียวกัน การตอบกลับการยกเลิกคือ WorkResponse ที่ตั้งค่าฟิลด์ was_cancelled) ฟิลด์อื่นเดียวที่ต้องอยู่ในคำขอยกเลิกหรือการตอบกลับการยกเลิกคือ request_id ซึ่งระบุคำขอที่จะยกเลิก request_id
ฟิลด์จะเป็น 0 สำหรับ Worker แบบ Singleplex หรือ request_id ที่ไม่ใช่ 0 ของ WorkRequest ที่ส่งก่อนหน้านี้
สำหรับ Worker แบบ Multiplex เซิร์ฟเวอร์อาจส่งคำขอยกเลิก
สำหรับคำขอที่ Worker ตอบกลับไปแล้ว ในกรณีนี้
ต้องไม่สนใจคำขอยกเลิก
ข้อความWorkRequestที่ไม่ใช่การยกเลิกแต่ละข้อความต้องได้รับการตอบกลับเพียงครั้งเดียว ไม่ว่าจะมีการยกเลิกหรือไม่ก็ตาม เมื่อเซิร์ฟเวอร์ส่งคำขอยกเลิกแล้ว Worker อาจตอบกลับด้วย WorkResponse โดยตั้งค่า request_id และตั้งค่าฟิลด์ was_cancelled
เป็นจริง นอกจากนี้ยังยอมรับการส่ง WorkResponse ปกติด้วย แต่ระบบจะไม่สนใจฟิลด์
output และ exit_code
เมื่อส่งการตอบกลับสำหรับ WorkRequest แล้ว ผู้ปฏิบัติงานต้องไม่แตะต้อง
ไฟล์ในไดเรกทอรีการทำงาน เซิร์ฟเวอร์มีอิสระในการล้างไฟล์
รวมถึงไฟล์ชั่วคราว
การสร้างกฎที่ใช้ Worker
นอกจากนี้ คุณยังต้องสร้างกฎที่สร้างการดำเนินการซึ่ง Worker จะต้องทำด้วย การสร้างกฎ Starlark ที่ใช้ Worker ก็เหมือนกับการสร้างกฎอื่นๆ
นอกจากนี้ กฎต้องมีการอ้างอิงถึง Worker เอง และ การดำเนินการที่กฎสร้างขึ้นต้องเป็นไปตามข้อกำหนดบางอย่าง
การอ้างอิงถึงผู้ปฏิบัติงาน
กฎที่ใช้ Worker ต้องมีฟิลด์ที่อ้างอิงถึง Worker เอง ดังนั้นคุณจะต้องสร้างอินสแตนซ์ของกฎ \*\_binary เพื่อกำหนด Worker หาก Worker ชื่อ MyWorker.Java กฎที่เกี่ยวข้องอาจเป็นดังนี้
java_binary(
    name = "worker",
    srcs = ["MyWorker.Java"],
)
ซึ่งจะเป็นการสร้างป้ายกำกับ "worker" ซึ่งหมายถึงไบนารีของ Worker จากนั้นคุณจะ กำหนดกฎที่ใช้ Worker กฎนี้ควรกำหนดแอตทริบิวต์ที่อ้างอิงไบนารีของ Worker
หากไบนารีของ Worker ที่คุณสร้างอยู่ในแพ็กเกจชื่อ "work" ซึ่งอยู่ที่ระดับบนสุดของการบิลด์ คำจำกัดความของแอตทริบิวต์อาจเป็นดังนี้
"worker": attr.label(
    default = Label("//work:worker"),
    executable = True,
    cfg = "exec",
)
cfg = "exec" ระบุว่าควรสร้าง Worker ให้ทำงานบน
แพลตฟอร์มการดำเนินการของคุณแทนที่จะเป็นบนแพลตฟอร์มเป้าหมาย (กล่าวคือ ใช้ Worker
เป็นเครื่องมือในระหว่างการสร้าง)
ข้อกำหนดในการดำเนินการเกี่ยวกับงาน
กฎที่ใช้ Worker จะสร้างการดำเนินการให้ Worker ทำ การดำเนินการเหล่านี้มีข้อกำหนดบางอย่าง
- ฟิลด์ "arguments" ซึ่งรับรายการสตริง โดยสตริงทั้งหมด ยกเว้นสตริงสุดท้าย จะเป็นอาร์กิวเมนต์ที่ส่งไปยัง Worker เมื่อเริ่มต้น องค์ประกอบสุดท้ายในรายการ "arguments" คืออาร์กิวเมนต์ - flag-file(นำหน้าด้วย @) Worker อ่านอาร์กิวเมนต์จากไฟล์แฟล็กที่ระบุตาม WorkRequest แต่ละรายการ กฎของคุณสามารถเขียนอาร์กิวเมนต์ที่ไม่ใช่การเริ่มต้นสำหรับ Worker ไปยังแฟล็กไฟล์นี้ได้
- ฟิลด์ "execution-requirements" ซึ่งรับพจนานุกรมที่มี - "supports-workers" : "1",- "supports-multiplex-workers" : "1"หรือทั้งสองอย่าง- ฟิลด์ "arguments" และ "execution-requirements" เป็นฟิลด์ที่จำเป็นสำหรับ การดำเนินการทั้งหมดที่ส่งไปยังผู้ปฏิบัติงาน นอกจากนี้ การดำเนินการที่ควรดำเนินการโดย Worker JSON ต้องมี - "requires-worker-protocol" : "json"ใน ช่องข้อกำหนดในการดำเนินการ- "requires-worker-protocol" : "proto"ยังเป็น ข้อกำหนดการดำเนินการที่ถูกต้องด้วย แม้ว่าจะไม่จำเป็นสำหรับผู้ปฏิบัติงาน Proto เนื่องจากเป็นค่าเริ่มต้น- คุณยังตั้งค่า - worker-key-mnemonicในข้อกำหนดการดำเนินการได้ด้วย ซึ่งอาจมีประโยชน์หากคุณนำไฟล์ที่เรียกใช้งานได้กลับมาใช้ซ้ำสำหรับประเภทการดำเนินการหลายประเภท และต้องการแยกความแตกต่างของการดำเนินการตาม Worker นี้
- ควรบันทึกไฟล์ชั่วคราวที่สร้างขึ้นระหว่างการดำเนินการไว้ในไดเรกทอรีของ Worker ซึ่งจะช่วยให้ใช้แซนด์บ็อกซ์ได้ 
สมมติว่ามีการกำหนดกฎที่มีแอตทริบิวต์ "worker" ตามที่อธิบายไว้ข้างต้น นอกเหนือจากแอตทริบิวต์ "srcs" ที่แสดงถึงอินพุต แอตทริบิวต์ "output" ที่แสดงถึงเอาต์พุต และแอตทริบิวต์ "args" ที่แสดงถึงอาร์กิวเมนต์การเริ่มต้นของ Worker การเรียกใช้ 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"]
 )
ดูอีกตัวอย่างได้ที่ การใช้งาน Worker แบบถาวร
ตัวอย่าง
โค้ดเบสของ Bazel ใช้ Java compiler workers นอกเหนือจาก example JSON worker ที่ใช้ในการทดสอบการผสานรวม
คุณสามารถใช้โครงสร้างพื้นฐาน เพื่อเปลี่ยนเครื่องมือที่ใช้ Java ให้เป็น Worker ได้โดยส่งการเรียกกลับที่ถูกต้อง
ดูตัวอย่างกฎที่ใช้ Worker ได้ที่การทดสอบการผสานรวม Worker ของ Bazel
ผู้ร่วมให้ข้อมูลภายนอกได้ติดตั้งใช้งาน Worker ในภาษาต่างๆ โปรดดูการติดตั้งใช้งาน Worker แบบถาวรของ Bazel ในหลายภาษา คุณดูตัวอย่างอื่นๆ อีกมากมายได้ใน GitHub