Pekerja persisten dapat membuat build Anda lebih cepat. Jika Anda memiliki tindakan berulang dalam build yang memiliki biaya startup tinggi atau akan manfaat dari caching lintas tindakan, Anda mungkin ingin menerapkan pekerja untuk melakukan tindakan ini.
Server Bazel berkomunikasi dengan pekerja menggunakan stdin
/stdout
. Ini
mendukung penggunaan buffering protokol atau string JSON.
Implementasi pekerja memiliki dua bagian:
Menjadikan pekerja
Pekerja persisten memenuhi beberapa persyaratan:
- Dapat dibaca
WorkRequests
dari
stdin
-nya. - {i>Spreadsheet<i} menulis
WorkResponses
(dan hanya
WorkResponse
) kestdout
. - Properti ini menerima flag
--persistent_worker
. Wrapper harus mengenali Flag command line--persistent_worker
dan hanya akan persisten jika penanda itu diteruskan, jika tidak, sistem itu harus melakukan kompilasi satu kali dan keluar.
Jika program Anda memenuhi persyaratan ini, program dapat digunakan sebagai pekerja!
Permintaan pekerjaan
WorkRequest
berisi daftar argumen ke pekerja, yaitu daftar
pasangan path-digest yang mewakili input yang dapat diakses pekerja (ini bukan
diberlakukan, 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
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
pesan output yang menjelaskan error apa pun yang ditemukan dalam pemrosesan atau eksekusi
terhadap permintaan. Pekerja harus menangkap stdout
dan stderr
alat apa pun yang
panggilan dan melaporkannya melalui WorkResponse
. Menulisnya ke stdout
dari
proses pekerja tidak aman, karena akan mengganggu protokol worker.
Menulisnya ke stderr
proses pekerja memang aman, tetapi hasilnya adalah
dikumpulkan dalam file log per pekerja, alih-alih ditentukan oleh tindakan individu.
{
"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, agar memiliki permintaan yang sama
{i>id<i}, jadi id permintaan harus ditentukan jika bukan nol. Ini adalah valid
WorkResponse
.
{
"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
(lihatMessageLite.writeDelimitedTo()
. - Permintaan dan respons JSON tidak didahului oleh 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 setel
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. request_id
adalah 0 untuk pekerja singleplex atau request_id
non-0 dari
mengirim WorkRequest
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, worker dapat
merespons dengan WorkResponse
dengan request_id
yang ditetapkan dan was_cancelled
isian 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 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 worker Anda disebut MyWorker.Java
, ini mungkin karena
aturan yang terkait:
java_binary(
name = "worker",
srcs = ["MyWorker.Java"],
)
Ini menciptakan "pekerja" label, yang mengacu pada biner pekerja. Anda kemudian akan tentukan aturan yang menggunakan pekerja. Aturan ini harus mendefinisikan 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 dibangun untuk berjalan pada
platform eksekusi alih-alih di platform target (yaitu, worker digunakan
sebagai alat (tool) selama build).
Persyaratan tindakan kerja
Aturan yang menggunakan pekerja akan membuat tindakan untuk dilakukan pekerja tersebut. 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. Nama aturan dapat menulis argumen non-startup untuk pekerja ke flagfile ini.Kolom "execution-requirements", yang mengambil 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"
dalam persyaratan eksekusi."requires-worker-protocol" : "proto"
juga persyaratan eksekusi yang valid, meskipun tidak diperlukan untuk pekerja proto, karena mereka adalah {i>default-<i}nya.Anda juga dapat menetapkan
worker-key-mnemonic
dalam persyaratan eksekusi. Ini mungkin berguna jika Anda menggunakan kembali {i> executable<i} 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.
Mengasumsikan definisi aturan dengan "worker" yang dijelaskan di atas, selain
menjadi "srcs" yang mewakili input, "output" atribut
yang merepresentasikan output, dan "args" yang mewakili pekerja
argumen startup, 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.
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.