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