बड़े सिस्टम और लंबे समय तक चलने वाले बैकग्राउंड जॉब्स के लिए बिल्डिंग।
क्रेडिट: इलियास चेब्बी ऑन अनस्प्लैशकुछ महीने पहले, मैंने मीडिया (ऑडियो) स्ट्रीमिंग के लिए इंफ्रास्ट्रक्चर बनाने की भूमिका निभाई। लेकिन ऑडियो को स्ट्रीमेबल चंक्स के रूप में सर्व करने के अलावा, लंबे समय तक चलने वाले मीडिया प्रोसेसिंग जॉब्स और एक व्यापक RAG पाइपलाइन थी जो ट्रांसक्रिप्शन, ट्रांसकोडिंग, एम्बेडिंग और क्रमिक मीडिया अपडेट्स के लिए थी। प्रोडक्शन माइंडसेट के साथ एक MVP बनाने के लिए हमें एक निर्बाध सिस्टम प्राप्त करने तक पुनरावृत्ति करनी पड़ी। हमारा दृष्टिकोण ऐसा रहा है जहां हमने फीचर्स और प्राथमिकताओं के अंतर्निहित स्टैक को एकीकृत किया है।
निर्माण के दौरान, प्रत्येक पुनरावृत्ति तत्काल और अक्सर "व्यापक" आवश्यकता के जवाब में आई। प्रारंभिक चिंता जॉब्स को कतारबद्ध करना था, जो Redis के साथ आसानी से पर्याप्त था; हमने बस फायर किया और भूल गए। NEST JS फ्रेमवर्क में Bull MQ ने हमें रिट्राई, बैकलॉग और डेड-लेटर क्यू पर और भी बेहतर नियंत्रण दिया। स्थानीय रूप से और प्रोडक्शन में कुछ पेलोड के साथ, हमने मीडिया प्रवाह को सही किया। हम जल्द ही ऑब्जर्वेबिलिटी के बोझ से दब गए:
लॉग्स → जॉब्स का रिकॉर्ड (अनुरोध, प्रतिक्रियाएं, त्रुटियां)।
मेट्रिक्स → कितना / कितनी बार ये जॉब्स चलते हैं, फेल होते हैं, पूरे होते हैं, आदि।
ट्रेसेस → एक जॉब ने सेवाओं में कौन सा पथ लिया (फ्लो पथ के भीतर कॉल किए गए फंक्शन/मेथड्स)।
आप इनमें से कुछ को API डिजाइन करके और उन्हें प्लग करने के लिए एक कस्टम डैशबोर्ड बनाकर हल कर सकते हैं, लेकिन स्केलेबिलिटी की समस्या पर्याप्त होगी। और वास्तव में, हमने API डिजाइन की।
जटिल, लंबे समय तक चलने वाले बैकएंड वर्कफ्लो को प्रबंधित करने की चुनौती, जहां विफलताओं को रिकवरेबल होना चाहिए, और स्टेट को टिकाऊ होना चाहिए, Inngest हमारा आर्किटेक्चरल उद्धार बन गया। इसने मूल रूप से हमारे दृष्टिकोण को पुनर्गठित किया: प्रत्येक लंबे समय तक चलने वाला बैकग्राउंड जॉब एक बैकग्राउंड फंक्शन बन जाता है, जो एक विशिष्ट इवेंट द्वारा ट्रिगर होता है।
उदाहरण के लिए, एक Transcription.request इवेंट एक TranscribeAudio फंक्शन को ट्रिगर करेगा। इस फंक्शन में fetch_audio_metadata, deepgram_transcribe, parse_save_trasncription, और notify_user के लिए स्टेप-रन्स हो सकते हैं।
कोर ड्यूरेबिलिटी प्रिमिटिव स्टेप-रन्स हैं। एक बैकग्राउंड फंक्शन आंतरिक रूप से इन स्टेप-रन्स में विभाजित होता है, प्रत्येक में न्यूनतम, परमाणु लॉजिक का ब्लॉक होता है।
Inngest फंक्शन अब्स्ट्रैक्ट:
import { inngest } from 'inngest-client';
export const createMyFunction = (dependencies) => {
return inngest.createFunction(
{
id: 'my-function',
name: 'My Example Function',
retries: 3, // retry the entire run on failure
concurrency: { limit: 5 },
onFailure: async ({ event, error, step }) => {
// handle errors here
await step.run('handle-error', async () => {
console.error('Error processing event:', error);
});
},
},
{ event: 'my/event.triggered' },
async ({ event, step }) => {
const { payload } = event.data;
// Step 1: Define first step
const step1Result = await step.run('step-1', async () => {
// logic for step 1
return `Processed ${payload}`;
});
// Step 2: Define second step
const step2Result = await step.run('step-2', async () => {
// logic for step 2
return step1Result + ' -> step 2';
});
// Step N: Continue as needed
await step.run('final-step', async () => {
// finalization logic
console.log('Finished processing:', step2Result);
});
return { success: true };
},
);
};
Inngest का इवेंट-ड्रिवन मॉडल हर वर्कफ्लो एक्जीक्यूशन में ग्रैन्युलर इनसाइट प्रदान करता है:
शुद्ध इवेंट प्रोसेसिंग पर निर्भर रहने का कैवेट यह है कि जबकि Inngest कुशलतापूर्वक फंक्शन एक्जीक्यूशन को कतारबद्ध करता है, इवेंट्स स्वयं आंतरिक रूप से कतारबद्ध नहीं होते पारंपरिक मैसेजिंग ब्रोकर के अर्थ में। एक स्पष्ट इवेंट क्यू की यह अनुपस्थिति हाई-ट्रैफिक परिदृश्यों में समस्याग्रस्त हो सकती है, संभावित रेस कंडीशन्स या ड्रॉप्ड इवेंट्स के कारण यदि इंजेस्शन एंडपॉइंट ओवरव्हेल्म हो जाता है।
इसे संबोधित करने और सख्त इवेंट ड्यूरेबिलिटी लागू करने के लिए, हमने एक समर्पित क्यूइंग सिस्टम को एक बफर के रूप में लागू किया।
AWS सिंपल क्यू सिस्टम (SQS) हमारी पसंद का सिस्टम था (हालांकि कोई भी मजबूत क्यूइंग सिस्टम संभव है), हमारे मौजूदा AWS इंफ्रास्ट्रक्चर को देखते हुए। हमने एक दो-क्यू सिस्टम की योजना बनाई: एक मेन क्यू और एक डेड लेटर क्यू (DLQ)।
हमने एक इलास्टिक बीनस्टॉक (EB) वर्कर एनवायरनमेंट स्थापित किया जो विशेष रूप से मेन क्यू से सीधे संदेशों का उपभोग करने के लिए कॉन्फ़िगर किया गया था। यदि मेन क्यू में कोई संदेश EB वर्कर द्वारा निर्धारित संख्या में बार प्रोसेस करने में विफल रहता है, तो मेन क्यू स्वचालित रूप से विफल संदेश को समर्पित DLQ में स्थानांतरित कर देता है। यह सुनिश्चित करता है कि कोई भी इवेंट स्थायी रूप से खो नहीं जाता है यदि वह ट्रिगर करने या Inngest द्वारा उठाए जाने में विफल रहता है। यह वर्कर एनवायरनमेंट एक मानक EB वेब सर्वर एनवायरनमेंट से भिन्न है, क्योंकि इसकी एकमात्र जिम्मेदारी संदेश उपभोग और प्रोसेसिंग है (इस मामले में, उपभोग किए गए संदेश को Inngest API एंडपॉइंट पर अग्रेषित करना)।
एंटरप्राइज-स्केल इंफ्रास्ट्रक्चर बनाने का एक अनकहा और बहुत प्रासंगिक हिस्सा यह है कि यह संसाधनों का उपभोग करता है, और वे लंबे समय तक चलने वाले हैं। माइक्रोसर्विसेज आर्किटेक्चर प्रति सेवा स्केलेबिलिटी प्रदान करता है। स्टोरेज, RAM और संसाधनों के टाइमआउट महत्वपूर्ण हो जाएंगे। उदाहरण के लिए, AWS इंस्टेंस टाइप के लिए हमारी विशिष्टता जल्दी से t3.micro से t3.small तक चली गई, और अब t3.medium पर तय है। लंबे समय तक चलने वाले, CPU-इंटेंसिव बैकग्राउंड जॉब्स के लिए, छोटे इंस्टेंस के साथ हॉरिजॉन्टल स्केलिंग विफल हो जाती है क्योंकि बॉटलनेक एक सिंगल जॉब को प्रोसेस करने में लगने वाला समय है, न कि क्यू में प्रवेश करने वाले नए जॉब्स की मात्रा।
जॉब्स या फंक्शन्स जैसे ट्रांसकोडिंग, एम्बेडिंग आमतौर पर CPU-बाउंड और मेमोरी-बाउंड होते हैं। CPU-बाउंड क्योंकि उन्हें निरंतर, तीव्र CPU उपयोग की आवश्यकता होती है, और मेमोरी-बाउंड क्योंकि उन्हें अक्सर बड़े मॉडल लोड करने या बड़ी फाइलों या पेलोड को कुशलतापूर्वक संभालने के लिए पर्याप्त RAM की आवश्यकता होती है।
अंततः, यह वर्धित आर्किटेक्चर, SQS की ड्यूरेबिलिटी और EB वर्कर एनवायरनमेंट के नियंत्रित एक्जीक्यूशन को सीधे Inngest API के अपस्ट्रीम रखते हुए, आवश्यक रेजिलिएंसी प्रदान की। हमने सख्त इवेंट ओनरशिप हासिल की, ट्रैफिक स्पाइक्स के दौरान रेस कंडीशन्स को समाप्त किया, और एक नॉन-वोलेटाइल डेड लेटर मैकेनिज्म प्राप्त किया। हमने अपने वर्कफ्लो ऑर्केस्ट्रेशन और डीबगिंग क्षमताओं के लिए Inngest का लाभ उठाया, जबकि अधिकतम मैसेज थ्रूपुट और ड्यूरेबिलिटी के लिए AWS प्रिमिटिव्स पर निर्भर रहे। परिणामी सिस्टम न केवल स्केलेबल है बल्कि अत्यधिक ऑडिटेबल है, जटिल, लंबे समय तक चलने वाले बैकएंड जॉब्स को सुरक्षित, ऑब्जर्वेबल और फेल्योर-टॉलरेंट माइक्रो-स्टेप्स में सफलतापूर्वक अनुवादित करता है।
सर्मन्स के लिए स्पॉटिफाई बनाना। मूल रूप से मीडियम पर कॉइनमोंक्स में प्रकाशित किया गया था, जहां लोग इस कहानी को हाइलाइट करके और उस पर प्रतिक्रिया देकर बातचीत जारी रख रहे हैं।


