Kalıcı çalışanlar, derlemenizi hızlandırabilir. Derlemenizde yüksek başlangıç maliyeti olan veya işlemler arası önbelleğe almadan yararlanacak tekrarlanan işlemler varsa bu işlemleri gerçekleştirmek için kendi kalıcı çalışanınızı uygulayabilirsiniz.
Bazel sunucusu, stdin
/stdout
kullanarak çalışanla iletişim kurar. Protokol arabelleklerinin veya JSON dizelerinin kullanılmasını destekler.
Çalışan uygulaması iki bölümden oluşur:
İşçiyi yapma
Kalıcı bir çalışan, birkaç koşulu karşılamalıdır:
stdin
konumundaki WorkRequests dosyasını okur.stdout
konumuna WorkResponses (ve yalnızcaWorkResponse
) yazar.--persistent_worker
işaretini kabul eder. Sarmalayıcı,--persistent_worker
komut satırı işaretini tanımalı ve yalnızca bu işaret iletilirse kalıcı olmalıdır. Aksi takdirde tek seferlik derleme yapıp çıkmalıdır.
Programınız bu koşulları karşılıyorsa kalıcı çalışan olarak kullanılabilir.
İş istekleri
WorkRequest
, çalışana iletilecek bağımsız değişkenlerin listesini, çalışanın erişebileceği girişleri temsil eden yol-özet çiftlerinin listesini (bu zorunlu değildir ancak bu bilgileri önbelleğe alma için kullanabilirsiniz) ve tek kanallı çalışanlar için 0 olan bir istek kimliğini içerir.
NOT: Protokol arabelleği spesifikasyonu "snake case" (request_id
) kullanırken JSON protokolü "camel case" (requestId
) kullanır. Bu belgedeki JSON örneklerinde camel case kullanılır ancak protokolden bağımsız olarak alandan bahsederken snake case kullanılır.
{
"arguments" : ["--some_argument"],
"inputs" : [
{ "path": "/path/to/my/file/1", "digest": "fdk3e2ml23d"},
{ "path": "/path/to/my/file/2", "digest": "1fwqd4qdd" }
],
"requestId" : 12
}
İsteğe bağlı verbosity
alanı, çalışandan ek hata ayıklama çıkışı istemek için kullanılabilir. Çalışan, neyi ve nasıl çıktı vereceğine tamamen kendisi karar verir. Değerlerin yüksek olması, daha ayrıntılı bir çıkış olduğunu gösterir. --worker_verbose
işaretini Bazel'e iletmek verbosity
alanını 10 olarak ayarlar ancak farklı miktarlarda çıkış için daha küçük veya daha büyük değerler manuel olarak kullanılabilir.
İsteğe bağlı sandbox_dir
alanı yalnızca çoklu korumalı alan destekleyen çalışanlar tarafından kullanılır.
İşle ilgili yanıtlar
WorkResponse
, istek kimliği, sıfır veya sıfır olmayan bir çıkış kodu ve isteğin işlenmesi ya da yürütülmesi sırasında karşılaşılan hataları açıklayan bir çıkış mesajı içerir. Bir çalışan, çağırdığı tüm araçların stdout
ve stderr
değerlerini yakalamalı ve bunları WorkResponse
aracılığıyla bildirmelidir. İşçi protokolüne müdahale edeceğinden, işçi sürecinin stdout
yazılması güvenli değildir.
Çalışan sürecinin stderr
bölümüne yazmak güvenlidir ancak sonuç, bağımsız işlemlere atfedilmek yerine çalışan başına bir günlük dosyasında toplanır.
{
"exitCode" : 1,
"output" : "Action failed with the following message:\nCould not find input
file \"/path/to/my/file/1\"",
"requestId" : 12
}
protobuf'lar için geçerli olan kurala göre tüm alanlar isteğe bağlıdır. Ancak Bazel, WorkRequest
ve karşılık gelen WorkResponse
değerlerinin aynı istek kimliğine sahip olmasını gerektirir. Bu nedenle, istek kimliği sıfır değilse belirtilmelidir. Bu geçerli bir WorkResponse
.
{
"requestId" : 12,
}
0 request_id
değeri, bu istek diğer isteklerle paralel olarak işlenemediğinde kullanılan "tekli" bir isteği gösterir. Sunucu, belirli bir çalışanın yalnızca request_id
0 veya yalnızca sıfırdan büyük request_id
değerine sahip istekler alacağını garanti eder. Tekli istekler, seri olarak gönderilir. Örneğin, sunucu yanıt alana kadar başka bir istek göndermez (iptal istekleri hariç, aşağıya bakın).
Notlar
- Her protokol arabelleğinden önce
varint
biçiminde uzunluğu gelir (bkz.MessageLite.writeDelimitedTo()
). - JSON istekleri ve yanıtlarının başında boyut göstergesi bulunmaz.
- JSON istekleri, protobuf ile aynı yapıyı korur ancak standart JSON kullanır ve tüm alan adları için camel case kullanılır.
- JSON çalışanlarının, protobuf ile aynı geriye ve ileriye dönük uyumluluk özelliklerini korumak için bu mesajlardaki bilinmeyen alanları tolere etmesi ve eksik değerler için protobuf varsayılanlarını kullanması gerekir.
- Bazel, istekleri protobuf olarak depolar ve protobuf'un JSON biçimini kullanarak JSON'a dönüştürür.
İptal
Çalışanlar, iş isteklerinin tamamlanmadan önce iptal edilmesine isteğe bağlı olarak izin verebilir.
Bu özellik, özellikle yerel yürütmenin daha hızlı bir uzaktan yürütme tarafından düzenli olarak kesilebileceği dinamik yürütme ile bağlantılı olarak kullanışlıdır. İptale izin vermek için supports-worker-cancellation: 1
alanına execution-requirements
ekleyin (aşağıya bakın) ve --experimental_worker_cancellation
işaretini ayarlayın.
İptal isteği, cancel
alanı ayarlanmış bir WorkRequest
'dir (benzer şekilde, iptal yanıtı da was_cancelled
alanı ayarlanmış bir WorkResponse
'dir). Bir iptal isteğinde veya iptal yanıtında bulunması gereken tek alan, hangi isteğin iptal edileceğini belirten request_id
alanıdır. request_id
alanı, tekli çalışanlar için 0, çoklu çalışanlar için ise daha önce gönderilen WorkRequest
'nin 0 olmayan request_id
değeri olur. Sunucu, çalışanın yanıtladığı istekler için iptal istekleri gönderebilir. Bu durumda iptal isteği yoksayılmalıdır.
İptal edilmeyen her WorkRequest
mesaj, iptal edilmiş olsun veya olmasın tam olarak bir kez yanıtlanmalıdır. Sunucu iptal isteği gönderdikten sonra çalışan, WorkResponse
ile yanıt verebilir. Bu yanıtta request_id
ayarlanmış ve was_cancelled
alanı doğru olarak ayarlanmıştır. Normal bir WorkResponse
göndermek de kabul edilir ancak output
ve exit_code
alanları yoksayılır.
WorkRequest
için yanıt gönderildikten sonra çalışan, çalışma dizinindeki dosyalara dokunmamalıdır. Sunucu, geçici dosyalar da dahil olmak üzere dosyaları temizleyebilir.
Çalışanı kullanan kuralı oluşturma
Ayrıca, çalışanın gerçekleştireceği işlemleri oluşturan bir kural da oluşturmanız gerekir. Çalışan kullanan bir Starlark kuralı oluşturmak, diğer kuralları oluşturmaya benzer.
Ayrıca kural, çalışanın kendisine bir referans içermeli ve oluşturduğu işlemlerle ilgili bazı koşullar olmalıdır.
Çalışandan bahsetme
Çalışanı kullanan kural, çalışanın kendisine atıfta bulunan bir alan içermelidir. Bu nedenle, çalışanınızı tanımlamak için \*\_binary
kuralının bir örneğini oluşturmanız gerekir. Çalışanınızın adı MyWorker.Java
ise ilişkili kural şu olabilir:
java_binary(
name = "worker",
srcs = ["MyWorker.Java"],
)
Bu işlem, çalışan ikilisine atıfta bulunan "worker" etiketini oluşturur. Ardından, çalışanı kullanan bir kural tanımlarsınız. Bu kural, çalışan ikilisine atıfta bulunan bir özelliği tanımlamalıdır.
Oluşturduğunuz worker ikilisi, derlemenin en üst düzeyinde bulunan "work" adlı bir paketteyse bu, özellik tanımı olabilir:
"worker": attr.label(
default = Label("//work:worker"),
executable = True,
cfg = "exec",
)
cfg = "exec"
, çalışanın hedef platformda değil, yürütme platformunuzda çalışacak şekilde oluşturulması gerektiğini gösterir (ör. çalışan, derleme sırasında araç olarak kullanılır).
Çalışma eylemi şartları
Çalışanı kullanan kural, çalışanın gerçekleştireceği işlemler oluşturur. Bu işlemlerin birkaç koşulu vardır.
"arguments" alanı. Bu işlev, dizelerden oluşan bir liste alır. Bu listedeki son dize hariç tüm dizeler, başlangıçta çalışana iletilen bağımsız değişkenlerdir. "arguments" listesindeki son öğe,
flag-file
(@ ile başlayan) bağımsız değişkenidir. Çalışanlar, belirtilen flagfile'daki bağımsız değişkenleri WorkRequest başına okur. Kuralınız, bu flagfile için çalışana başlangıç dışı argümanlar yazabilir."supports-workers" : "1"
,"supports-multiplex-workers" : "1"
veya her ikisini içeren bir sözlük alan "execution-requirements" alanı.Çalışanlara gönderilen tüm işlemler için "arguments" (argümanlar) ve "execution-requirements" (yürütme koşulları) alanları gereklidir. Ayrıca, JSON çalışanları tarafından yürütülmesi gereken işlemler, yürütme koşulları alanında
"requires-worker-protocol" : "json"
içermelidir."requires-worker-protocol" : "proto"
, varsayılan olarak ayarlandığı için proto çalışanları için gerekli olmasa da geçerli bir yürütme koşuludur.Yürütme koşullarında
worker-key-mnemonic
da belirleyebilirsiniz. Bu, yürütülebilir dosyayı birden fazla işlem türü için yeniden kullanıyorsanız ve işlemleri bu çalışan tarafından ayırt etmek istiyorsanız yararlı olabilir.İşlem sırasında oluşturulan geçici dosyalar, çalışanın dizinine kaydedilmelidir. Bu, korumalı alan oluşturmayı etkinleştirir.
Yukarıda açıklanan "worker" özelliğine sahip bir kural tanımının yanı sıra girişleri temsil eden bir "srcs" özelliği, çıkışları temsil eden bir "output" özelliği ve worker başlatma bağımsız değişkenlerini temsil eden bir "args" özelliği olduğunu varsayarsak ctx.actions.run
çağrısı şu şekilde olabilir:
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"]
)
Başka bir örnek için Kalıcı çalışanları uygulama başlıklı makaleyi inceleyin.
Örnekler
Bazel kod tabanı, entegrasyon testlerimizde kullanılan bir örnek JSON çalışanı ile birlikte Java derleyici çalışanlarını kullanır.
Doğru geri çağırma işlevini ileterek Java tabanlı tüm araçları worker'a dönüştürmek için bu araçların iskelelerini kullanabilirsiniz.
Çalışan kullanan bir kural örneği için Bazel'in worker integration test (Çalışan entegrasyon testi) bölümüne bakın.
Harici katkıda bulunanlar, çeşitli dillerde çalışanlar uygulamıştır. Bazel kalıcı çalışanlarının çok dilli uygulamalarına göz atın. GitHub'da çok daha fazla örnek bulabilirsiniz.