การสร้างผู้ปฏิบัติงานถาวร

วันที่ รายงานปัญหา ดูแหล่งที่มา ตอนกลางคืน · 7.3 · 7.2 · 7.1 · 7.0 · 6.5

ผู้ปฏิบัติงานอย่างต่อเนื่องจะช่วยให้บิลด์ของคุณทำงานได้เร็วขึ้น ถ้า คุณมีการดำเนินการซ้ำๆ ในบิลด์ที่มีต้นทุนในการเริ่มต้นใช้งานสูง หรือ ประโยชน์จากการแคชข้ามการกระทำ คุณอาจต้องการใช้ ผู้ปฏิบัติงานเพื่อดำเนินการเหล่านี้

เซิร์ฟเวอร์ Bazel สื่อสารกับพนักงานโดยใช้ stdin/stdout ทั้งนี้ รองรับการใช้บัฟเฟอร์โปรโตคอลหรือสตริง JSON

การใช้งานผู้ปฏิบัติงานมี 2 ส่วนดังนี้

การทำให้พนักงาน

ผู้ปฏิบัติงานถาวรจะต้องปฏิบัติตามข้อกำหนดบางประการดังต่อไปนี้

  • อ่านว่า WorkRequests จากstdin
  • เขียนว่า WorkResponses (และเพียง WorkResponse วินาที) ไปยัง stdout
  • ยอมรับแฟล็ก--persistent_worker Wrapper ต้องจดจำ แฟล็กบรรทัดคำสั่ง --persistent_worker และทำให้ตนเองอยู่ถาวรได้ก็ต่อเมื่อ แฟล็กนั้นจะถูกส่งผ่าน หรือมิฉะนั้นก็จะต้องทำการคอมไพล์และการออกภาพเดียว

หากโปรแกรมของคุณปฏิบัติตามข้อกำหนดเหล่านี้ ก็สามารถใช้เป็นแบบถาวร ผู้ปฏิบัติงาน!

คำขอทำงาน

WorkRequest มีรายการอาร์กิวเมนต์สำหรับผู้ปฏิบัติงาน ซึ่งเป็นรายการของ คู่ของไดเจสต์เส้นทางซึ่งแสดงอินพุตที่ผู้ปฏิบัติงานเข้าถึงได้ (ซึ่งไม่ใช่ บังคับใช้ แต่คุณสามารถใช้ข้อมูลนี้ในการแคช) และรหัสคำขอ ซึ่งก็คือ 0 สำหรับผู้ปฏิบัติงาน Singleplex

หมายเหตุ: แม้ว่าข้อกำหนดบัฟเฟอร์โปรโตคอลจะใช้ "กรณีงู" (request_id), โปรโตคอล JSON ใช้ "รูปแบบอูฐ" (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 (ไม่บังคับ) สามารถใช้เพื่อขอเอาต์พุตการแก้ไขข้อบกพร่องเพิ่มเติม จากผู้ปฏิบัติงาน โดยขึ้นอยู่กับผู้ปฏิบัติงานว่าจะนำเสนออะไรและอย่างไร สูงขึ้น จะบ่งบอกถึงเอาต์พุตที่มีรายละเอียดมากขึ้น ส่ง Flag --worker_verbose ไปยัง Bazel ตั้งค่าช่อง verbosity เป็น 10 แต่จะใช้ค่าที่น้อยกว่าหรือใหญ่กว่าก็ได้ ด้วยตนเองสำหรับจำนวนเอาต์พุตที่ต่างกัน

ช่อง sandbox_dir ที่ไม่บังคับใช้สำหรับผู้ปฏิบัติงานที่ให้การสนับสนุนเท่านั้น แซนด์บ็อกซ์ Multiplex

การตอบกลับงาน

WorkResponse ประกอบด้วยรหัสคำขอ โค้ดสำหรับออก 0 หรือที่ไม่ใช่ 0 และ สตริงเอาต์พุตที่อธิบายข้อผิดพลาดที่พบในการประมวลผลหรือดำเนินการ คำขอ ช่อง 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
}

ช่องทั้งหมดเป็นตัวเลือกที่ไม่บังคับตามบรรทัดฐานของ Protobuf อย่างไรก็ตาม Bazel WorkRequest และ WorkResponse ที่เกี่ยวข้องเพื่อให้มีคำขอเดียวกัน รหัส ดังนั้นต้องระบุรหัสคำขอหากไม่เป็นศูนย์ อีเมลนี้ถูกต้อง WorkResponse

{
  "requestId" : 12,
}

request_id จาก 0 หมายถึง "singleplex" คำขอที่ใช้เมื่อคำขอนี้ ไม่สามารถประมวลผลพร้อมกันได้กับคำขออื่นๆ เซิร์ฟเวอร์จะรับประกันว่า ผู้ปฏิบัติงานหนึ่งๆ ได้รับคำขอที่มีเพียง request_id 0 หรือเท่านั้น request_id มากกว่า 0 คำขอ Singleplex จะส่งแบบอนุกรมสำหรับ ตัวอย่างเช่น ถ้าเซิร์ฟเวอร์ไม่ส่งคำขออีกจนกว่าจะได้รับ การตอบกลับ (ยกเว้นคำขอยกเลิก โปรดดูด้านล่าง)

หมายเหตุ

  • บัฟเฟอร์โปรโตคอลแต่ละแบบจะมีความยาวในรูปแบบ varint นำหน้า (ดู MessageLite.writeDelimitedTo()
  • คำขอและการตอบสนอง JSON ไม่ได้นำหน้าด้วยตัวระบุขนาด
  • คำขอ JSON รักษาโครงสร้างเดียวกันกับ Protobuf แต่ใช้มาตรฐาน JSON และใช้ตัวอักษรประเภทอูฐสำหรับชื่อช่องทั้งหมด
  • เพื่อรักษาคุณสมบัติความเข้ากันได้แบบย้อนหลังและไปข้างหน้าที่เหมือนกัน เป็น Protobuf, ผู้ปฏิบัติงาน JSON ต้องยอมรับฟิลด์ที่ไม่รู้จักในข้อความเหล่านี้ และใช้ค่าเริ่มต้นของ Protobuf สำหรับค่าที่ขาดหายไป
  • Bazel จัดเก็บคำขอเป็น Protocolbufs และแปลงเป็น 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 สำหรับผู้ปฏิบัติงานมัลติเพล็กซ์ เซิร์ฟเวอร์อาจส่งคำขอยกเลิก สำหรับคำขอที่ผู้ปฏิบัติงานตอบกลับแล้ว ซึ่งในกรณีนี้คือการยกเลิก จะต้องละเว้นคำขอ

ต้องตอบ WorkRequest ข้อความที่ไม่ยกเลิกแต่ละข้อความให้ครบ 1 ครั้งเท่านั้น ไม่ว่าจะเป็น ไม่ใช่ว่าถูกยกเลิก เมื่อเซิร์ฟเวอร์ส่งคำขอยกเลิกแล้ว ผู้ปฏิบัติงานอาจ ตอบกลับด้วย 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 ในข้อกำหนดการดำเนินการได้ด้วย ช่วงเวลานี้ อาจมีประโยชน์หากคุณใช้ไฟล์ปฏิบัติการซ้ำสำหรับการดำเนินการหลายประเภท ต้องการจำแนกการทำงานของผู้ปฏิบัติงานรายนี้

  • ไฟล์ชั่วคราวที่สร้างขึ้นในระหว่างดำเนินการควรบันทึกไว้ใน ไดเรกทอรีของผู้ปฏิบัติงาน การดำเนินการนี้จะเปิดใช้แซนด์บ็อกซ์

สมมติคำจำกัดความของกฎด้วยคำว่า "ผู้ปฏิบัติงาน" ที่อธิบายไว้ข้างต้น นอกจากนี้ ไปยัง "srcs" ที่แสดงถึงอินพุต ซึ่งเป็น "เอาต์พุต" แอตทริบิวต์ จะแสดงเอาต์พุตและ "อาร์กิวเมนต์" แอตทริบิวต์ที่แสดงถึงผู้ปฏิบัติงาน อาร์กิวเมนต์เริ่มต้น การเรียกไปยัง 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 ที่ถูกต้อง

ในตัวอย่างของกฎที่ใช้ผู้ปฏิบัติงาน ให้ดู การทดสอบการผสานรวมผู้ปฏิบัติงาน

ผู้ร่วมให้ข้อมูลภายนอกได้ติดตั้งใช้งานผู้ปฏิบัติงานด้วยภาษาที่หลากหลาย ถ่าย ดูที่ การใช้ Polyglot ของผู้ปฏิบัติงานต่อเนื่องของ Bazel คุณสามารถ ดูตัวอย่างอีกมากมายใน GitHub