پالیسی دوبارہ کوشش — قواعد کا ایک مجموعہ جو یہ طے کرتا ہے کہ موبائل ایپلیکیشن خودکار طور پر ناکام نیٹ ورک کالز کو کب اور کیسے دہراتی ہے۔ غیر مستحکم کنکشن یا عارضی سرور کی خرابیوں کے ساتھ، ایک اچھی طرح ڈیزائن کردہ پالیسی دوبارہ کوشش صارف کی مداخلت کے بغیر ایپلیکیشن کی اعتمادیت کو بہتر بناتی ہے۔ Google Developer Relations (2025) کی تحقیق کے مطابق، پالیسی دوبارہ کوشش کا صحیح نفاذ بار بار نیٹ ورک آپریشن والی موبائل ایپلیکیشنز میں کھوئی ہوئی درخواستوں کے فیصد کو 40–60% تک کم کر دیتا ہے۔
اہم نکات
پالیسی دوبارہ کوشش — ایک سافٹ ویئر حکمت عملی جو نیٹ ورک کی درخواست کی ناکامی پر کلائنٹ کے رویے کی وضاحت کرتی ہے: کن خرابیوں کو دہرایا جانا چاہیے، کتنی بار، کس تاخیر سے، اور کب کوششیں روکنی چاہئیں۔ موبائل ایپلیکیشنز میں، موبائل نیٹ ورکس کی عدم استحکام اور ممکنہ عارضی سرور کی جانب سے ناکامیوں کی وجہ سے دوبارہ کوشش کی پالیسی انتہائی اہم ہے۔
ایک بنیادی پالیسی دوبارہ کوشش میں تین پیرامیٹرز شامل ہیں: دوبارہ کوشش کی زیادہ سے زیادہ تعداد (maxRetries)، ابتدائی تاخیر (baseDelay)، اور backoff حکمت عملی۔ اس کے علاوہ، HTTP اسٹیٹس کوڈز کی ایک فہرست متعین کی جا سکتی ہے جن پر دوبارہ کوشش کے ساتھ رد عمل ظاہر کرنا چاہیے، اور تمام کوششوں کو منسوخ کرنے کے لیے ایک ٹائم آؤٹ۔
مارٹن کلیپمین کی کتاب “Designing Data-Intensive Applications” کے مطابق، تقسیم شدہ نظاموں میں 50% ناکامیاں عارضی ہوتی ہیں اور دوبارہ کوشش سے حل ہو جاتی ہیں۔ یہ پالیسی دوبارہ کوشش کو سرور کے آرکیٹیکچر میں تبدیلی کے بغیر موبائل ایپلیکیشن کی خرابی برداشت کرنے کی صلاحیت کو بہتر بنانے کے سب سے مؤثر اور سستے طریقوں میں سے ایک بناتا ہے۔
عارضی خرابیاں (دوبارہ قابل کوشش) — واحد قسم کی ناکامی ہے جس پر پالیسی دوبارہ کوشش کو رد عمل ظاہر کرنا چاہیے۔ ان میں کنکشن ٹائم آؤٹ (SocketTimeoutException)، عارضی سرور غیر دستیابی (HTTP 503, 502)، اور DNS خرابیاں شامل ہیں۔ مستقل خرابیاں — HTTP 400, 401, 403, 404 — کو دہرانا بے معنی ہے کیونکہ وہ نیٹ ورک یا سرور میں نہیں بلکہ درخواست میں مسئلہ کی نشاندہی کرتی ہیں۔
AWS Architecture Blog کی تحقیق کے مطابق، خرابیوں کی دوبارہ قابل کوشش اور ناقابل دوبارہ کوشش میں درست درجہ بندی پالیسی دوبارہ کوشش کو ڈیزائن کرتے وقت سب سے اہم فیصلہ ہے۔ HTTP 401 پر ایک غیر idempotent درخواست کو دہرانے سے اکاؤنٹ لاک ہو سکتا ہے، اور HTTP 400 کو دہرانے سے ڈپلیکیٹ ڈیٹا بن سکتا ہے۔ ہمیشہ دوبارہ کوشش کے لیے کوڈز کی فہرست واضح طور پر کنفیگر کریں۔
مقررہ وقفہ — سب سے آسان حکمت عملی: ہر دوبارہ کوشش ایک ہی وقت کے وقفے کے بعد ہوتی ہے۔ مثال کے طور پر، 2 سیکنڈ کی تاخیر کے ساتھ، ایپلیکیشن 2، 2، 2 سیکنڈ کے بعد درخواست دہراتی ہے۔ مقررہ وقفہ لاگو کرنے میں آسان اور پیش گوئی کے قابل ہے، لیکن بڑے پیمانے پر ناکامیوں کے دوران سرور پر یکساں بوجھ پیدا کرتا ہے۔
بڑھتا ہوا وقفہ — ہر دوبارہ کوشش کے ساتھ تاخیر لکیری طور پر بڑھتی ہے: پہلی دوبارہ کوشش 1 سیکنڈ کے بعد، دوسری 2 کے بعد، تیسری 3 کے بعد، وغیرہ۔ یہ حکمت عملی بار بار ناکامیوں پر سرور کو ٹھیک ہونے کے لیے زیادہ وقت دیتی ہے، لیکن بیک وقت ناکام ہونے والے متعدد کلائنٹس کے لیے اب بھی پیش گوئی کے قابل ہے۔
| حکمت عملی | تاخیر کا فارمولا | مجموعی وقت (3 کوششیں) | استعمال |
|---|---|---|---|
| مقررہ | delay = D | 3 × D | سادہ منظرنامے، مقامی ٹائم آؤٹ |
| بڑھتا ہوا | delay = N × D | 6 × D | بتدریج بوجھ میں کمی |
| Exponential | delay = D × 2^N | 7 × D | بڑے پیمانے پر ناکامیاں، کلاؤڈ سروسز |
| Exponential + Jitter | delay = random(0, D × 2^N) | متغیر | زیادہ بوجھ، مائیکرو سروسز |
حکمت عملی کا انتخاب ایپلیکیشن کی نوعیت پر منحصر ہے۔ موبائل آلات پر ڈیٹا سنکرونائزیشن کے بیک گراؤنڈ کاموں کے لیے، jitter کے ساتھ exponential حکمت عملی بہترین ہے — یہ سرور اور صارف کے آلے پر کم سے کم بوجھ کے ساتھ کامیابی کا سب سے زیادہ امکان فراہم کرتی ہے۔
Exponential backoff — ایک حکمت عملی جس میں ہر کوشش کے ساتھ دوبارہ کوششوں کے درمیان تاخیر دوگنی ہو جاتی ہے۔ اگر ابتدائی تاخیر 1 سیکنڈ ہے، تو تاخیر کا سلسلہ 1، 2، 4، 8، 16 سیکنڈ ہوگا۔ یہ سرور کو تیزی سے بڑھتا ہوا بحالی کا وقت دیتا ہے۔
Jitter — بے ترتیب تاخیر کا انحراف جو متعدد کلائنٹس سے بیک وقت دوبارہ کوشش کی درخواستوں کو روکتا ہے (تھنڈرنگ ہرڈ مسئلہ)۔ Jitter کے بغیر، ایک ہی پالیسی دوبارہ کوشش والے ہزاروں کلائنٹ بیک وقت درخواستیں دہرائیں گے، جس سے سرور پر چوٹی کا بوجھ پیدا ہوگا۔ Jitter دوبارہ کوششوں کو وقت میں پھیلا دیتا ہے۔
Kotlin coroutines مرکزی تھریڈ کو روکے بغیر jitter کے ساتھ exponential backoff کو لاگو کرنے کی اجازت دیتے ہیں۔ kotlinx-coroutines کا retry فنکشن دوبارہ کوشش کی شرط اور درخواست کے باڈی کے ساتھ ایک بلاک لیتا ہے، خودکار طور پر تاخیر اور کوششوں کی تعداد کا انتظام کرتا ہے۔
suspend fun RetryPolicy.executeWithRetry(
block: suspend () -> Result<T>
): Result<T> {
var lastError: Throwable? = null
repeat(maxRetries + 1) { attempt ->
try {
return block()
} catch (e: Exception) {
if (!isRetriable(e) || attempt == maxRetries) {
return Result.failure(e)
}
val delay = (baseDelayMs * (1 shl attempt))
.toLong()
val jitteredDelay = (delay * (0.5 + Random.nextDouble())).toLong()
delay(jitteredDelay)
lastError = e
}
}
return Result.failure(lastError!!)
}
executeWithRetry فنکشن نیٹ ورک کال کے ساتھ ایک لیمبڈا لیتا ہے اور اسے exponential backoff اور jitter کے ساتھ انجام دیتا ہے۔ اگر خرابی دوبارہ قابل کوشش نہیں ہے یا زیادہ سے زیادہ کوششوں کی تعداد سے تجاوز کر گئی ہے، تو فنکشن ایک خرابی لوٹاتا ہے۔ دوبارہ کوششوں کی یکساں تقسیم کے لیے تاخیر کو 0.5 سے 1.5 کے بے ترتیب عنصر سے ضرب دیا جاتا ہے۔
Circuit Breaker — ایک ڈیزائن پیٹرن جو طویل سروس غیر دستیابی کے دوران لامتناہی دوبارہ کوشش کی درخواستوں کو روکتا ہے۔ جب خرابیوں کی تعداد ایک حد سے تجاوز کر جاتی ہے، Circuit Breaker OPEN حالت میں منتقل ہو جاتا ہے اور درخواست کو انجام دیے بغیر فوری طور پر خرابی لوٹاتا ہے، جس سے سرور کو بحالی کا وقت ملتا ہے۔
موبائل ایپلیکیشنز میں، Circuit Breaker خاص طور پر مفید ہے جب API منصوبہ بند دیکھ بھال یا آپریٹر نیٹ ورک کی ناکامیوں کی وجہ سے دستیاب نہ ہو۔ اس کے بغیر، ایپلیکیشن لامتناہی دوبارہ کوششوں میں بیٹری اور ٹریفک خرچ کرے گی، صارف کے تجربے کو خراب کرے گی اور آلے کی بیٹری کی زندگی کم کرے گی۔
Circuit Breaker کی تین حالتیں ہیں: CLOSED (عام آپریشن، درخواستیں انجام دی جاتی ہیں)، OPEN (ناکامی، درخواستیں مسدود ہوتی ہیں)، اور HALF_OPEN (بحالی کی جانچ کے لیے آزمائشی درخواست)۔ OPEN حالت میں مخصوص ٹائم آؤٹ کے بعد، بریکر HALF_OPEN میں منتقل ہوتا ہے اور ایک درخواست انجام دیتا ہے — کامیابی پر CLOSED پر، ناکامی پر OPEN پر واپس آتا ہے۔
class CircuitBreaker(
private val failureThreshold: Int = 3,
private val timeoutMs: Long = 30000
) {
private var state = State.CLOSED
private var failureCount = 0
private var lastFailureTime: Long = 0
suspend fun T.protect(block: suspend () -> T): T {
checkState()
return try {
val result = block()
onSuccess()
result
} catch (e: Exception) {
onFailure()
throw e
}
}
}
Kotlin میں Circuit Breaker کے نفاذ میں ایک خرابی کا کاؤنٹر اور ایک بحالی ٹائمر شامل ہے۔ protect طریقہ لپیٹی گئی درخواست کو انجام دینے سے پہلے موجودہ حالت کی جانچ کرتا ہے اور ناکامیوں پر خرابی کا کاؤنٹر اپ ڈیٹ کرتا ہے۔ failureThreshold تک پہنچنے کے بعد، timeoutMs ختم ہونے تک تمام درخواستیں فوری طور پر مسترد کر دی جاتی ہیں۔
موبائل نیٹ ورکس میں ایسی خصوصیات ہیں جو پالیسی دوبارہ کوشش کو خاص طور پر اہم بناتی ہیں۔ Wi-Fi اور موبائل ڈیٹا کے درمیان سوئچ کرنا، میٹرو اور سرنگوں میں سگنل کھونا، آپریٹر کی سطح پر عارضی بلاک — یہ تمام منظرنامے درخواست کی ناکامیوں کا سبب بنتے ہیں جنہیں دوبارہ کوشش سے کامیابی سے ہینڈل کیا جا سکتا ہے۔
Android پر، Retrofit لائبریری اور OkHttp Interceptor کے ذریعے ایک بلٹ ان دوبارہ کوشش کا طریقہ کار فراہم کرتے ہیں۔ iOS پر، کام URLSessionConfiguration اور کسٹم ڈیلیگیشن کے ذریعے حل کیا جاتا ہے۔ کراس پلیٹ فارم ڈویلپمنٹ کے لیے، Ktor (KMP) کنفیگر کرنے کے قابل حکمت عملیوں کے ساتھ بلٹ ان دوبارہ کوشش کی حمایت شامل کرتا ہے۔
Combine — reactive پروگرامنگ کے لیے Apple کا فریم ورک۔ Combine میں retry آپریٹر خرابی پر مخصوص تعداد میں publisher کو دہراتا ہے، لیکن دوبارہ کوششوں کے درمیان تاخیر کنفیگر کرنے کی اجازت نہیں دیتا۔ مکمل پالیسی دوبارہ کوشش کے لیے، تاخیر کے ساتھ catch اور flatMap کا کسٹم امتزاج استعمال کیا جاتا ہے۔
extension Publisher {
func retryWithBackoff(
retries: Int = 3,
baseDelay: TimeInterval = 1.0
) -> AnyPublisher<Output, Failure> {
return self.catch { error -> AnyPublisher in
guard retries > 0 else {
return Fail(error).eraseToAnyPublisher()
}
return Just(())
.delay(for: .seconds(baseDelay), scheduler: DispatchQueue.main)
.flatMap { self.retryWithBackoff(
retries: retries - 1,
baseDelay: baseDelay * 2
) }
.eraseToAnyPublisher()
}
.eraseToAnyPublisher()
}
}
Combine میں Publisher کے لیے retryWithBackoff توسیع گھٹتے ہوئے کاؤنٹر اور دوگنی تاخیر کے ساتھ بار بار کالوں کے ذریعے exponential backoff کو لاگو کرتی ہے۔ delay آپریٹر دوبارہ کوششوں کے درمیان وقفہ پیدا کرتا ہے، جبکہ catch خرابی کو روکتا ہے اور فیصلہ کرتا ہے کہ آیا دوبارہ کوشش کرنی ہے یا ناکامی لوٹانی ہے۔
پہلی غلطی — idempotency کی جانچ کیے بغیر درخواستوں کو دہرانا۔ اگر سرور نے ایک وسائل بنایا لیکن نیٹ ورک کی ناکامی کی وجہ سے تصدیق نہیں لوٹائی، تو دوبارہ کوشش ایک ڈپلیکیٹ بنائے گی۔ POST درخواستوں کے لیے، ہمیشہ ہیڈر میں idempotency کلید (Idempotency-Key) استعمال کریں یا صرف GET، PUT اور DELETE کے لیے دوبارہ کوشش پر جائیں۔
دوسری غلطی — لامتناہی دوبارہ کوشش۔ ہمیشہ زیادہ سے زیادہ کوششوں کی تعداد (موبائل ایپلیکیشنز کے لیے 3–5) اور تمام کوششوں کے لیے ایک مجموعی ٹائم آؤٹ مقرر کریں۔ لامتناہی دوبارہ کوشش بیٹری ختم کرتی ہے اور سرور پر پرجیوی بوجھ پیدا کرتی ہے، خاص طور پر ڈیٹا بیس مائیگریشن یا API تبدیلیوں کے دوران۔
تیسری غلطی — ایپلیکیشن کے سیاق و سباق کو نظر انداز کرنا۔ اگر صارف نے ایپلیکیشن بند کر دی یا بیک گراؤنڈ میں چلا گیا، تو فعال پالیسی دوبارہ کوشش کو صحیح طریقے سے منسوخ کرنا چاہیے۔ اسکرین بند ہونے پر خودکار دوبارہ کوشش منسوخی کے لیے SupervisorScope کے ساتھ coroutines یا UI لائف سائیکل کے ساتھ Combine استعمال کریں۔
چوتھی غلطی — دوبارہ کوششوں کو لاگ نہ کرنا۔ لاگنگ کے بغیر، آپ کو معلوم نہیں ہوگا کہ کتنی درخواستیں دہرائی گئیں، کون سی خرابیاں ہوئیں، اور آپ کی پالیسی دوبارہ کوشش کتنی مؤثر ہے۔ میٹرکس شامل کریں: دوبارہ کوشش کی تعداد، دوبارہ کوشش کے بعد کامیابی، تاخیر کی تقسیم۔ یہ ڈیٹا آپ کی مخصوص ایپلیکیشن کے لیے بہترین حکمت عملی کے پیرامیٹرز کو ٹیون کرنے میں مدد کرے گا۔
اکثر پوچھے گئے سوالات
زیادہ تر منظرناموں کے لیے دوبارہ کوشش کی بہترین تعداد 3–5 کوششیں ہیں۔ بیک گراؤنڈ سنکرونائزیشن کے لیے، 5–7 کوششیں قابل قبول ہیں؛ انٹرایکٹو درخواستوں (مثلاً فارم جمع کرانے) کے لیے، 3 سے زیادہ نہیں۔ زیادہ تعداد میں دوبارہ کوشش کامیابی کے امکانات نہیں بڑھاتی لیکن صارف کی بیٹری اور ڈیٹا ٹریفک خرچ کرتی ہے۔
Exponential backoff — دوبارہ کوششوں کے درمیان تاخیر کا دوگنا ہونا: 1 سیکنڈ، 2، 4، 8، 16 وغیرہ۔ اگر سرپر اوورلوڈ ہے، پہلی چند دوبارہ کوششوں کے درمیان مختصر وقفہ اسے فوری جواب دینے کی اجازت دیتا ہے، جبکہ ہر بعد کی دوبارہ کوشش کے ساتھ بڑھتا ہوا وقفہ سرور کو بحالی کے لیے زیادہ وقت دیتا ہے۔
صرف عارضی خرابیاں دہرائیں: 408 (Request Timeout)، 429 (Too Many Requests)، 502 (Bad Gateway)، 503 (Service Unavailable)، 504 (Gateway Timeout)۔ 4xx خرابیاں (408 اور 429 کو چھوڑ کر) کلائنٹ کے مسائل کی نشاندہی کرتی ہیں — انہیں دہرانا بے معنی ہے اور صارف کے ڈیٹا کے لیے خطرناک ہو سکتا ہے۔
پالیسی دوبارہ کوشش ناکامی پر ایک درخواست کی دوبارہ کوشش کا انتظام کرتی ہے۔ Circuit Breaker سروس کے ساتھ کنکشن کی حالت کا انتظام کرتا ہے: جب خرابیاں جمع ہو جاتی ہیں، تو یہ سرکٹ کھولتا ہے (OPEN) اور نئی درخواستوں کو بلاک کرتا ہے۔ دوبارہ کوشش انفرادی کال کی سطح پر کام کرتی ہے، Circuit Breaker سروس انٹیگریشن کی سطح پر۔
جانچ کے لیے، نیٹ ورک کی ناکامیوں کا نقلی بنانے کے لیے Android پر NetworkInterceptor (OkHttp) اور iOS پر URLProtocol (URLSession) استعمال کریں۔ پیرامیٹرز سیٹ کریں: خرابی کی تعدد، غیر دستیابی کی مدت، اور جوابی کوڈز۔ MockWebServer (OkHttp) یا OHHTTPStubs (iOS) کے ساتھ یونٹ ٹیسٹ حقیقی نیٹ ورک کے بغیر دوبارہ کوشش کی منطق کی تصدیق کرتے ہیں۔
خلاصہ
ہم ایک موبائل ایپلیکیشن ٹرنکی تیار کریں گے
IT Sectr 2017 سے اسٹارٹ اپس اور کاروبار کے لیے iOS اور Android ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔
مزید پڑھیں