Membuat Pekerja Persisten

Laporkan masalah Lihat sumber Nightly · 7.4 . 7,3 · 7,2 · 7,1 · 7,0 · 6,5

Pekerja persisten dapat membuat build Anda lebih cepat. Jika Anda memiliki tindakan berulang dalam build yang memiliki biaya startup tinggi atau akan mendapatkan manfaat dari penyimpanan dalam cache lintas tindakan, sebaiknya terapkan pekerja persisten Anda sendiri untuk melakukan tindakan ini.

Server Bazel berkomunikasi dengan pekerja menggunakan stdin/stdout. Server ini mendukung penggunaan buffering protokol atau string JSON.

Implementasi pekerja memiliki dua bagian:

Menjadikan pekerja

Pekerja persisten memenuhi beberapa persyaratan:

  • Class ini membaca WorkRequests dari stdin-nya.
  • {i>Spreadsheet<i} menulis WorkResponses (dan hanya WorkResponse) ke stdout.
  • Properti ini menerima flag --persistent_worker. Wrapper harus mengenali tanda command line --persistent_worker dan hanya membuatnya persisten jika tanda tersebut diteruskan, jika tidak, wrapper harus melakukan kompilasi satu kali dan keluar.

Jika program Anda memenuhi persyaratan ini, program tersebut dapat digunakan sebagai pekerja yang persisten.

Permintaan pekerjaan

WorkRequest berisi daftar argumen ke pekerja, daftar pasangan ringkasan jalur yang mewakili input yang dapat diakses pekerja (ini tidak diberlakukan, tetapi Anda dapat menggunakan info ini untuk menyimpan dalam cache), dan ID permintaan, yang merupakan 0 untuk pekerja singleplex.

CATATAN: Meskipun spesifikasi buffering protokol menggunakan "snake case" (request_id), protokol JSON menggunakan "camel case" (requestId). Dokumen ini menggunakan camel case dalam contoh JSON, tetapi {i>snake case<i} ketika berbicara tentang bidang terlepas dari dan berperforma tinggi karena merupakan protokol biner.

{
  "arguments" : ["--some_argument"],
  "inputs" : [
    { "path": "/path/to/my/file/1", "digest": "fdk3e2ml23d"},
    { "path": "/path/to/my/file/2", "digest": "1fwqd4qdd" }
 ],
  "requestId" : 12
}

Kolom verbosity opsional dapat digunakan untuk meminta output proses debug tambahan dari pekerja. Terserah pekerja apa dan bagaimana output-nya. Lebih tinggi menunjukkan {i>output<i} yang lebih panjang. Meneruskan flag --worker_verbose ke Bazel menyetel kolom verbosity ke 10, tetapi nilai yang lebih kecil atau lebih besar dapat digunakan secara manual untuk jumlah {i>output<i} yang berbeda.

Kolom sandbox_dir opsional hanya digunakan oleh pekerja yang mendukung sandbox multipleks.

Respons kerja

WorkResponse berisi ID permintaan, kode keluar nol atau bukan nol, dan string output yang menjelaskan error yang ditemukan dalam pemrosesan atau eksekusi terhadap permintaan. Kolom output berisi deskripsi singkat; log lengkap dapat ditulis ke stderr pekerja. Karena pekerja hanya dapat menulis WorkResponses ke stdout, biasanya pekerja mengalihkan stdout dari semua alat yang digunakan untuk stderr.

{
  "exitCode" : 1,
  "output" : "Action failed with the following message:\nCould not find input
    file \"/path/to/my/file/1\"",
  "requestId" : 12
}

Sesuai dengan norma untuk protobuf, semua kolom bersifat opsional. Namun, Bazel mewajibkan WorkRequest dan WorkResponse yang sesuai, untuk memiliki ID permintaan yang sama, sehingga ID permintaan harus ditentukan jika bukan nol. Ini adalah WorkResponse yang valid.

{
  "requestId" : 12,
}

request_id dari 0 menunjukkan "singleplex" , digunakan saat permintaan ini tidak dapat diproses secara paralel dengan permintaan lain. Server menjamin bahwa pekerja tertentu menerima permintaan dengan hanya request_id 0 atau hanya request_id lebih besar dari nol. Permintaan {i>singleplex<i} dikirim dalam bentuk serial, jika server tidak mengirimkan permintaan lain sebelum menerima sebuah (kecuali untuk permintaan pembatalan, lihat di bawah).

Catatan

  • Setiap buffering protokol didahului oleh panjangnya dalam format varint (lihat MessageLite.writeDelimitedTo().
  • Permintaan dan respons JSON tidak didahului dengan indikator ukuran.
  • Permintaan JSON mempertahankan struktur yang sama dengan protobuf, tetapi menggunakan JSON dan gunakan camel case untuk semua nama kolom.
  • Untuk mempertahankan properti kompatibilitas mundur dan maju yang sama sebagai protobuf, pekerja JSON harus menoleransi kolom yang tidak diketahui dalam pesan ini, dan menggunakan default protobuf untuk nilai yang tidak ada.
  • Bazel menyimpan permintaan sebagai protobuf dan mengonversinya ke JSON menggunakan format JSON protobuf

Pembatalan

Pekerja dapat secara opsional mengizinkan permintaan pekerjaan dibatalkan sebelum selesai. Ini sangat berguna dalam kaitannya dengan eksekusi dinamis, di mana eksekusi dapat terganggu secara berkala oleh eksekusi jarak jauh yang lebih cepat. Untuk mengizinkan pembatalan, tambahkan supports-worker-cancellation: 1 ke kolom execution-requirements (lihat di bawah) dan tetapkan tanda --experimental_worker_cancellation.

Permintaan pembatalan adalah WorkRequest dengan kolom cancel yang ditetapkan (dan sama seperti respons pembatalan adalah WorkResponse dengan was_cancelled kumpulan kolom). Satu-satunya kolom lainnya yang harus ada dalam permintaan pembatalan atau batal responsnya adalah request_id, yang menunjukkan permintaan mana yang akan dibatalkan. Kolom request_id akan bernilai 0 untuk pekerja singleplex atau request_id non-0 dari WorkRequest yang dikirim sebelumnya untuk pekerja multipleks. Server dapat mengirimkan permintaan pembatalan untuk permintaan yang telah direspons oleh pekerja, dalam hal ini permintaan harus diabaikan.

Setiap pesan WorkRequest yang tidak dibatalkan harus dijawab hanya satu kali, baik bukan dibatalkan. Setelah server mengirim permintaan pembatalan, pekerja dapat merespons dengan WorkResponse dengan request_id yang ditetapkan dan kolom was_cancelled ditetapkan ke benar (true). Mengirim WorkResponse reguler juga diterima, tetapi Kolom output dan exit_code akan diabaikan.

Setelah respons dikirim untuk WorkRequest, pekerja tidak boleh menyentuh file di direktori kerjanya. Server bebas untuk membersihkan file, termasuk file sementara.

Membuat aturan yang menggunakan pekerja

Anda juga harus membuat aturan yang menghasilkan tindakan yang akan dilakukan oleh pekerja. Membuat aturan Starlark yang menggunakan pekerja sama seperti membuat aturan lainnya.

Selain itu, aturan harus berisi referensi ke pekerja itu sendiri, dan ada beberapa persyaratan untuk tindakan yang dihasilkannya.

Merujuk ke pekerja

Aturan yang menggunakan pekerja harus berisi kolom yang mengacu pada pekerja sendiri, jadi Anda harus membuat instance aturan \*\_binary untuk menentukan pekerja Anda. Jika pekerja Anda bernama MyWorker.Java, ini mungkin adalah aturan terkait:

java_binary(
    name = "worker",
    srcs = ["MyWorker.Java"],
)

Tindakan ini akan membuat label "pekerja", yang merujuk ke biner pekerja. Kemudian, Anda akan menentukan aturan yang menggunakan pekerja. Aturan ini harus menentukan atribut yang mengacu pada biner pekerja.

Jika biner pekerja yang Anda bangun berada dalam paket bernama "work", yang ada di bagian atas build, hal ini mungkin berupa definisi atribut:

"worker": attr.label(
    default = Label("//work:worker"),
    executable = True,
    cfg = "exec",
)

cfg = "exec" menunjukkan bahwa pekerja harus di-build untuk berjalan di platform eksekusi, bukan di platform target (yaitu, pekerja digunakan sebagai alat selama build).

Persyaratan tindakan kerja

Aturan yang menggunakan pekerja akan membuat tindakan untuk dilakukan pekerja tersebut. Tindakan ini memiliki beberapa persyaratan.

  • Kolom "arguments". Ini membutuhkan daftar {i>string<i}, yang semuanya kecuali yang terakhir yang merupakan argumen yang diteruskan ke pekerja saat startup. Elemen terakhir di "argumen" daftar adalah argumen flag-file (@-preceded). Pekerja membaca argumen dari flagfile yang ditentukan berdasarkan per-WorkRequest. Aturan Anda dapat menulis argumen non-startup untuk pekerja ke file tanda ini.

  • Kolom "execution-requirements", yang menggunakan kamus yang berisi "supports-workers" : "1", "supports-multiplex-workers" : "1", atau keduanya.

    "Argumen" dan "{i>execution-requirements<i}" kolom wajib diisi untuk semua tindakan yang dikirim ke pekerja. Selain itu, tindakan yang harus dijalankan oleh pekerja JSON harus menyertakan "requires-worker-protocol" : "json" di kolom persyaratan eksekusi. "requires-worker-protocol" : "proto" juga merupakan persyaratan eksekusi yang valid, meskipun tidak diperlukan untuk pekerja proto, karena merupakan default.

    Anda juga dapat menetapkan worker-key-mnemonic dalam persyaratan eksekusi. Hal ini mungkin berguna jika Anda menggunakan kembali file yang dapat dieksekusi untuk beberapa jenis tindakan dan ingin membedakan tindakan oleh pekerja ini.

  • File sementara yang dibuat selama proses tindakan harus disimpan ke pada direktori pekerja. Tindakan ini akan mengaktifkan sandbox.

Dengan asumsi definisi aturan dengan atribut "worker" yang dijelaskan di atas, selain atribut "srcs" yang mewakili input, atribut "output" yang mewakili output, dan atribut "args" yang mewakili argumen startup pekerja, panggilan ke ctx.actions.run mungkin:

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"]
 )

Untuk contoh lain, lihat Mengimplementasikan pekerja persisten.

Contoh

Basis kode Bazel menggunakan pekerja compiler Java, selain contoh pekerja JSON yang digunakan dalam pengujian integrasi kami.

Anda dapat menggunakan perancah untuk membuat alat berbasis Java apa pun ke pekerja dengan meneruskan callback yang benar.

Untuk contoh aturan yang menggunakan pekerja, perhatikan aturan Bazel pengujian integrasi pekerja.

Kontributor eksternal telah menerapkan pekerja dalam berbagai bahasa; ambil lihat Implementasi poliglot pekerja persisten Bazel. Anda dapat temukan lebih banyak contoh di GitHub.