रन कैसे चलता है
एक रन शुरुआत पर शुरू होता है, नोड से नोड तक वायरों का पीछा करता है, और तब पूरा होता है जब हर शाखा समाप्त हो जाए और अंत तक पहुँच जाए। यह पेज उन नियमों को समझाता है जिनका वह पालन करता है; हर नोड क्या करता है यह नोड संदर्भ में है, और उसके साथ चलने वाले मान डेटा में।
शुरुआत और अंत
एक प्रयोग में ठीक एक शुरुआत और एक अंत होता है।
- शुरुआत का कोई इनपुट नहीं होता। यह तुरंत आगे बढ़ जाता है, और टाइमलाइन में उसकी पंक्ति रन का सीड देती है। उसके आउटपुट पर कई वायर हो सकते हैं: तब प्रयोग समानांतर शाखाओं से शुरू होता है।
- जो भी शाखा अंत तक पहुँचती है, वहीं रुक जाती है। End पहली बार पहुँचने से चलता हुआ दिखता है और एक बार आगे बढ़ता है, आख़िरी शाखा समाप्त होने के बाद — और अगर कोई चरण विफल हुआ हो तो बिल्कुल नहीं। वही आगे बढ़ना रन को सफल बनाता है।
- जिस रन में हर शाखा बिना त्रुटि के समाप्त हुई पर कोई End तक नहीं पहुँचा, वह
run.no_endके साथ विफल होता है।
आउटपुट और वायर
कोई नोड का चरण कोई आउटपुट चुनकर समाप्त होता है, और रन उस आउटपुट के हर वायर का पीछा करता है। ज़्यादातर नोड का एक आउटपुट होता है, आउटपुट; कुछ कई में से चुनते हैं:
| नोड | जिन आउटपुट पर वायर ज़रूरी है | जिन आउटपुट पर वायर हो सकता है |
|---|---|---|
| अंत | — | — |
| समानांतर शाखा | शाखा 1, शाखा 2 | — |
| स्टेटस पर शाखा, मान पर शाखा | हाँ, नहीं | — |
| हर प्रतीक्षा (OSC की प्रतीक्षा, UDP की प्रतीक्षा, MQTT की प्रतीक्षा, HTTP रिक्वेस्ट की प्रतीक्षा, WebSocket की प्रतीक्षा) | मेल खाया | टाइमआउट |
| लूप | बॉडी, पूर्ण | सीमा |
| हर दूसरा नोड | आउटपुट | — |
जोड़ने के लिए, किसी आउटपुट से किसी नोड पर खींचें; ख़ाली कैनवास पर छोड़ने पर वहाँ एक नया नोड जुड़ जाता है। जिस आउटपुट पर पहले से वायर है, उससे खींचने पर एक और जुड़ जाता है। अगला जोड़ें, A कुंजी और किसी वायर पर का + इसके बजाय मौजूदा वायर में एक नोड जोड़ देते हैं।
अधूरा ग्राफ़ एक ड्राफ़्ट है: वह सहेजा जाता है, पर चलता नहीं। टूलबार में ग्राफ़ पूरा करें बताता है कि क्या ग़ायब है और उस नोड को दिखाता है। देखें रन से पहले क्या जाँचा जाता है।
समानांतर शाखाएँ
एक आउटपुट से कई वायर
जब किसी आउटपुट पर कई वायर हों — शुरुआत के भी — तो जिन नोडों तक वे ले जाते हैं, वे सब एक साथ चलते हैं। पहला वायर शाखा को जारी रखता है; हर अगला वायर एक समानांतर शाखा शुरू करता है। हर शाखा चरों और नवीनतम HTTP रिस्पॉन्स की अपनी प्रति ले चलती है, इसलिए एक शाखा जो सेट करती या प्राप्त करती है, बाकी को नहीं दिखता।
समानांतर शाखा और Join
समानांतर शाखा तुरंत आगे बढ़ता है और शाखा 1 तथा शाखा 2 दोनों से निकलता है — वही जो एक आउटपुट से दो वायर हैं, नोड के रूप में बनाए हुए।
शाखाएँ जोड़ें उसमें आने वाले हर वायर की प्रतीक्षा करता है, फिर उन वायरों के क्रम में मिलाई गई प्रतियों के साथ एक शाखा के रूप में आगे बढ़ता है:
- उन सबके चर — जिस नाम को दो शाखाएँ दोनों सेट करती हैं, उसमें प्रयोग में बाद में सूचीबद्ध वायर जीतता है;
- आख़िरी वायर का HTTP रिस्पॉन्स, उसी क्रम में, जो कोई लाता हो;
- उसके बाद की प्रतीक्षाओं के लिए, उनकी नवीनतम क्रियाओं में से सबसे पहली।
वायरों का क्रम तय करता है, कभी नहीं कि कौन-सी शाखा पहले समाप्त हुई।
Join केवल उन्हीं का, जो समानांतर चलते हैं
एक Join अपने वायर गिनता है, चाहे वे समानांतर कैसे भी चले हों: किसी समानांतर शाखा से, एक आउटपुट के कई वायरों से, अलग पथों से। किसी शाखा के हाँ और नहीं के पीछे केवल एक पथ चलता है, इसलिए दोनों से भरा Join ऐसी शाखा की प्रतीक्षा करता है जो कभी आती ही नहीं: रन run.join_waiting के साथ विफल होता है, और बताता है कि कितने वायरों का पीछा कभी नहीं किया गया। वैकल्पिक पथों को मिलाने के लिए, उन्हें सीधे अगले नोड में वायर करें।
जो नोड Join नहीं है, और जिस तक दो समानांतर शाखाएँ पहुँचती हैं, वह उनमें से हर एक के लिए एक बार चलता है।
जब कोई चरण विफल होता है
पहली विफलता रन को विफल कर देती है। बाकी शाखाएँ कोई नया चरण शुरू नहीं करतीं: कोई दोहराव या लोड जल्दी समाप्त हो जाता है, बाकी जिस भी चरण में वे हैं वह अपने अंत तक चलता रहता है। इस बीच उन्हें मिलने वाली कोई विफलता टाइमलाइन में रिपोर्ट होती है पर रन की त्रुटि नहीं होती। जो चरण टाइमआउट वायर मौजूद रहते टाइमआउट में पड़ा, वह विफल नहीं हुआ — देखें प्रतीक्षाएँ।
शाखा बनाना
| नोड | तब हाँ से निकलता है जब |
|---|---|
| स्टेटस पर शाखा | इस पथ पर नवीनतम HTTP रिस्पॉन्स का स्टेटस दिया गया है |
| मान पर शाखा | उसकी तुलना सही होती है — देखें मानों की तुलना |
वरना हर एक नहीं से निकलता है। एक स्टेटस शाखा को हर पथ पर अपने से पहले एक HTTP रिक्वेस्ट चाहिए; मान पर आधारित शाखा को वे नाम वहाँ ज्ञात चाहिए जो वह पढ़ती है। जब हाँ और नहीं के बाद के पथ फिर मिलते हैं, तो जिस नोड पर वे मिलते हैं वह एक बार चलता है, और वहाँ केवल वे चर ज्ञात होते हैं जो दोनों पथों पर सेट हुए (चर कहाँ ज्ञात होता है)।
दोबारा प्रयास
जो चरण भेजता या सुनता है, वह विफल होने पर फिर से कोशिश कर सकता है: उसके गुणों में विफल होने पर पुनः प्रयास करें चालू करें।
| सेटिंग | क्या | सीमा | पहले दिया गया |
|---|---|---|---|
| प्रयास | कुल कोशिशें, पहली मिलाकर | 1–10 | 3 |
| विराम, ms | दूसरी कोशिश से पहले का ठहराव | 0–60 000 ms | 500 |
| विराम | एक जैसे: हर ठहराव समान; दोगुने होते: हर ठहराव पिछले से दुगुना | — | एक जैसे |
- दोबारा प्रयास HTTP रिक्वेस्ट, TCP संदेश, MQTT पब्लिश, OSC संदेश, UDP डेटाग्राम, WebSocket कनेक्ट, WebSocket भेजें और हर प्रतीक्षा पर लागू होता है। बाकी नोड इसे अस्वीकार करते हैं (
node.retry_unsupported), और लोड के तहत कोई HTTP रिक्वेस्ट दोबारा प्रयास नहीं लेती। - कोई अकेला ठहराव 60 s से लंबा नहीं होता, दुगुना चाहे जो भी दे।
- हर विफल कोशिश टाइमलाइन में पुनः प्रयास के रूप में दिखती है, उसके नंबर और कारण के साथ। फिर चरण सफल होता है, या आख़िरी कोशिश के कारण के साथ विफल।
- केवल निष्पादन दोहराया जाता है। जिस फ़ील्ड का टेम्पलेट हल नहीं होता, वह तुरंत विफल होता है।
- जो भेजना अपने जवाब की प्रतीक्षा करता है, वह फिर भेजता है। एक प्रतीक्षा फिर प्रतीक्षा करती है, पहले की तरह शाखा की नवीनतम क्रिया से गिनते हुए।
- टाइमआउट वायर वाली प्रतीक्षा टाइमआउट पर विफल नहीं होती, इसलिए उसका दोबारा प्रयास नहीं होता: वह टाइमआउट का पालन करती है।
- रोकें किसी ठहराव को तुरंत समाप्त कर देता है।
दोहराव
जो चरण भेजता है वह बार-बार भेज सकता है — कोई हार्टबीट, कोई पोल, कोई स्थिर धारा — ग्राफ़ में लूप के बिना: भेजना दोहराएँ चालू करें।
| सेटिंग | क्या | सीमा | पहले दिया गया |
|---|---|---|---|
| दोहराव | तय संख्या में या तय समय तक | — | तय संख्या में |
| बार | कुल भेजे जाने, पहला मिलाकर | 2–10 000 | 10 |
| अवधि, ms | कितनी देर भेजते रहना है, पहले भेजे जाने से | 1–300 000 ms | 10 000 |
| अंतराल, ms | दो भेजे जाने के बीच का ठहराव | 10–60 000 ms | 1000 |
| जिटर, ms | हर ठहराव रैंडम रूप से इतना तक और लंबा | 0–60 000 ms | 0 |
- दोहराव HTTP रिक्वेस्ट, TCP संदेश, MQTT पब्लिश, OSC संदेश, UDP डेटाग्राम और WebSocket भेजें पर लागू होता है (बाकी जगह
node.repeat_unsupported)। किसी HTTP रिक्वेस्ट में या तो दोहराव होता है या लोड, दोनों नहीं। - हर भेजना वैसे ही होता है जैसे अकेला होता: उसके टेम्पलेट फिर पढ़े जाते हैं —
{{counter}}भेजे जाने का नंबर है,{{now}}उसका समय — और दोबारा प्रयास, चालू हो तो, हर भेजे जाने पर लागू होता है। जो भेजना अपने जवाब की प्रतीक्षा करता है, वह अपने जवाब की प्रतीक्षा करता है। - समय के अनुसार, कोई भेजना तभी होता है जब वह समय समाप्त होने से पहले शुरू हो सकता हो।
- जिटर रन के सीड से निकाला जाता है: वही सीड वही ठहराव देता है।
- टाइमलाइन प्रगति दोहरा रहा है के रूप में अधिकतम सेकंड में एक बार रिपोर्ट करती है। आख़िरी भेजे जाने के बाद चरण सफल होता है, उसी भेजे जाने के नतीजे के साथ; जो भेजना पक्का विफल होता है वह चरण विफल कर देता है।
- किसी दूसरी शाखा की विफलता भेजना समाप्त कर देती है; रोकें किसी ठहराव को तुरंत समाप्त करता है।
उसे एक रन में फ़िट होना चाहिए: भेजे जाने और उनके सबसे लंबे ठहराव ((count − 1) × (interval + jitter)) अधिकतम 300 s (node.repeat_too_long), और समय-आधारित दोहराव में अधिकतम 10 000 भेजे जाने (node.repeat_too_many)।
लूप
लूप अपने बॉडी आउटपुट पर चरणों को बार-बार चलाता है; उनमें से आख़िरी लूप से वापस जोड़ा जाता है।
| सेटिंग | क्या | सीमा |
|---|---|---|
| अधिकतम इटरेशन | सबसे ज़्यादा पुनरावृत्तियाँ | 1–1000 |
| पहले रुकें, जब | एक निकास शर्त: मान, शर्त, अपेक्षित, जैसे मान जाँचें में | वैकल्पिक |
- बाहर से पहुँचने पर, लूप बॉडी पर पुनरावृत्ति 1 शुरू करता है।
- हर बार जब बॉडी वापस आती है, निकास शर्त पढ़ी जाती है — पुनरावृत्ति के बाद, इसलिए बॉडी हमेशा कम से कम एक बार चलती है और जिसे वह जाँचती है उसे सेट कर सकती है।
- जब शर्त सही होती है, लूप पूर्ण से निकलता है।
- वरना अगली पुनरावृत्ति शुरू होती है, जब तक कोई बची हो।
- जब पुनरावृत्तियाँ पहले ख़त्म हो जाती हैं, तो लूप सीमा से निकलता है अगर उस पर वायर हो, और अगर न हो तो
loop.limitके साथ रन विफल कर देता है। शर्त के बिना, बॉडी हर पुनरावृत्ति चलती है और लूप पूर्ण से निकलता है।
बॉडी के भीतर {{counter}} पुनरावृत्ति का नंबर है, क्योंकि हर नोड अपने निष्पादन ख़ुद गिनता है। शर्त और पूर्ण या सीमा के बाद के चरण वह इस्तेमाल कर सकते हैं जो बॉडी की हर पुनरावृत्ति सेट करती है — जैसे बॉडी द्वारा निकाला गया कोई स्टेटस; बॉडी ख़ुद केवल वही देखती है जो लूप तक पहुँचने पर ज्ञात था।
टेम्पलेट तैयार होने तक पोल करें किसी डिवाइस से हर 0.3 s पर उसका स्टेटस माँगता है जब तक वह ready जवाब न दे, अधिकतम 10 बार।
बॉडी में क्या हो सकता है
बॉडी एक शाखा के रूप में चलती है, एक के बाद एक पुनरावृत्ति। लूप तक वापस जाने वाला वायर ही अकेला चक्र है जो प्रयोग में हो सकता है; कोई और graph.cycle है।
| नियम | त्रुटि |
|---|---|
| बॉडी पर कुछ लूप तक वापस ले जाता है | loop.no_return |
| बॉडी में हर आउटपुट पर एक वायर है | loop.body_parallel |
| बॉडी में हर आउटपुट बॉडी में आगे या लूप तक वापस ले जाता है | loop.body_leaves |
| बॉडी में केवल लूप का बॉडी आउटपुट ही ले जाता है | loop.body_entered |
| बॉडी में कोई शुरुआत, अंत, समानांतर शाखा, शाखाएँ जोड़ें या दूसरा लूप नहीं | loop.body_unsupported |
प्रतीक्षाएँ
एक प्रतीक्षा तब सफल होती है जब जिस संदेश की वह प्रतीक्षा कर रही है वह आ जाए: OSC की प्रतीक्षा, UDP की प्रतीक्षा, MQTT की प्रतीक्षा, HTTP रिक्वेस्ट की प्रतीक्षा और WebSocket की प्रतीक्षा। हर एक किससे मेल खाती है यह नोड संदर्भ में है; यह बताता है कि वे कैसे सुनती हैं।
शुरुआत से सुनना
रन जिन चीज़ों पर अपनी प्रतीक्षाएँ सुनती हैं, उन्हें अपने पहले चरण से पहले खोलता है, ताकि अगले चरण से तेज़ आने वाला जवाब न छूटे:
| प्रतीक्षा | पहले चरण से पहले खुलने वाली चीज़ |
|---|---|
| OSC, UDP | सुनने का पता (IP:port) पते पर एक UDP सॉकेट, उस पर हर प्रतीक्षा द्वारा साझा |
| HTTP रिक्वेस्ट | पते पर एक लिसनर — रन का HTTP एमुलेटर जब कोई हो, वरना एक जो 204 जवाब देता है |
| MQTT | हर ब्रोकर और टॉपिक फ़िल्टर के लिए एक कनेक्शन, सब्सक्राइब किया हुआ; जो retained संदेश ब्रोकर तब दोबारा भेजता है वे अनदेखा किए जाते हैं |
| WebSocket | कुछ नहीं: वह उस कनेक्शन को पढ़ता है जो WebSocket कनेक्ट ने चलते समय खोला था |
चूँकि वे पहले खुलती हैं, ये पते रन से पहले तय हो जाते हैं: OSC, UDP या HTTP प्रतीक्षा 0 के अलावा किसी पोर्ट के साथ शाब्दिक IP:port पर सुनती है, और MQTT प्रतीक्षा का ब्रोकर और टॉपिक केवल पैरामीटर लेते हैं। जो पोर्ट खोला नहीं जा सकता — लिया गया, या इस कंप्यूटर का पता नहीं — वह किसी भी ट्रैफ़िक से पहले, उस प्रतीक्षा के फ़ील्ड पर, रन रोक देता है। रन जब किसी भी तरह समाप्त होता है, सब कुछ बंद कर दिया जाता है।
कौन-से संदेश गिने जाते हैं
एक प्रतीक्षा उन संदेशों को गिनती है जो उसकी शाखा की नवीनतम क्रिया शुरू होने के बाद आए — नवीनतम रिक्वेस्ट, संदेश, पब्लिश, WebSocket कनेक्ट या भेजना — या, किसी क्रिया से पहले, रन शुरू होने के बाद। रिक्वेस्ट से पहले का संदेश नहीं गिना जाता, और रिक्वेस्ट तथा प्रतीक्षा के बीच का कोई विलंब या लॉग उसका जवाब नहीं छिपाता। किसी Join के बाद, मिलाई गई शाखाओं की सबसे पहली नवीनतम क्रिया गिनी जाती है।
एक प्रतीक्षा पहला मेल खाता संदेश लेती है और उसे खपा देती है: दो प्रतीक्षाएँ कभी एक ही संदेश से मेल नहीं खातीं।
हर सॉकेट, सब्सक्रिप्शन या कनेक्शन अपनी प्रतीक्षाओं के लिए अधिकतम 1024 संदेश और 64 MiB रखता है; उससे आगे, सबसे पुराने गिरा दिए जाते हैं और गिने जाते हैं।
टाइमआउट
टाइमआउट, ms 1–120 000 ms है, शुरू में 2000। जब समय में कुछ मेल नहीं खाता:
- टाइमआउट वायर के साथ, प्रतीक्षा उसका पालन करती है;
- उसके बिना, चरण
wait.timeoutके साथ विफल होता है, जो बताता है कि इस बीच कितने और संदेश आए — ग़लत पैटर्न चुप डिवाइस से अलग दिखता है — और, उसके विवरण में, कतार भरने पर कितने पुराने संदेश गिराए गए।
प्रतीक्षा का चर — reply, या HTTP के लिए request — केवल मेल खाया के बाद मौजूद होता है। जब इंस्पेक्टर कैप्चर कर रहा हो, तो चरण उस फ़्रेम को भी जोड़ देता है जिससे वह मेल खाया: देखें टाइमलाइन।
उसी चरण पर जवाब
एक OSC संदेश या UDP डेटाग्राम अपने जवाब की प्रतीक्षा कर सकता है: जवाब की प्रतीक्षा करें चालू करें।
| सेटिंग | क्या | पहले दिया गया |
|---|---|---|
| जवाब का पोर्ट (IP:port) | वह पता जिस पर जवाब की प्रतीक्षा की जाती है; पोर्ट 0 कोई भी ख़ाली पोर्ट है | 0.0.0.0:0 |
| जवाब का पता पैटर्न (OSC), जवाब का पेलोड (UDP) | जवाब क्या होना चाहिए, जैसे मेल खाती प्रतीक्षा में | कोई भी |
| टाइमआउट, ms | 1–120 000 ms | 2000 |
| जवाब का वैरिएबल | वह चर जिसमें जवाब लिखा जाता है | reply |
जवाब का पोर्ट (IP:port) पर का सॉकेट पहले चरण से पहले खोला जाता है, किसी प्रतीक्षा की तरह, और संदेश उसी से बाहर जाता है: जो डिवाइस भेजने वाले के अपने पोर्ट पर जवाब देता है वह सुनाई देता है, और जो किसी तय पोर्ट पर जवाब देता है वह तब सुनाई देता है जब वही पोर्ट दिया गया हो। मेल खाता जवाब मिलने पर चरण सफल होता है, और चर उसके आउटपुट के बाद मौजूद होता है। कोई टाइमआउट आउटपुट नहीं है: समय में जवाब न आना चरण को विफल कर देता है, और दोबारा प्रयास फिर भेज सकता है। चुप्पी पर शाखा बनाने के लिए, अलग प्रतीक्षा इस्तेमाल करें।
रन से पहले क्या जाँचा जाता है
एडिटर प्रयोग को संपादन के साथ-साथ जाँचता है; Run बटन एक बार और जाँचता है। कोई समस्या नोड का नाम बताती है, और फ़ील्ड का भी जब कोई हो।
| नियम | त्रुटि |
|---|---|
| प्रयोग का एक नाम है | doc.name_required |
| 1–64 नोड, ठीक एक Start और एक End | doc.node_count, doc.start_end_count |
| Start का कोई इनपुट नहीं | graph.start_input |
| एक वायर किसी और मौजूद नोड तक ले जाता है | doc.connection_invalid |
| वही वायर दो बार नहीं है | doc.connection_duplicate |
| जिस हर आउटपुट पर वायर ज़रूरी है, उस पर है | graph.outputs_required |
| जो आउटपुट किसी नोड में नहीं है, उस पर उसका वायर नहीं है | graph.port_unexpected |
| हर नोड तक Start से पहुँचा जा सकता है | graph.unreachable |
| लूप के वापसी वायर के अलावा कोई चक्र नहीं | graph.cycle, और बॉडी के नियम |
| किसी जाँच या Extract से पहले हर पथ पर एक HTTP रिक्वेस्ट है; लोड के तहत वाली रिक्वेस्ट नहीं गिनी जाती | graph.needs_http |
| हर टेम्पलेट पार्स होता है, और उसका इस्तेमाल किया हर नाम हर पथ पर ज्ञात है | template.*, name.* — देखें डेटा |
| हर फ़ील्ड मौजूद और सीमा में है | node.* |
| जो नोड किसी और का नाम लेता है — बाधा बदलें, एमुलेटर बंद/चालू, WebSocket नोड — वह वहाँ मौजूद एक का नाम लेता है, और WebSocket नोड अपने कनेक्ट के बाद आता है | impair.relay_unknown, emulator.node_unknown, ws.connection_unknown, ws.connection_after |
| रन के दो सॉकेट एक पोर्ट साझा नहीं करते | देखें फ़ॉल्ट |
फिर रन जाँचता है कि उसे शुरू होने के लिए क्या चाहिए: हर सीक्रेट सहेजा हुआ, हर पोर्ट खुला। जब तक सब कुछ सही न हो, कोई चरण नहीं चलता और कुछ नहीं भेजा जाता।
समय सीमा
एक रन अधिकतम 300 s चलता है। उसके बाद भी चल रहा रन रोक दिया जाता है और run.timeout के साथ विफल होता है। कमांड लाइन और API से सीमा छोटी हो सकती है, 1–300 s।
रोकें
जब तक कोई रन चलता है, Run बटन रोकें होता है। रोकें रन को तुरंत समाप्त कर देता है: हर शाखा, दोबारा प्रयास या दोहराव का हर ठहराव, हर प्रतीक्षा और हर लोड — रास्ते में चल रही रिक्वेस्ट गिरा दी जाती हैं। उसके सॉकेट, सब्सक्रिप्शन, एमुलेटर और रिले बंद हो जाते हैं, और उसके WebSocket कनेक्शन एक close फ़्रेम भेजते हैं। हेडर में सभी रोकें हर जॉब के साथ यही करता है। रोका गया रन कोई रिपोर्ट नहीं सहेजता; देखें रन।