PHP Academy · पाठ

इवेंट-ड्रिवन वर्कफ़्लो बनाना

इवेंट और इडेम्पोटेंसी के माध्यम से सेवाओं का समन्वय करें।

पाठ 4, कुल 4 में से13 चरण

इवेंट-ड्रिवन वर्कफ़्लो बनाना, CoddyKit पर PHP Academy का एक निःशुल्क पाठ है। यह 4 में से 4वाँ पाठ है। आप नीचे पूरा पाठ निःशुल्क पढ़ सकते हैं—फिर अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर के साथ ब्राउज़र में इसका व्यावहारिक अभ्यास कर सकते हैं। यह PHP Academy सीखने के मार्ग का हिस्सा है और आपकी प्रगति वेब तथा CoddyKit ऐप पर सिंक होती रहती है। PHP Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

घटना-प्रेरित कार्यप्रवाह

एक संदेश सरल होता है। कई सेवाओं में फैला हुआ कार्यप्रवाह — "आदेश दिया गया → स्टॉक आरक्षित कीजिए → कार्ड से शुल्क लीजिए → भेजिए → सूचना दीजिए" — वह जगह है जहाँ घटना-प्रेरित अभिकल्पना अपना महत्व दिखाती है और जहाँ इसे सरलतापूर्वक करने पर यही आपके लिए समस्या बन जाती है।

इस पाठ में कोरियोग्राफी बनाम ऑर्केस्ट्रेशन, परमाणु प्रकाशन के लिए आउटबॉक्स प्रतिरूप, वितरित वापसी-प्रक्रिया के लिए सागा और इन सबको एक साथ बाँधे रखने वाली पुनरावृत्ति-सुरक्षा शामिल है।

कोरियोग्राफी बनाम ऑर्केस्ट्रेशन

बहु-चरणीय प्रवाहों का समन्वय करने के दो तरीके हैं:

  • कोरियोग्राफी — प्रत्येक सेवा घटनाओं पर प्रतिक्रिया देती है और अपनी घटनाएँ उत्पन्न करती है; कोई केंद्रीय नियंत्रण नहीं होता। सेवाएँ ढीले रूप से जुड़ी रहती हैं, लेकिन the समग्र प्रवाह अप्रत्यक्ष और उसका पता लगाना कठिन होता है।
  • ऑर्केस्ट्रेशन — एक केंद्रीय समन्वयक प्रत्येक सेवा को बताता है कि अगला काम क्या करना है। यह स्पष्ट और निगरानी योग्य होता है, लेकिन ऑर्केस्ट्रेटर जुड़ाव का एक केंद्र बन जाता है।

सामान्य नियम: सरल प्रसारण के लिए कोरियोग्राफी और कई क्रमबद्ध चरणों वाले तथा स्पष्ट स्थिति की आवश्यकता रखने वाले प्रवाह के लिए ऑर्केस्ट्रेशन चुनिए।

घटनाएँ बनाम आदेश

अपने संदेशों के नाम सोच-समझकर रखिए:

  • कोई घटना अतीत में घटित तथ्य बताती है: OrderPlaced। प्रकाशक को परवाह नहीं होती कि कौन सुन रहा है।
  • कोई आदेश किसी विशिष्ट हैंडलर से भविष्य की कार्रवाई करने का अनुरोध करता है: ChargeCard।

घटनाएँ कोरियोग्राफी चलाती हैं; आदेश ऑर्केस्ट्रेशन चलाते हैं। शब्दावली को मिलाना — ऐसा "घटना" संदेश जो गुप्त रूप से केवल एक हैंडलर की अपेक्षा करता हो — छिपे हुए जुड़ाव का सामान्य स्रोत है।

<?php
final class OrderPlaced {
    public function __construct(
        public readonly string $orderId,
        public readonly string $customerId,
        public readonly int $amountCents,
        public readonly string $occurredAt,
    ) {}
}

$e = new OrderPlaced('o-42', 'c-7', 1990, gmdate('c'));
echo json_encode($e), "\n";

दोहरी-लेखन की समस्या

क्लासिक त्रुटि यह है: कोई हैंडलर डेटाबेस को अद्यतन करता है और संदेश प्रकाशित करता है, लेकिन इन दोनों को अलग-अलग कार्रवाइयों के रूप में करता है। यदि प्रक्रिया इनके बीच में बंद हो जाए, तो असंगति पैदा होती है — पंक्ति बदल जाती है लेकिन कोई घटना नहीं भेजी जाती, या इसका उलटा होता है।

<?php
// BROKEN: not atomic. A crash between the two lines corrupts state.
function placeOrder(PDO $db, $broker, array $o): void {
    $db->prepare('INSERT INTO orders ...')->execute($o);
    // <-- crash here = row exists but no event ever published
    $broker->publish('OrderPlaced', json_encode($o));
}

लेन-देन संबंधी आउटबॉक्स

इसका समाधान आउटबॉक्स प्रतिरूप है: आपके डेटा में बदलाव करने वाले उसी डेटाबेस लेन-देन के भीतर घटना को outbox तालिका में डालिए। एक अलग रिले प्रक्रिया अप्रकाशित पंक्तियों को पढ़ती है और उन्हें ब्रोकर तक भेजती है। एक परमाणु कमिट, कोई दोहरा लेखन नहीं।

<?php
function placeOrder(PDO $db, array $o): void {
    $db->beginTransaction();
    $db->prepare('INSERT INTO orders (id, total) VALUES (?, ?)')
       ->execute([$o['id'], $o['total']]);
    // Same transaction -> atomic with the business write
    $db->prepare('INSERT INTO outbox (id, type, payload) VALUES (?, ?, ?)')
       ->execute([bin2hex(random_bytes(8)), 'OrderPlaced', json_encode($o)]);
    $db->commit();
}

रिले (प्रकाशक)

कोई कार्यकर्ता आउटबॉक्स से बार-बार पूछताछ करता है (या CDC के माध्यम से डेटाबेस के बदलाव लॉग का अनुसरण करता है), प्रत्येक पंक्ति को प्रकाशित करता है और फिर उसे भेजी हुई के रूप में चिह्नित करता है। क्योंकि the रिले प्रकाशन के बाद लेकिन चिह्नित करने से पहले बंद हो सकता है, इसलिए वह स्वयं कम-से-कम-एक-बार व्यवहार करता है — यह ठीक है, क्योंकि उपभोक्ता पुनरावृत्ति-सुरक्षित होते हैं।

<?php
function relayOutbox(PDO $db, $broker): void {
    $rows = $db->query(
        'SELECT id, type, payload FROM outbox
         WHERE published_at IS NULL ORDER BY created_at LIMIT 100'
    )->fetchAll(PDO::FETCH_ASSOC);

    foreach ($rows as $r) {
        $broker->publish($r['type'], $r['payload'], messageId: $r['id']);
        $db->prepare('UPDATE outbox SET published_at = now() WHERE id = ?')
           ->execute([$r['id']]);
    }
}

पुनरावृत्ति-सुरक्षित उपभोक्ता (फिर से)

क्योंकि रिले और ब्रोकर दोनों कम-से-कम-एक-बार व्यवहार करते हैं, इसलिए आगे के हैंडलर को दोहराए हुए संदेश ज़रूर दिखाई देंगे। प्रत्येक उपभोक्ता अपने द्वारा संसाधित संदेश की आईडी दर्ज करता है और दोहराव को तुरंत छोड़ देता है — वही दोहराव-रोधक द्वार जिसे आपने पहले सीखा था, अब प्रत्येक सेवा पर लागू किया गया है।

<?php
function onOrderPlaced(PDO $db, string $messageId, array $data): void {
    $db->beginTransaction();
    try {
        $db->prepare('INSERT INTO inbox (message_id) VALUES (?)')
           ->execute([$messageId]); // unique index = dedup
    } catch (PDOException $e) {
        $db->rollBack();
        return; // already handled this message
    }
    reserveStock($data['orderId']);
    $db->commit();
}
function reserveStock(string $id): void {}

सागा: वितरित वापसी-प्रक्रिया

आप सेवाओं के बीच एक ACID लेन-देन नहीं खोल सकते। कोई सागा लंबे समय तक चलने वाले प्रवाह को स्थानीय लेन-देन की एक शृंखला के रूप में दर्शाता है, जहाँ प्रत्येक लेन-देन के साथ उसे पूर्ववत करने वाली क्षतिपूरक कार्रवाई होती है। यदि चरण 3 विफल हो जाए, तो चरण 2 और 1 की क्षतिपूरक कार्रवाइयाँ उलटे क्रम में चलाइए।

उदाहरण: स्टॉक आरक्षित होने के बाद भुगतान विफल हो जाता है → क्षतिपूर्ति के लिए ReleaseStock भेजिए। कोई स्वचालित वापसी-प्रक्रिया नहीं होती — आपको प्रत्येक चरण के लिए उसे पूर्ववत करने की कार्रवाई स्वयं तय करनी होती है।

ऑर्केस्ट्रेटेड सागा

ऑर्केस्ट्रेटर सागा को चलाता है: सफलता पर उसे आगे बढ़ाता है और विफलता पर क्षतिपूरक कार्रवाइयाँ भेजता है। सागा की स्थिति को स्थायी रूप से सहेजिए, ताकि प्रक्रिया बंद होने पर उसे वहीं से फिर शुरू किया जा सके।

<?php
function handleStepResult(array $saga, string $step, bool $ok, $bus): array {
    if ($ok) {
        $next = ['reserveStock' => 'chargeCard', 'chargeCard' => 'ship'][$step] ?? null;
        if ($next) { $bus->send($next, $saga['orderId']); $saga['state'] = $next; }
        else { $saga['state'] = 'completed'; }
    } else {
        // Run compensations in reverse for whatever already succeeded
        foreach (array_reverse($saga['done']) as $s) {
            $bus->send('compensate.' . $s, $saga['orderId']);
        }
        $saga['state'] = 'compensating';
    }
    return $saga;
}

दीर्घ प्रवाहों में समय-सीमाएँ

सागा का कोई चरण कभी वापस सूचना न दे — भुगतान सेवा बंद हो सकती है या मानव अनुमोदन कभी नहीं मिल सकता। समय-सीमा के बिना सागा हमेशा के लिए अटक जाता है और आरक्षण रोके रखता है। प्रत्येक चरण के लिए अंतिम समय-सीमा स्थायी रूप से सहेजिए; कोई समय-निर्धारक समय-सीमा पार कर चुके सागा को खोजकर विफलता और क्षतिपूर्ति वाला मार्ग शुरू करे।

<?php
function reapTimedOutSagas(PDO $db, $bus): void {
    $rows = $db->query(
        "SELECT order_id, state FROM sagas
         WHERE state NOT IN ('completed','compensating')
           AND deadline_at < now()"
    )->fetchAll(PDO::FETCH_ASSOC);

    foreach ($rows as $r) {
        echo "Saga {$r['order_id']} timed out at step {$r['state']}\n";
        $bus->send('saga.compensate', $r['order_id']); // trigger rollback
    }
}

संस्करण-प्रबंधन और अवलोकनीयता

कार्यप्रवाह वर्षों तक चलते हैं; इसलिए घटनाओं को सुरक्षित ढंग से विकसित करना आवश्यक है:

  • हर घटना में version (या स्कीमा) जोड़ें; उपभोक्ता नए अज्ञात फ़ील्ड को सहन करें और कभी यह न मानें कि कोई फ़ील्ड अवश्य मौजूद होगा।
  • वृद्धिशील बदलावों को प्राथमिकता दें; किसी मौजूदा फ़ील्ड के अर्थ को कभी न बदलें।
  • हर संदेश में सहसंबंध पहचानकर्ता आगे भेजें, ताकि लॉग और अनुरेखण में सभी सेवाओं के बीच एक व्यावसायिक लेन-देन का पता लगाया जा सके।

सहसंबंध पहचानकर्ताओं के बिना, पाँच सेवाओं में फैले कार्य-समन्वित प्रवाह की गड़बड़ी ठीक करना लगभग असंभव है।

<?php
$envelope = [
    'type'          => 'OrderPlaced',
    'version'       => 2,
    'correlationId' => $incoming['correlationId'] ?? bin2hex(random_bytes(8)),
    'occurredAt'    => gmdate('c'),
    'data'          => ['orderId' => 'o-42'],
];
echo json_encode($envelope, JSON_PRETTY_PRINT), "\n";

त्वरित जाँच

दोहरी-लेखन की समस्या से बचना।

पुनरावलोकन

अब आप विश्वसनीय घटना-संचालित कार्यप्रवाहों की रूपरेखा बना सकते हैं:

  • प्रत्येक प्रवाह की जटिलता के अनुसार कार्य-समन्वय (घटनाएँ) या अध्यादेश-निर्देशन (आदेश) चुनें।
  • लेन-देनात्मक आउटबॉक्स और एक रिले की सहायता से दोहरी-लेखन की समस्या हल करें।
  • इनबॉक्स/डुप्लिकेट-रोधक कुंजी के माध्यम से प्रत्येक उपभोक्ता को इडेम्पोटेंट बनाएँ।
  • वितरित रोलबैक के लिए प्रतिपूरक कार्रवाइयों के साथ सागा का उपयोग करें।
  • घटनाओं का संस्करण वृद्धिशील रूप से बढ़ाएँ और पता लगाने योग्य बनाने के लिए सहसंबंध पहचानकर्ता को हर संदेश-श्रृंखला में आगे भेजें।

ये प्रतिरूप बिखरे हुए संदेशों को भरोसेमंद और अवलोकनीय व्यावसायिक प्रक्रियाओं में बदल देते हैं।

शुरुआत निःशुल्क

एआई शिक्षक के साथ PHP सीखें — निःशुल्क

अपने ब्राउज़र में वास्तविक कोड लिखें और चलाएँ, चौबीसों घंटे एआई शिक्षक से तुरंत सहायता पाएँ, और वेब या ऐप पर वहीं से शुरू करें जहाँ आपने छोड़ा था।

पाठ्यक्रम
49
पाठ
195

अक्सर पूछे जाने वाले प्रश्न

क्या “इवेंट-ड्रिवन वर्कफ़्लो बनाना” पाठ निःशुल्क है?

हाँ—“इवेंट-ड्रिवन वर्कफ़्लो बनाना” का पूरा पाठ यहाँ वेब पर निःशुल्क पढ़ा जा सकता है। इंटरैक्टिव अभ्यास (अंतर्निहित कोड संपादक और 24/7 एआई ट्यूटर) करने और PHP Academy पाठ्यक्रम का बाकी हिस्सा अनलॉक करने के लिए CoddyKit PRO लें। PHP Academy पाठ्यक्रम में कुल 4 पाठ शामिल हैं।

“इवेंट-ड्रिवन वर्कफ़्लो बनाना” में मैं क्या सीखूँगा?

इवेंट और इडेम्पोटेंसी के माध्यम से सेवाओं का समन्वय करें। आप ब्राउज़र में सीधे चलाए जाने वाले व्यावहारिक कोड के साथ PHP Academy का अभ्यास करते हैं, और पाठ पूरा करते समय 24/7 एआई ट्यूटर आपके प्रश्नों के उत्तर देता है।

क्या PHP Academy शुरू करने के लिए मुझे किसी अनुभव की आवश्यकता है?

पहले के अनुभव की आवश्यकता नहीं है। CoddyKit पर PHP Academy शुरुआती से लेकर उन्नत शिक्षार्थियों तक सभी के लिए व्यवस्थित किया गया है, इसलिए आप यहीं से या शुरुआत से सीखना शुरू कर सकते हैं और अपनी गति से आगे बढ़ सकते हैं। यह 4 में से 4वाँ पाठ है।

“इवेंट-ड्रिवन वर्कफ़्लो बनाना” पाठ पूरा करने में कितना समय लगता है?

CoddyKit का अधिकांश पाठ लगभग 5–10 मिनट में पूरा हो जाता है। हर पाठ छोटा और संवादात्मक है, इसलिए आप लगातार प्रगति करते हैं और वेब या ऐप पर वहीं से सीखना जारी रख सकते हैं जहाँ आपने छोड़ा था।

क्या मैं इस PHP Academy पाठ में कोड लिख और चला सकता हूँ?

हाँ। हर PHP Academy पाठ में एक अंतर्निर्मित कोड संपादक शामिल है, जिससे आप सीधे अपने ब्राउज़र में वास्तविक कोड लिख और चला सकते हैं और तुरंत एआई प्रतिक्रिया पा सकते हैं—स्थानीय सेटअप की आवश्यकता नहीं है।

इस पाठ्यक्रम के सभी पाठ

  1. अतुल्यकालिक संदेश क्यों
  2. PHP में RabbitMQ के साथ काम करना
  3. PHP के साथ Apache Kafka
  4. इवेंट-ड्रिवन वर्कफ़्लो बनाना
← PHP Academy पर वापस जाएँ