Pekerja persisten dapat mempercepat build Anda. Jika Anda memiliki tindakan berulang dalam build yang memiliki biaya startup tinggi atau akan diuntungkan dari caching lintas-tindakan, sebaiknya Anda menerapkan pekerja persisten sendiri untuk melakukan tindakan ini.
Server Bazel berkomunikasi dengan pekerja menggunakan stdin
/stdout
. Server
mendukung penggunaan buffering protokol atau string JSON.
Implementasi pekerja memiliki dua bagian:
Membuat pekerja
Pekerja persisten menegakkan beberapa persyaratan:
- Kode ini membaca
WorkRequests
dari
stdin
-nya. - Menulis
WorkResponses
(dan hanya
WorkResponse
) kestdout
. - Metode ini menerima flag
--persistent_worker
. Wrapper harus mengenali flag command line--persistent_worker
dan hanya membuat dirinya persisten jika flag tersebut diteruskan, jika tidak, wrapper harus melakukan kompilasi satu kali dan keluar.
Jika program Anda memenuhi persyaratan ini, program tersebut dapat digunakan sebagai pekerja tetap.
Permintaan pekerjaan
WorkRequest
berisi daftar argumen ke pekerja, daftar
pasangan jalur jalur yang mewakili input yang dapat diakses pekerja (ini tidak
diterapkan, tetapi Anda dapat menggunakan info ini untuk caching), 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 dalam contoh JSON, tetapi kasus snake saat berbicara tentang kolom terlepas dari protokol yang digunakan.
{
"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. Semuanya bergantung sepenuhnya pada pekerja dan apa yang bisa dihasilkan. Nilai
yang lebih tinggi menunjukkan output yang lebih panjang. Meneruskan flag --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
string output yang menjelaskan error yang terjadi dalam memproses atau menjalankan
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
alat apa pun 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 standar 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 nilainya bukan nol. Ini adalah
WorkResponse
yang valid.
{
"requestId" : 12,
}
request_id
dari 0 menunjukkan permintaan "singleplex", yang digunakan saat permintaan ini
tidak dapat diproses secara paralel dengan permintaan lain. Server menjamin bahwa
pekerja tertentu menerima permintaan hanya dengan request_id
0 atau hanya
request_id
yang lebih besar dari nol. Permintaan singleplex dikirim dalam serial, misalnya
jika server tidak mengirimkan permintaan lain hingga server tersebut menerima
respons (kecuali untuk permintaan pembatalan, lihat di bawah).
Catatan
- Setiap buffering protokol didahului dengan panjangnya dalam format
varint
(lihatMessageLite.writeDelimitedTo()
. - Respons dan permintaan JSON tidak diawali dengan indikator ukuran.
- Permintaan JSON memiliki 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 seperti protobuf, pekerja JSON harus menoleransi kolom yang tidak diketahui dalam pesan ini dan menggunakan nilai default protobuf untuk nilai yang tidak ada.
- Bazel menyimpan permintaan sebagai protobuf dan mengonversinya menjadi JSON menggunakan format JSON protobuf
Peredam Bising
Pekerja dapat secara opsional mengizinkan permintaan pekerjaan dibatalkan sebelum selesai.
Hal ini sangat berguna sehubungan dengan eksekusi dinamis, karena eksekusi
lokal dapat terganggu oleh eksekusi jarak jauh yang lebih cepat. Untuk mengizinkan
pembatalan, tambahkan supports-worker-cancellation: 1
ke
kolom execution-requirements
(lihat di bawah) dan tetapkan
flag --experimental_worker_cancellation
.
Permintaan pembatalan adalah WorkRequest
dengan kolom cancel
yang ditetapkan (dan
sama seperti respons pembatalan adalah WorkResponse
dengan kumpulan kolom was_cancelled
). 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 menjadi 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 ditanggapi oleh pekerja, dalam hal ini permintaan
pembatalan harus diabaikan.
Setiap pesan WorkRequest
yang tidak dibatalkan harus dijawab tepat satu kali, terlepas dari apakah pesan tersebut dibatalkan atau tidak. Setelah server mengirim permintaan pembatalan, pekerja dapat
merespons dengan WorkResponse
yang menetapkan request_id
dan kolom was_cancelled
yang ditetapkan ke true (benar). 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 perlu 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 pekerja
Aturan yang menggunakan pekerja harus berisi kolom yang merujuk ke pekerja tersebut, sehingga Anda harus membuat instance aturan \*\_binary
untuk menentukan
pekerja. Jika pekerja Anda disebut MyWorker.Java
, ini mungkin aturan
terkait:
java_binary(
name = "worker",
srcs = ["MyWorker.Java"],
)
Tindakan ini akan membuat label "pekerja", yang merujuk ke biner pekerja. Anda kemudian akan menentukan aturan yang menggunakan pekerja. Aturan ini harus menentukan atribut yang merujuk ke biner pekerja.
Jika biner pekerja yang Anda build berada dalam paket bernama "work", yang berada di tingkat teratas build, 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 membuat tindakan untuk dilakukan pekerja. Tindakan ini memiliki beberapa persyaratan.
Kolom "arguments". Tindakan ini mengambil daftar string, semuanya kecuali string terakhir yang merupakan argumen yang diteruskan ke pekerja saat memulai. 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 menggunakan kamus berisi
"supports-workers" : "1"
,"supports-multiplex-workers" : "1"
, atau keduanya.Kolom "argumen" dan "Execution-requirements" diperlukan untuk semua tindakan yang dikirim ke pekerja. Selain itu, tindakan yang harus dijalankan oleh pekerja JSON harus menyertakan
"requires-worker-protocol" : "json"
dalam kolom persyaratan eksekusi."requires-worker-protocol" : "proto"
juga merupakan persyaratan eksekusi yang valid, meskipun tidak diperlukan untuk pekerja proto, karena mereka adalah 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 yang dilakukan pekerja ini.File sementara yang dihasilkan selama terjadinya tindakan harus disimpan ke 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
dapat berupa:
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
Basis kode Bazel menggunakan pekerja compiler Java, selain contoh pekerja JSON yang digunakan dalam pengujian integrasi kami.
Anda dapat menggunakan scaffolding mereka untuk membuat alat berbasis Java menjadi pekerja dengan meneruskan callback yang benar.
Untuk melihat contoh aturan yang menggunakan pekerja, lihat pengujian integrasi pekerja Bazel.
Kontributor eksternal telah mengimplementasikan pekerja dalam berbagai bahasa; lihat implementasi Polyglot untuk pekerja persisten Bazel. Anda dapat menemukan banyak contoh lainnya di GitHub.