ترقی کے مرحلے پر، سائن اپ اختتامی نقطہ ٹھیک نظر آتا ہے۔ صارف رجسٹر کرتا ہے، قطار کو محفوظ کرتا ہے، اپنے ای میل فراہم کنندہ کو کال کرتا ہے، اور واپس آتا ہے۔ 201 Created. ہر ایک کو خوش آمدید ای میل موصول ہوتا ہے۔ آپ اسے بھیج دیں۔
پھر پروڈکشن ٹریفک آتا ہے۔
ای میل API 200 ملی سیکنڈ کے بجائے 2 سیکنڈ لیتا ہے۔ کئی درخواستوں کا وقت ختم ہو گیا۔ فراہم کنندہ کی بندش کے دوران، تمام سبسکرپشنز واپس آنا شروع ہو جائیں گی۔ 500. سپورٹ پوچھتا ہے کہ صارف اکاؤنٹ کیوں بنا سکتا ہے لیکن تصدیقی لنک حاصل نہیں کرتا ہے۔
بگ ای میل ٹیمپلیٹ نہیں ہے۔ بگ وہ جگہ ہے جہاں میں نے ای میل بھیجنے کا فیصلہ کیا۔
اس آرٹیکل میں، آپ یہ سیکھیں گے کہ HTTP درخواست کے راستے میں ای میلز بھیجنا ایک پروڈکشن ٹریپ کیوں ہے، جب آپ اسکیل کرتے ہیں تو کیا غلط ہوتا ہے، اور اپنے API کو تیز اور قابل اعتماد رکھنے کے لیے ای میلز (اور دیگر ضمنی اثرات) کو بیک گراؤنڈ ٹاسک کیو میں کیسے منتقل کیا جائے۔
شرطیں
اگر آپ مندرجہ ذیل جانتے ہیں، تو آپ کو اس مضمون میں مزید معلومات ملیں گی:
-
REST APIs کیسے کام کرتے ہیں (درخواستیں، جوابات، اسٹیٹس کوڈز)
-
مقامی Node.js یا کوئی بھی بیک اینڈ زبان جو ای میل API کو کال کر سکتی ہے۔
-
ایک اعلی سطحی پس منظر کا کام یا قطار کیا ہے؟
BullMQ، Redis، یا کسی مخصوص ای میل فراہم کنندہ کے ساتھ کسی پیشگی تجربے کی ضرورت نہیں ہے۔
انڈیکس
1. "درخواست کے اندر” کا اصل مطلب کیا ہے۔
جب کلائنٹ API تک پہنچ جاتا ہے، درخواست کا راستہ وہ سب کچھ ہوتا ہے جسے HTTP جواب بھیجنے سے پہلے مکمل کرنے کی ضرورت ہوتی ہے۔
اس میں عام طور پر شامل ہیں:
-
ان پٹ کی توثیق ہو رہی ہے۔
-
تصدیق کی توثیق کی جا رہی ہے۔
-
ڈیٹا بیس پر لکھیں
-
JSON واپس کریں۔
مندرجہ ذیل کو شاذ و نادر ہی شامل کیا جانا چاہئے:
-
SMTP سرور کو کال کریں۔
-
دوبارہ بھیجنے، SendGrid، SES، Mailgun یا پوسٹ مارک کا انتظار کر رہے ہیں۔
-
بڑے HTML ٹیمپلیٹس پیش کریں اور منسلکات اپ لوڈ کریں۔
-
غیر مستحکم تھرڈ پارٹی نیٹ ورک کالز کی دوبارہ کوشش کی جا رہی ہے۔
آپ کا ای میل فراہم کنندہ ایک بیرونی نظام ہے۔ اس کی اپنی تاخیر، رفتار کی حدیں اور بندشیں ہیں۔ اگر API ان کا انتظار کرتا ہے، تو ان کا مسئلہ صارف کا مسئلہ بن جاتا ہے۔
Bad path (synchronous):
Client ──▶ API ──▶ Database ──▶ Email provider ──▶ Client
▲
└── user waits for all of this
2. موہک کوڈ جو مسائل کا سبب بنتا ہے۔
یہ وہ نمونہ ہے جس سے زیادہ تر ٹیمیں شروع کرتی ہیں: یہ واضح، مختصر اور میرے لیپ ٹاپ پر کام کرتا ہے۔
app.post('/signup', async (c) => {
const body = await c.req.json();
const user = await db.users.create({
email: body.email,
passwordHash: await hash(body.password),
});
// This is the trap.
await emailClient.send({
to: user.email,
subject: 'Confirm your account',
html: renderConfirmEmail(user),
});
return c.json({ id: user.id }, 201);
});
آپ کی درخواست اس وقت تک مکمل نہیں ہو سکتی جب تک کہ آپ کا ای میل فراہم کنندہ جواب نہیں دیتا۔ اگر کال سست ہے تو جواب بھی سست ہوگا۔ جب وہ کال ہوتی ہے، تو سائن اپ یا تو ناکام ہو جائے گا یا ہمیں ایک غلطی نظر آئے گی اور خود بخود ای میل کو چھوڑ دیں گے۔
کوئی بھی آپشن اچھا نہیں ہے۔
3. پیداوار کیوں رک جاتی ہے؟
آپ کے جواب کا وقت کسی اور کا SLA بن جاتا ہے۔
ایک صحت مند سبسکرپشن اینڈ پوائنٹ کو اکثر دسیوں یا سینکڑوں ملی سیکنڈ کے اندر جواب دینے کی ضرورت ہوتی ہے۔ ای میل APIs کو عام طور پر اس سے زیادہ وقت لگتا ہے۔ اگر بوجھ ہے تو اس میں زیادہ وقت لگے گا۔
p95 لیٹنسی اب کوڈ کی ملکیت نہیں ہے۔ راستے پر سب سے سست تھرڈ پارٹی کال کی ملکیت۔
ناکامی بدصورت تجارت پیدا کرتی ہے۔
اگر send() جب آپ پھینکتے ہیں، تو آپ کے پاس دو برے انتخاب ہوتے ہیں۔
-
پوری درخواست ناکام ہوجاتی ہے: صارف کو غلطی نظر آتی ہے چاہے اکاؤنٹ پہلے سے موجود ہو۔
-
غلطی کو نگل لیں: صارف بنایا گیا لیکن ای میل موصول نہیں ہوا۔
دوسری صورت خاص طور پر تصدیق یا پاس ورڈ دوبارہ ترتیب دینے کے دوران تکلیف دہ ہوتی ہے۔ ڈیٹا بیس کہتا ہے کامیابی، لیکن میرا ان باکس کچھ نہیں دکھاتا۔
ٹائم آؤٹ کاسکیڈنگ
API گیٹ ویز، لوڈ بیلنسرز، اور براؤزرز سبھی کا ٹائم آؤٹ ہوتا ہے۔ سست ای میل کالز ایک کامیاب کاروباری کوشش کو کلائنٹ کی طرف سے ناکامی میں بدل سکتی ہیں۔ صارف دوبارہ کوشش کرے گا۔ اب آپ ڈپلیکیٹ صارفین بنا سکتے ہیں یا ڈپلیکیٹ ای میل بھیج سکتے ہیں۔
رفتار کی حد کے ساتھ ٹریفک کے اضافے کو سزا دیں۔
ای میل فراہم کرنے والے رفتار کو محدود کرتے ہیں۔ پروڈکٹ لانچ، ڈائجسٹ، پاس ورڈ ری سیٹ سرجز وغیرہ سبھی ان حدود کو مار سکتے ہیں۔ جب کسی درخواست کے اندر منتقلی ہوتی ہے، تو شرح کو محدود کرنے والی غلطی صارف کو دکھائی جانے والی API کی خرابی بن جاتی ہے۔
صاف طور پر دوبارہ کوشش نہیں کر سکتے
پس منظر کے کاموں کو بیک آف کے ساتھ دوبارہ آزمایا جا سکتا ہے۔ HTTP درخواستیں نہیں کی جا سکتی ہیں۔ جواب واپس کرنے سے درخواست ختم ہوجاتی ہے۔ اگر آپ کا ای میل ناکام ہوجاتا ہے اور آپ نے پہلے ہی کلائنٹ کو اس کی "کامیابی” کے بارے میں مطلع کر دیا ہے، تو آپ کو اس سے بازیافت کرنے کے لیے ایک اور سسٹم کی ضرورت ہوگی۔ وہ نظام ایک قطار ہے۔
What the user experiences during a provider slowdown:
Signup click
│
▼
API waits on email provider .............. 2s ... 5s ... timeout
│
▼
"Something went wrong"
│
▼
User clicks again → duplicate attempts, confused support tickets
4. قاعدہ: APIs کو قطار میں ہونا چاہیے، آپریشنز نہیں کرنا چاہیے۔
ای میل کو ایک غیر مطابقت پذیر آپریشن کے طور پر سمجھیں جو ہونا ضروری ہے۔ کیونکہ درخواست نہیں اندر درخواست
درخواست کا راستہ ہونا چاہئے:
-
ان پٹ کی توثیق کریں
-
کاروباری تبدیلیوں کا ارتکاب
-
ای میل کی وضاحت کرنے کے لیے قطار میں ایک کام شامل کریں۔
-
جلدی واپس آجاؤ
دوسرے مقامات پر کام کرنے والوں کو:
-
ایک کام کا انتخاب کریں
-
رینڈر ٹیمپلیٹ
-
اپنے ای میل فراہم کنندہ کو کال کریں۔
-
ناکامی پر دوبارہ کوشش کریں۔
-
نتائج ریکارڈ کریں
Good path (asynchronous):
Client ──▶ API ──▶ Database ──▶ Queue ──▶ Client (fast response)
│
▼
Worker ──▶ Email provider
یہ وہی خیال ہے جیسے اپ لوڈز پر کارروائی کرنا، پی ڈی ایف بنانا، AI APIs کو کال کرنا، یا ڈیٹا کو آپ کے CRM سے ہم آہنگ کرنا۔ ای میل صرف سب سے عام مثال ہے۔
5. ای میلز کو پس منظر کی قطار میں کیسے منتقل کیا جائے۔
BullMQ اور Redis کا استعمال کرتے ہوئے کم سے کم Node.js کیسا لگتا ہے: عین لائبریری اس کی حدود سے کم اہم ہے۔
ملازمت کی تعریف
// jobs/email.ts
export type SendEmailJob = {
to: string;
template: 'confirm-account' | 'password-reset' | 'welcome';
variables: Record;
idempotencyKey: string;
};
API سے قطار میں شامل کریں۔
import { emailQueue } from '../queues/email-queue';
app.post('/signup', async (c) => {
const body = await c.req.json();
const user = await db.users.create({
email: body.email,
passwordHash: await hash(body.password),
});
await emailQueue.add(
'send-email',
{
to: user.email,
template: 'confirm-account',
variables: {
name: user.name,
confirmUrl: `https://example.com/confirm/${user.confirmToken}`,
},
idempotencyKey: `confirm-account:${user.id}`,
},
{
jobId: `confirm-account:${user.id}`,
attempts: 5,
backoff: { type: 'exponential', delay: 2000 },
removeOnComplete: 1000,
removeOnFail: 5000,
},
);
return c.json({ id: user.id }, 201);
});
غور کریں کہ کیا بدلا ہے۔ API اب بھی صارفین تخلیق کرتا ہے۔ SMTP کا مزید انتظار نہیں کرنا۔ Redis کے آپریشن کو قبول کرنے کا انتظار کریں۔ یہ عام طور پر آپ کے ای میل فراہم کنندہ کا انتظار کرنے سے کہیں زیادہ سستا اور زیادہ متوقع ہوتا ہے۔
کارکنوں میں پروسیسنگ کام
// worker/email-worker.ts
import { Worker } from 'bullmq';
import { emailClient } from '../lib/email-client';
import { renderTemplate } from '../lib/templates';
new Worker(
'email',
async (job) => {
const { to, template, variables } = job.data;
await emailClient.send({
to,
subject: subjectFor(template),
html: renderTemplate(template, variables),
});
},
{
connection: redisConnection,
concurrency: 5,
},
);
کارکن کو API سے الگ عمل کے طور پر چلائیں۔ اس کی وجہ سے ای میل کی بندش کارکنوں کو سست کرے گی، لیکن تمام HTTP جوابات نہیں۔
صحیح حیثیت واپس کرتا ہے۔
سائن اپ کرنے کے لیے، 201 Created یہ تب تک درست ہے جب تک کہ آپ کا اکاؤنٹ موجود ہے اور آپ تصدیقی ای میل کا انتظار کر رہے ہیں۔
اختتامی نکات کے لیے جو صرف کارروائیوں کو متحرک کرتے ہیں، ہم ترجیح دیتے ہیں: 202 Accepted جب کلائنٹ کو پیشرفت کو ٹریک کرنے کی ضرورت ہو تو ٹاسک یا ڈیلیوری ID لوٹاتا ہے۔
6. دوبارہ کوششوں، ناکامیوں، اور بے حسی کو کیسے ہینڈل کیا جائے۔
صرف ای میلز کو قطار میں لے جانا کافی نہیں ہے۔ ہمیں ناکامی کے اصول کی بھی ضرورت ہے۔
عارضی غلطی کی دوبارہ کوشش کریں۔
نیٹ ورک کی خرابی، 429 Too Many Requestsاور 503 Service Unavailable آپ کو بیک آف کرکے دوبارہ کوشش کرنے کی ضرورت ہوگی۔ مسلسل غلطیاں، جیسے غلط وصول کنندگان، تیزی سے ناکام ہو جائیں گے اور ڈیڈ لیٹر قطار یا ناکام آپریشن ٹیبل میں دکھائی دیں گے۔
کاموں کو بے اختیار بنانا
ایک کارکن ایک سے زیادہ بار دوڑ سکتا ہے۔ مستحکم استعمال کریں۔ jobId یا idempotencyKey لہذا، دوبارہ کوشش کرنے کے نتیجے میں ایک رجسٹریشن کے لیے 5 خوش آمدید ای میلز نہیں بھیجے جائیں گے۔
ایک عملی نقطہ نظر:
-
کاروباری واقعات سے چابیاں حاصل کریں۔
confirm-account:user_123 -
اگر منتقلی کامیاب ہو جاتی ہے، تو ہم فراہم کنندہ کے پیغام کی شناخت کو محفوظ کر لیتے ہیں۔
-
اگر کلید پہلے سے گزر چکی ہے، تو آپریشن کو چھوڑ دیا جاتا ہے۔
کاروباری تقریب کو مت چھوڑیں۔
اگر کوئی عمل آپس میں متصادم ہو۔ db.users.create() اور emailQueue.add()آپ اپنا ای میل کھو سکتے ہیں۔
اس خطرے کو کم کرنے کے دو عمومی طریقے ہیں:
-
آؤٹ باکس پیٹرن: ای میل کا ارادہ
outboxصارف کی قطار کی طرح ڈیٹا بیس کے لین دین میں ایک ٹیبل۔ علیحدہ پبلشرز سے میل باکس پڑھیں اور قطار میں کام شامل کریں۔ -
اگر تعاون یافتہ ہو تو لین دین کی قطار شامل کریں۔: لکھنے اور اضافے کو جتنا ممکن ہو ایک دوسرے کے قریب رکھیں، اور چھوٹی ہوئی منتقلیوں کے لیے مصالحتی کارروائیاں چلائیں۔
بہت سی ایپس کے لیے، شروع کرنے کے لیے سادہ قطار اور نگرانی کافی ہے۔ اگر دفتر سے باہر ای میل ایک حقیقی قابل اعتماد ضرورت بن جاتی ہے، تو ایک آؤٹ باکس شامل کریں۔
فوری اور بلک ای میلز کو الگ کریں۔
پاس ورڈ ری سیٹ اور OTP ای میلز کو نیوز لیٹر کے دھماکوں کے پیچھے نہیں چھپایا جانا چاہیے۔
ترجیحی یا علیحدہ قطاریں استعمال کریں۔
-
اعلی ترجیح: OTP، پاس ورڈ ری سیٹ، تصدیق
-
عمومی ترجیح: رسیدیں، آن بورڈنگ
-
کم ترجیح: ڈائجسٹ، مارکیٹنگ
یہ صارفین کو تیز رفتاری سے ای میلز کو روکتا ہے یہاں تک کہ ہائی والیوم ٹریفک اسپائکس کے دوران بھی۔
7. ایک اور چیز جس کو درخواست کا راستہ چھوڑنے کی ضرورت ہے۔
اگر کوئی آپریشن تھرڈ پارٹی نیٹ ورک API کو کال کرتا ہے، تو اسے چند سو ملی سیکنڈ سے زیادہ وقت لگ سکتا ہے، یا دوبارہ کوشش کی ضرورت ہے، اسے درخواست کے راستے سے خارج کر دیں۔ یہ اس صورت میں بھی درست ہے اگر آپ کلیدی کاروباری کارروائیوں کو کالعدم کیے بغیر ناکام ہو سکتے ہیں، یا اگر آپ سی پی یو سے متعلق کام کر رہے ہیں جیسے کہ تصویر یا پی ڈی ایف بنانا۔
اس قسم کے کام کی کچھ عام مثالیں یہ ہیں:
APIs کو ارادے کو حل کرنا اور حالت کو برقرار رکھنا چاہیے۔ کارکنوں کو سست حصہ کرنا پڑتا ہے۔
8. عملی چیک لسٹ
ای میل بھیجنے کی صلاحیت فراہم کرنے سے پہلے، درج ذیل سوالات پوچھیں:
-
کیا صارف کو کامیابی دیکھنے سے پہلے ای میل کو مکمل کرنا ہوگا؟
-
اگر میرا ای میل فراہم کنندہ نیچے چلا جاتا ہے تو کیا اس اختتامی نقطہ سے سمجھوتہ کیا جا سکتا ہے؟
-
اگر ڈیٹا بیس لکھنے کے بعد ٹرانسفر ناکام ہو جائے تو میں کیسے بازیافت کروں؟
-
اگر کوئی ٹاسک دو بار چلتا ہے تو کیا صارفین کو ڈپلیکیٹ پیغامات نظر آئیں گے؟
-
کیا OTP اور پاس ورڈ دوبارہ ترتیب دینے والی ای میلز میں بلک ای میلز کے مقابلے تیز رفتار راستہ ہے؟
-
کیا میں لاگز، میٹرکس یا ڈیش بورڈز میں ناکام کاموں کو دیکھ سکتا ہوں؟
-
اگر قطار کی گہرائی یا ناکامی کی شرح بڑھ جاتی ہے تو کیا آپ اطلاعات فراہم کرتے ہیں؟
اگر آپ ان سوالات کا جواب نہیں دے سکتے ہیں، تو آپ کا ڈیزائن ابھی تک پیداوار کے لیے تیار نہیں ہے۔
نتیجہ
API کی درخواست کے اندر ای میل بھیجنا آپ کو فریق ثالث کے نظام سے جوڑتا ہے جس کے جوابی اوقات اور غلطی کی شرح آپ کے قابو سے باہر ہے۔ یہ ڈیمو میں آسان لگ سکتا ہے، لیکن پیداوار میں یہ مہنگا ہے.
ایک بہتر ڈیفالٹ آسان ہے:
-
کاروباری تبدیلیوں کا ارتکاب
-
ای میل کو قطار میں رکھیں
-
جلدی واپس آجاؤ
-
کارکنوں کو ناکامیوں کو بھیجنے، دوبارہ کوشش کرنے اور رپورٹ کرنے دیں۔
یہ نمونے آپ کے API کو تیز تر، ای میل کی ترسیل کو زیادہ قابل اعتماد، اور ناکامی کے طریقوں کا اندازہ لگانا بہت آسان بناتے ہیں۔
جب آپ اپنے ای میل پر سیگمنٹیشن کرتے ہیں، تو آپ کو ہر جگہ ایک جیسی حدود نظر آنے لگتی ہیں۔ اگر صارف انتظار نہیں کرتا ہے، تو یہ درخواست کا حصہ نہیں ہے۔