ผู้ปฏิบัติงานแบบถาวรช่วยให้บิลด์เร็วขึ้น หากคุณมีการดำเนินการซ้ำๆ ในบิลด์ซึ่งมีต้นทุนในการเริ่มต้นใช้งานสูงหรือจะได้รับประโยชน์จากการแคชข้ามการดำเนินการ คุณอาจต้องให้ผู้ปฏิบัติงานถาวรของคุณเองเป็นผู้ดำเนินการเหล่านี้
เซิร์ฟเวอร์ Bazel จะสื่อสารกับเวิร์กเกอร์โดยใช้ stdin
/stdout
โดยรองรับการใช้บัฟเฟอร์โปรโตคอลหรือสตริง JSON
การใช้งานผู้ปฏิบัติงานมี 2 ส่วนดังนี้
การสร้างผู้ปฏิบัติงาน
ผู้ปฏิบัติงานแบบถาวรต้องปฏิบัติตามข้อกำหนดบางประการ ดังนี้
- โดยจะอ่าน WorkRequests จาก
stdin
- โดยจะเขียน WorkResponses (และเฉพาะ
WorkResponse
) ลงในstdout
- ยอมรับ Flag
--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
(ไม่บังคับ) เพื่อขอเอาต์พุตการแก้ไขข้อบกพร่องเพิ่มเติมจากเวิร์กเกอร์ ขึ้นอยู่กับว่าผู้ปฏิบัติงานจะแสดงผลอะไรและอย่างไร ค่าที่สูงขึ้นบ่งบอกถึงเอาต์พุตที่ละเอียดมากขึ้น การส่ง Flag --worker_verbose
ไปยัง Bazel จะตั้งค่าช่อง verbosity
เป็น 10 แต่คุณใช้ค่าที่เล็กกว่าหรือมากกว่าได้ด้วยตัวเองสำหรับเอาต์พุตจำนวนต่างๆ
ช่อง 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 บ่งบอกถึงคำขอ "แบบเดี่ยว" ซึ่งจะใช้เมื่อประมวลผลคำขอนี้ควบคู่ไปกับคำขออื่นๆ ไม่ได้ เซิร์ฟเวอร์รับประกันว่าผู้ปฏิบัติงานหนึ่งๆ จะได้รับคำขอที่มี request_id
เท่ากับ 0 เท่านั้น หรือมี request_id
มากกว่า 0 เท่านั้น ระบบจะส่งคำขอแบบ Singleplex แบบอนุกรม เช่น หากเซิร์ฟเวอร์ไม่ส่งคำขออื่นจนกว่าจะได้รับการตอบกลับ (ยกเว้นคำขอยกเลิก ดูด้านล่าง)
หมายเหตุ
- บัฟเฟอร์โปรโตคอลแต่ละรายการจะมีความยาวนำหน้าในรูปแบบ
varint
(ดูMessageLite.writeDelimitedTo()
- คำขอและการตอบสนอง JSON ไม่ได้นำหน้าด้วยตัวระบุขนาด
- คำขอ JSON จะใช้โครงสร้างเดียวกับ protobuf แต่จะใช้ JSON มาตรฐานและใช้รูปแบบตัวพิมพ์ใหญ่ขึ้นต้นสำหรับชื่อช่องทั้งหมด
- โปรแกรมประมวลผล JSON ต้องยอมรับช่องที่ไม่รู้จักในข้อความเหล่านี้และใช้ค่าเริ่มต้นของ protobuf สำหรับค่าที่ขาดหายไป เพื่อรักษาพร็อพเพอร์ตี้ความเข้ากันได้ย้อนหลังและไปข้างหน้าแบบเดียวกับ protobuf
- Bazel จะจัดเก็บคำขอเป็น protobuf และแปลงเป็น JSON โดยใช้รูปแบบ JSON ของ protobuf
การยกเลิก
ผู้ปฏิบัติงานสามารถเลือกที่จะอนุญาตให้ยกเลิกคำของานก่อนทำเสร็จได้
ซึ่งมีประโยชน์อย่างยิ่งเมื่อเกี่ยวข้องกับการดำเนินการแบบไดนามิกที่การดําเนินการในเครื่องอาจถูกขัดจังหวะโดยการดำเนินการระยะไกลที่เร็วกว่าเป็นประจำ หากต้องการอนุญาตการยกเลิก ให้เพิ่ม supports-worker-cancellation: 1
ลงในช่อง execution-requirements
(ดูด้านล่าง) แล้วตั้งค่า Flag --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"],
)
ซึ่งจะสร้างป้ายกำกับ "worker" ที่หมายถึงไบนารีของผู้ปฏิบัติงาน จากนั้นคุณจะกำหนดกฎที่ใช้ผู้ปฏิบัติงาน กฎนี้ควรกำหนดแอตทริบิวต์ซึ่งอ้างอิงถึงไบนารีของเวิร์กเกอร์
หากไบนารีของเวิร์กเกอร์ที่คุณสร้างอยู่ในแพ็กเกจชื่อ "work" ซึ่งอยู่ในระดับบนสุดของบิลด์ คำจำกัดความของแอตทริบิวต์อาจเป็นดังนี้
"worker": attr.label(
default = Label("//work:worker"),
executable = True,
cfg = "exec",
)
cfg = "exec"
บ่งบอกว่าควรสร้างเวิร์กเกอร์ให้ทำงานบนแพลตฟอร์มการดำเนินการของคุณแทนแพลตฟอร์มเป้าหมาย (กล่าวคือ ใช้เวิร์กเกอร์เป็นเครื่องมือระหว่างการบิลด์)
ข้อกำหนดการดําเนินการของงาน
กฎที่ใช้ผู้ปฏิบัติงานจะสร้างการดำเนินการให้ผู้ปฏิบัติงานดำเนินการ การดําเนินการเหล่านี้มีข้อกําหนด 2 ข้อ
ฟิลด์ "arguments" การดำเนินการนี้จะรับรายการสตริง โดยสตริงทั้งหมดยกเว้นรายการสุดท้ายจะเป็นอาร์กิวเมนต์ที่ส่งไปยังเวิร์กเกอร์เมื่อเริ่มต้น องค์ประกอบสุดท้ายในรายการ "arguments" คืออาร์กิวเมนต์
flag-file
(ตามด้วย @) ผู้ปฏิบัติงานจะอ่านอาร์กิวเมนต์จาก 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 เป็นเวิร์กเกอร์ได้โดยส่งการเรียกกลับที่ถูกต้อง
ดูตัวอย่างกฎที่ใช้ผู้ปฏิบัติงานได้ที่การทดสอบการผสานรวมผู้ปฏิบัติงานของ Bazel
ผู้ร่วมให้ข้อมูลภายนอกได้ติดตั้งใช้งานผู้ปฏิบัติงานโดยใช้ภาษาต่างๆ โปรดดู การใช้ Polyglot ของผู้ปฏิบัติงานถาวรของ Bazel คุณสามารถดูตัวอย่างอื่นๆ อีกมากมายใน GitHub