लगातार काम करने वाले लोग बनाना

किसी समस्या की शिकायत करें स्रोत देखें

स्थायी कर्मचारी आपके बिल्ड को तेज़ बना सकते हैं. अगर आपने अपने बिल्ड में बार-बार होने वाली ऐसी कार्रवाइयों का इस्तेमाल किया है जिनकी स्टार्टअप लागत ज़्यादा है या जिन्हें क्रॉस-ऐक्शन कैश मेमोरी से फ़ायदा मिलता है, तो आप ये कार्रवाइयां करने के लिए खुद का स्थायी वर्कर लागू कर सकते हैं.

Bazel सर्वर, stdin/stdout का इस्तेमाल करके वर्कर से संपर्क करता है. यह प्रोटोकॉल बफ़र या JSON स्ट्रिंग के इस्तेमाल करने के साथ काम करता है.

वर्कर को लागू करने की प्रोसेस के दो चरण होते हैं:

वर्कर बनाया जा रहा है

स्थायी कर्मचारी कुछ ज़रूरी शर्तें पूरी करता है:

  • मैसेज में, stdin से मिले WorkRequests के बारे में बताया गया है.
  • यह अपने stdout पर WorkResponses (और केवल WorkResponses) लिखता है.
  • यह --persistent_worker फ़्लैग को स्वीकार करता है. रैपर को --persistent_worker कमांड-लाइन फ़्लैग की पहचान करनी चाहिए और उसे सिर्फ़ तब ही बनाए रखना चाहिए, जब उस फ़्लैग को पास किया जा रहा हो, नहीं तो उसे एक-शॉट कंपाइल करना होगा और बाहर निकलना होगा.

अगर आपका प्रोग्राम इन ज़रूरतों को पूरा करता है, तो इसका इस्तेमाल स्थायी कर्मचारी के तौर पर किया जा सकता है!

काम से जुड़े अनुरोध

WorkRequest में वर्कर के लिए आर्ग्युमेंट की एक सूची और वर्कर डाइजेस्ट पेयर की एक सूची होती है जो वर्कर के इनपुट ऐक्सेस कर सकता है. इसे लागू नहीं किया जा सकता. साथ ही, इस जानकारी का इस्तेमाल कैश मेमोरी के लिए किया जा सकता है. रिक्वेस्ट आईडी, सिंगलप्लेक्स वर्कर के लिए 0 होती है.

ध्यान दें: हालांकि, प्रोटोकॉल बफ़र की सेटिंग में "स्नेक केस" (request_id) का इस्तेमाल किया जाता है, लेकिन JSON प्रोटोकॉल में "ऊंटों के केस" (requestId) का इस्तेमाल किया जाता है. इस दस्तावेज़ में JSON के उदाहरण में ऊंट के केस का इस्तेमाल किया गया है. हालांकि, प्रोटोकॉल के बावजूद फ़ील्ड के बारे में बात करते समय स्नेक केस का इस्तेमाल किया जाता है.

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

वैकल्पिक verbosity फ़ील्ड का इस्तेमाल वर्कर से ज़्यादा डीबग करने के अनुरोध के लिए किया जा सकता है. यह पूरी तरह से कर्मचारी पर निर्भर करता है कि क्या और कैसे आउटपुट करना है. ज़्यादा मान, ज़्यादा वर्बोस आउटपुट दिखाते हैं. --worker_verbose फ़्लैग को पास करने पर बेज़ल verbosity फ़ील्ड को 10 पर सेट करता है, लेकिन आउटपुट की अलग-अलग मात्रा के लिए मैन्युअल रूप से छोटे या बड़े मानों का इस्तेमाल किया जा सकता है.

वैकल्पिक sandbox_dir फ़ील्ड का इस्तेमाल सिर्फ़ वे कर्मचारी करते हैं जो मल्टीप्लेक्स सैंडबॉक्सिंग की सुविधा देते हैं.

काम के जवाब

WorkResponse में एक अनुरोध आईडी, शून्य या गैर-शून्य एग्ज़िट कोड, और एक आउटपुट स्ट्रिंग शामिल होती है. यह अनुरोध को प्रोसेस करते समय या उसे पूरा करते समय होने वाली गड़बड़ियों के बारे में बताता है. output फ़ील्ड में कम शब्दों में जानकारी दी जाती है. हो सकता है कि पूरे लॉग को वर्कर के stderr में लिखा गया हो. वर्कर सिर्फ़ stdout पर WorkResponses लिख सकते हैं. इसलिए, आम तौर पर वर्कर, stdout में किसी भी टूल का इस्तेमाल करके, stderr पर रीडायरेक्ट करता है.

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

प्रोटोबफ़ के नियम के मुताबिक, सभी फ़ील्ड वैकल्पिक होते हैं. हालांकि, Bazel का WorkRequest और उससे जुड़े WorkResponse का एक ही अनुरोध आईडी होना ज़रूरी है. इसलिए, अगर अनुरोध आईडी शून्य नहीं है, तो तय किया जाना चाहिए. यह मान्य WorkResponse है.

{
  "requestId" : 12,
}

0 में से request_id, "सिंगलप्लेक्स" अनुरोध दिखाता है. इसका इस्तेमाल तब किया जाता है, जब इस अनुरोध को दूसरे अनुरोधों के साथ-साथ प्रोसेस नहीं किया जाता. सर्वर गारंटी देता है कि दिए गए वर्कर को request_id 0 या सिर्फ़ request_id से ज़्यादा वाले अनुरोध मिलते हैं. सिंगलप्लेक्स अनुरोध सीरियल में भेजे जाते हैं, उदाहरण के लिए, अगर सर्वर तब तक कोई और अनुरोध नहीं भेजता, जब तक कि उसे कोई रिस्पॉन्स नहीं मिलता (अनुरोध रद्द करने के अलावा, नीचे देखें).

ज़रूरी जानकारी

  • हर प्रोटोकॉल बफ़र के आगे varint का फ़ॉर्मैट होता है (MessageLite.writeDelimitedTo() देखें).
  • JSON के अनुरोधों और रिस्पॉन्स से पहले, साइज़ इंडिकेटर नहीं होता.
  • JSON के अनुरोधों का स्ट्रक्चर वही होता है जो प्रोटोबफ़ की तरह होता है. हालांकि, स्टैंडर्ड JSON का इस्तेमाल करें और सभी फ़ील्ड के लिए ऊंट का केस इस्तेमाल करें.
  • आगे और पीछे जाने की एक जैसी विशेषताओं को प्रोटोबफ़ के रूप में बनाए रखने के लिए, JSON वर्कर को इन मैसेज में अनजान फ़ील्ड को सहन करना ज़रूरी है. साथ ही, अनुपलब्ध मान के लिए प्रोटोबफ़ डिफ़ॉल्ट का इस्तेमाल करना चाहिए.
  • Bazel अनुरोधों को प्रोटोबफ़ के तौर पर सेव करता है और उन्हें प्रोटोबफ़ के JSON फ़ॉर्मैट का इस्तेमाल करके JSON में बदलता है

रद्द किया जाना

काम से जुड़े अनुरोध खत्म होने से पहले, काम करने वाले लोग इसे रद्द करने की अनुमति दे सकते हैं. यह डाइनैमिक तरीके से एक्ज़ीक्यूशन करने के लिए, खास तौर पर फ़ायदेमंद होता है. जब लोकल एक्ज़ीक्यूशन की वजह से, रिमोट तरीके से प्रोग्राम चलाने की प्रोसेस में नियमित रूप से रुकावट आती है. रद्द करने की अनुमति देने के लिए, supports-worker-cancellation: 1 को execution-requirements फ़ील्ड में जोड़ें (नीचे देखें) और --experimental_worker_cancellation फ़्लैग सेट करें.

रद्द करने का अनुरोध, cancel फ़ील्ड सेट की मदद से किया गया एक WorkRequest होता है. इसी तरह, सदस्यता रद्द करने का अनुरोध, WorkResponse फ़ील्ड सेट के साथ WorkResponse होता है. अनुरोध को रद्द करने या रद्द करने के जवाब के रूप में एक और फ़ील्ड request_id होना चाहिए. इससे पता चलता है कि किस अनुरोध को रद्द करना है. request_idप्लेक्स वर्कर के लिए request_id फ़ील्ड 0 होगा या मल्टीप्लेक्स वर्कर के लिए पहले से भेजे गए WorkRequest का नॉन-0 फ़ील्ड. सर्वर उन अनुरोधों के लिए रद्द करने के अनुरोध भेज सकता है जिनका वर्कर ने जवाब दे दिया है. ऐसे में रद्द करने के अनुरोध को अनदेखा किया जाना चाहिए.

हर रद्द नहीं किए गए WorkRequest मैसेज का बिलकुल एक बार जवाब दिया जाना चाहिए, चाहे वह रद्द किया गया हो या नहीं. अगर सर्वर रद्द करने का अनुरोध भेजता है, तो हो सकता है कि वर्कर WorkResponse के साथ, request_id सेट और was_cancelled फ़ील्ड को 'सही है' पर सेट करे. सामान्य WorkResponse भेजने की भी अनुमति है, लेकिन output और exit_code फ़ील्ड को अनदेखा कर दिया जाएगा.

WorkRequest के लिए जवाब भेजे जाने के बाद, वर्कर को अपनी काम करने वाली डायरेक्ट्री में मौजूद फ़ाइलों को नहीं छूना चाहिए. सर्वर, अस्थायी फ़ाइलों सहित फ़ाइलों को साफ़ करने के लिए स्वतंत्र है.

वर्कर का इस्तेमाल करने वाला नियम बनाना

आपको एक ऐसा नियम भी बनाना होगा जो वर्कर की कार्रवाई करेगा. किसी कर्मचारी का उपयोग करने वाला Starlark नियम बनाना कोई अन्य नियम बनाने जैसा ही है.

इसके अलावा, नियम में वर्कर के लिए रेफ़रंस भी होना चाहिए. साथ ही, यहां मौजूद कार्रवाइयों के लिए भी कुछ ज़रूरी शर्तें हैं.

वर्कर की बात की जा रही है

वर्कर नियम का इस्तेमाल करने वाले नियम में वह फ़ील्ड शामिल होना चाहिए जो वर्कर के बारे में बताता है. इसलिए, आपको अपने वर्कर को तय करने के लिए \*\_binary नियम का इंस्टेंस बनाना होगा. अगर आपके वर्कर को MyWorker.Java कहा जाता है, तो यह असोसिएट नियम हो सकता है:

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

इससे वर्कर बाइनरी का लेबल "वर्कर" लेबल बनता है. इसके बाद, आपको वर्कर को इस्तेमाल करने वाला नियम तय करना होगा. इस नियम से किसी ऐसे एट्रिब्यूट की जानकारी मिलनी चाहिए जो वर्कर बाइनरी से जुड़ा हो.

अगर आपके बनाए गए वर्कर बाइनरी का नाम "work" है, जो पैकेज के टॉप लेवल पर मौजूद होता है, तो हो सकता है कि यह एट्रिब्यूट की परिभाषा हो:

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

cfg = "exec" से पता चलता है कि वर्कर को टारगेट प्लैटफ़ॉर्म के बजाय, आपके एक्ज़ीक्यूशन प्लैटफ़ॉर्म पर चलाने के लिए बनाया जाना चाहिए. उदाहरण के लिए, बिल्ड के दौरान वर्कर का इस्तेमाल टूल के तौर पर किया जाता है.

काम से जुड़ी ज़रूरी शर्तें

वर्कर का इस्तेमाल करने वाला नियम, वर्कर के लिए कार्रवाइयां बनाता है. इन कार्रवाइयों के लिए कुछ ज़रूरी शर्तें पूरी करनी होंगी.

  • "तर्क" फ़ील्ड. यह स्ट्रिंग की एक सूची लेता है. इसमें, आखिर में दिए गए आर्ग्युमेंट के अलावा, सभी स्ट्रिंग की सूची होती है. "तर्क" सूची के आखिरी एलिमेंट में एक flag-file (@-पिछली) तर्क है. वर्कर, तय किए गए फ़्लैग फ़ाइल के आर्ग्युमेंट को हर WorkRequest आधार पर पढ़ते हैं. आपका नियम, इस फ़्लैगफ़ाइल के लिए वर्कर के लिए नॉन-स्टार्टअप आर्ग्युमेंट लिख सकता है.

  • "एक्ज़ीक्यूशन से जुड़ी ज़रूरी शर्तें" फ़ील्ड, जो शब्दकोश में "supports-workers" : "1", "supports-multiplex-workers" : "1" या दोनों को लेता है.

    "कर्मचारी" और "कार्रवाई करने से जुड़ी ज़रूरी शर्तें" फ़ील्ड, कर्मचारियों को भेजी जाने वाली सभी कार्रवाइयों के लिए ज़रूरी होते हैं. इसके अलावा, जिन कार्रवाइयों को JSON वर्कर लागू करता है उन्हें एक्ज़ीक्यूशन की ज़रूरी शर्तों वाले फ़ील्ड में "requires-worker-protocol" : "json" को शामिल करना होगा. "requires-worker-protocol" : "proto" एक मान्य निष्पादन भी है, हालांकि यह प्रोटो वर्कर्स के लिए ज़रूरी नहीं है, क्योंकि वे डिफ़ॉल्ट हैं.

    एक्ज़ीक्यूशन के लिए ज़रूरी शर्तों में, worker-key-mnemonic भी सेट किए जा सकते हैं. अगर आप कई तरह की कार्रवाइयों के लिए एक्ज़ीक्यूटेबल का फिर से इस्तेमाल कर रहे हैं और इस कार्रवाई के लिए अलग-अलग कार्रवाई करना चाहते हैं, तो यह काम का हो सकता है.

  • कार्रवाई के दौरान जनरेट की गई अस्थायी फ़ाइलों को वर्कर की डायरेक्ट्री में सेव किया जाना चाहिए. इससे सैंडबॉक्सिंग चालू हो जाती है.

ऊपर बताए गए "वर्कर" एट्रिब्यूट वाली नियम परिभाषा को मानते हुए, इनपुट के बारे में बताने वाला "srcs" एट्रिब्यूट और आउटपुट को दिखाने वाला "आउटपुट" एट्रिब्यूट. इसके बाद, वर्कर स्टार्टअप आर्ग्युमेंट को दिखाने वाला "args" एट्रिब्यूट, ctx.actions.run को कॉल कर सकता है:

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

दूसरे उदाहरण के लिए, स्थायी वर्कर को लागू करना देखें.

उदाहरण

Bazel कोड बेस, Java कंपाइलर वर्कर का इस्तेमाल करता है. हमारे JSON टेस्ट में, इस उदाहरण के तौर पर JSON वर्कर का इस्तेमाल भी किया जाता है.

सही कॉलबैक पास करके, किसी भी Java-आधारित टूल को वर्कर में बनाने के लिए, आप उनके स्क्रैफ़ोल्डिंग का इस्तेमाल कर सकते हैं.

वर्कर का इस्तेमाल करने वाले नियम के उदाहरण के लिए, Bazel का वर्कर इंटिग्रेशन टेस्ट देखें.

बाहरी योगदान देने वालों ने अलग-अलग भाषाओं में वर्कर को लागू किया है. बैजल परसिस्टेंट वर्कर्स के पॉलीपॉलिट को लागू करने पर एक नज़र डालें. GitHub पर आपको और भी कई उदाहरण मिल सकते हैं!