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 caching lintas tindakan, Anda mungkin perlu mengimplementasikan 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:
- Fungsi ini membaca
WorkRequests
dari
stdin
-nya. - Composable ini menulis
WorkResponses
(dan hanya
WorkResponse
) kestdout
-nya. - Properti ini menerima flag
--persistent_worker
. Wrapper harus mengenali tanda command line--persistent_worker
dan hanya akan persisten jika tanda tersebut diteruskan, jika tidak, wrapper harus melakukan kompilasi satu kali dan keluar.
Jika program Anda memenuhi persyaratan ini, program dapat digunakan sebagai pekerja persisten.
Permintaan pekerjaan
WorkRequest
berisi daftar argumen ke pekerja, daftar
pasangan jalur digest yang mewakili input yang dapat diakses pekerja (ini tidak
diterapkan, tetapi Anda dapat menggunakan info ini untuk penyimpanan dalam cache), dan ID permintaan, yaitu 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
pada contoh JSON, tetapi ketika membahas kolom, {i>snake case<i} terlepas dari
protokol yang diberikan.
{
"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. Nilai yang lebih tinggi
menunjukkan output yang lebih panjang. Meneruskan tanda --worker_verbose
ke Bazel akan menetapkan kolom verbosity
ke 10, tetapi nilai yang lebih kecil atau lebih besar dapat digunakan secara manual untuk jumlah output 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 pesan output yang menjelaskan error yang ditemukan saat memproses atau menjalankan permintaan. Pekerja harus menangkap stdout
dan stderr
alat apa pun
yang dipanggilnya dan melaporkannya melalui WorkResponse
. Menulisnya ke stdout
proses pekerja tidak aman, karena akan mengganggu protokol pekerja.
Menulisnya ke stderr
proses pekerja memang aman, tetapi hasilnya
dikumpulkan dalam file log per pekerja, bukan dikaitkan ke tindakan individual.
{
"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 memerlukan
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
0 menunjukkan permintaan "singleplex", yang 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
yang lebih besar dari nol. Permintaan singleplex dikirim secara serial, misalnya jika server tidak mengirim permintaan lain hingga menerima
respons (kecuali untuk permintaan pembatalan, lihat di bawah).
Notes
- Setiap buffering protokol didahului dengan panjangnya dalam format
varint
(lihatMessageLite.writeDelimitedTo()
. - Permintaan dan respons JSON tidak didahului oleh indikator ukuran.
- Permintaan JSON mempertahankan struktur yang sama dengan protobuf, tetapi menggunakan JSON standar dan menggunakan camel case untuk semua nama kolom.
- Untuk mempertahankan properti kompatibilitas mundur dan maju yang sama dengan 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 menjadi JSON menggunakan format JSON protobuf
Pembatalan
Pekerja dapat secara opsional mengizinkan permintaan pekerjaan dibatalkan sebelum selesai.
Hal ini sangat berguna dalam kaitannya dengan eksekusi dinamis, di mana eksekusi
lokal dapat secara rutin diganggu 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
respons pembatalan adalah WorkResponse
dengan
kolom was_cancelled
yang ditetapkan). Satu-satunya kolom lain yang harus ada dalam permintaan pembatalan atau respons
pembatalan 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 mengirim permintaan pembatalan
untuk permintaan yang telah direspons oleh pekerja, dalam hal ini permintaan
pembatalan harus diabaikan.
Setiap pesan WorkRequest
yang tidak dibatalkan harus dijawab hanya satu kali, terlepas dari apakah pesan tersebut dibatalkan atau tidak. Setelah server mengirim permintaan pembatalan, pekerja dapat
merespons menggunakan WorkResponse
dengan request_id
yang ditetapkan dan kolom was_cancelled
ditetapkan ke true. Mengirim WorkResponse
reguler juga diterima, tetapi
kolom output
dan exit_code
akan diabaikan.
Setelah respons dikirim untuk WorkRequest
, pekerja tidak boleh menyentuh
file dalam direktori kerjanya. Server bebas 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 lain.
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 merujuk ke pekerja itu sendiri, sehingga Anda harus membuat instance aturan \*\_binary
untuk menentukan
pekerja Anda. Jika pekerja Anda disebut MyWorker.Java
, ini mungkin merupakan aturan yang terkait:
java_binary(
name = "worker",
srcs = ["MyWorker.Java"],
)
Perintah ini akan membuat label "worker", yang mengacu ke biner pekerja. Kemudian, Anda akan menentukan aturan yang menggunakan pekerja. Aturan ini harus menentukan atribut yang merujuk ke biner pekerja.
Jika biner pekerja yang Anda bangun berada dalam paket bernama "work", yang berada di tingkat teratas build, hal ini mungkin adalah definisi atribut:
"worker": attr.label(
default = Label("//work:worker"),
executable = True,
cfg = "exec",
)
cfg = "exec"
menunjukkan bahwa worker harus dibangun untuk berjalan di
platform eksekusi, bukan di platform target (yaitu, worker 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". Tindakan ini memerlukan daftar string, semuanya kecuali yang terakhir adalah argumen yang diteruskan ke pekerja saat startup. Elemen terakhir dalam daftar "argumen" 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 flag ini.Kolom "execution-requirements", yang mengambil kamus yang berisi
"supports-workers" : "1"
,"supports-multiplex-workers" : "1"
, atau keduanya.Kolom "argumen" dan "execution-requirements" 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 setelan 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 dihasilkan dalam tindakan tindakan harus disimpan ke direktori pekerja. Tindakan ini akan mengaktifkan sandbox.
Dengan asumsi definisi aturan dengan atribut "pekerja" 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 lainnya, lihat Mengimplementasikan pekerja persisten.
Contoh
Code base Bazel menggunakan pekerja compiler Java, selain contoh pekerja JSON yang digunakan dalam pengujian integrasi kami.
Anda dapat menggunakan scaffolding untuk membuat alat berbasis Java apa pun ke worker dengan meneruskan callback yang benar.
Untuk contoh aturan yang menggunakan pekerja, lihat pengujian integrasi pekerja Bazel.
Kontributor eksternal telah menerapkan pekerja dalam berbagai bahasa; lihat implementasi Polyglot dari pekerja persisten Bazel. Anda dapat menemukan berbagai contoh lainnya di GitHub.