स्थायी कर्मचारी बनाना

7.3 · 7.2 · 7.1 · 7.0 · 6.5

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

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

वर्कर लागू करने के दो हिस्से होते हैं:

कर्मचारी को

लगातार काम करने वाले लोग, कुछ ज़रूरी शर्तों को पूरा करते हैं:

  • यह अपने stdin से WorkRequests को पढ़ता है.
  • यह अपने stdout में WorkResponses (और सिर्फ़ WorkResponse) लिखता है.
  • यह --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 फ़्लैग को Basel में पास करने पर, verbosity फ़ील्ड को 10 पर सेट कर दिया जाता है. हालांकि, आउटपुट की अलग-अलग वैल्यू के लिए, छोटी या बड़ी वैल्यू को मैन्युअल तरीके से इस्तेमाल किया जा सकता है.

sandbox_dir फ़ील्ड का इस्तेमाल सिर्फ़ उन वर्कर्स के लिए किया जाता है जो मल्टीप्लेक्स सैंडबॉक्सिंग की सुविधा के साथ काम करते हैं. हालांकि, इस फ़ील्ड का इस्तेमाल करना ज़रूरी नहीं है.

काम से जुड़े जवाब

WorkResponse में एक अनुरोध आईडी, एक शून्य या नॉन-ज़ीरो एक्ज़िट कोड, और एक आउटपुट स्ट्रिंग शामिल होती है, जो अनुरोध को प्रोसेस या निष्पादित करते समय होने वाली किसी भी गड़बड़ी के बारे में बताती है. output फ़ील्ड में कम शब्दों में जानकारी होती है. वर्कफ़्लो के पूरे लॉग, वर्कफ़्लो के stderr में लिखे जा सकते हैं. ऐसा हो सकता है कि वर्कर, सिर्फ़ WorkResponses को stdout पर लिख रहे हों. आम तौर पर, वर्कर किसी भी टूल के 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 का इस्तेमाल किया जाता है. साथ ही, सभी फ़ील्ड के नामों के लिए ऊंट के केस का इस्तेमाल किया जाता है.
  • protobuf की तरह ही, पुराने और नए वर्शन के साथ काम करने की प्रॉपर्टी बनाए रखने के लिए, JSON वर्कर्स को इन मैसेज में अनजान फ़ील्ड को बर्दाश्त करना होगा. साथ ही, वैल्यू मौजूद न होने पर protobuf की डिफ़ॉल्ट वैल्यू का इस्तेमाल करना होगा.
  • Basel, अनुरोधों को प्रोटोबफ़ के तौर पर सेव करता है और उन्हें protobuf के JSON फ़ॉर्मैट का इस्तेमाल करके, JSON में बदलता है

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

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

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

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

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

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

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

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

कर्मचारी के बारे में जानकारी

वर्कफ़्लो में वर्कर्स का इस्तेमाल करने वाले नियम में, वर्कर्स का रेफ़रंस देने वाला फ़ील्ड होना चाहिए. इसलिए, आपको अपने वर्कर्स की जानकारी देने के लिए, \*\_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 के आधार पर पढ़ते हैं. आपका नियम इस फ़्लैगफ़ाइल में वर्कर के लिए, नॉन-स्टार्टअप आर्ग्युमेंट लिख सकता है.

  • "execution-requirements" फ़ील्ड, जो "supports-workers" : "1", "supports-multiplex-workers" : "1" या दोनों वाले शब्दकोश लेता है.

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

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

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

ऊपर बताए गए "worker" एट्रिब्यूट के साथ नियम की परिभाषा मानते हुए, इनपुट दिखाने वाले "srcs" एट्रिब्यूट, आउटपुट दिखाने वाले "output" एट्रिब्यूट, और वर्कर के स्टार्टअप आर्ग्युमेंट दिखाने वाले "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"]
 )

दूसरा उदाहरण देखने के लिए, पर्सिस्टेंट वर्कर्स लागू करना लेख पढ़ें.

उदाहरण

बेज़ेल कोड बेस हमारे इंटिग्रेशन टेस्ट में इस्तेमाल किए जाने वाले उदाहरण JSON वर्कर के अलावा, Java कंपाइलर वर्कर का इस्तेमाल करता है.

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

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

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