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

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

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

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

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

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

WorkResponse में अनुरोध आईडी, शून्य या शून्य से ज़्यादा वाला बाहर निकलने का कोड, और आउटपुट मैसेज होता है. इस मैसेज में, अनुरोध को प्रोसेस करने या उसे लागू करने में हुई गड़बड़ियों के बारे में बताया जाता है. वर्कर को ऐसे किसी भी टूल के stdout और stderr को कैप्चर करना चाहिए, जिसे वह कॉल करता है और WorkResponse के ज़रिए उनकी रिपोर्ट करता है. इसे वर्कर प्रोसेस के 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,
}

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

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

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

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

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

रद्द करने का अनुरोध, cancel फ़ील्ड सेट वाला WorkRequest होता है. इसी तरह, रद्द करने का जवाब, was_cancelled फ़ील्ड सेट वाला WorkResponse होता है. रद्द करने के अनुरोध या रद्द करने के जवाब में, request_id फ़ील्ड होना ज़रूरी है. इससे यह पता चलता है कि किस अनुरोध को रद्द करना है. सिंगलप्लेक्स वर्कर के लिए request_id फ़ील्ड में 0 दिखेगा. वहीं, मल्टीप्लेक्स वर्कर के लिए, पहले भेजे गए WorkRequest के request_id में 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 के आधार पर पढ़ते हैं. आपका नियम, इस फ़्लैगफ़ाइल में वर्कर्स के लिए, स्टार्टअप के अलावा अन्य आर्ग्युमेंट लिख सकता है.

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

    कर्मचारियों को भेजी गई सभी कार्रवाइयों के लिए "तर्क" और "लागू करने की ज़रूरी शर्तें" फ़ील्ड ज़रूरी हैं. इसके अलावा, JSON वर्कर्स के ज़रिए की जाने वाली कार्रवाइयों के लिए, "requires-worker-protocol" : "json" को 'कार्रवाई करने से जुड़ी ज़रूरी शर्तें' फ़ील्ड में शामिल करना ज़रूरी है. "requires-worker-protocol" : "proto", प्रोटो वर्कर्स के लिए ज़रूरी नहीं है, क्योंकि वे डिफ़ॉल्ट तौर पर उपलब्ध होते हैं. हालांकि, प्रोटो वर्कर्स को लागू करने के लिए, "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"]
 )

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

उदाहरण

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

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

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

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