ساخت یادآور قبض برق برای چند ملک با API: صف، خطا و هزینه
یادآور قبض برق برای چند ملک را با یک کار زمانبندیشده بسازید، نه با استعلام لحظهای؛ و بدانید کدام خطا هزینه دارد، کدام تکرار شدنی است و کجا باید کار متوقف شود.
اگر میخواهید برای دهها یا صدها ملک قبض برق را خودکار بپایید، استعلام را نباید به رفتار کاربر وصل کنید؛ باید یک کار زمانبندیشده بسازید که شبانه یا روزانه، با ترتیب و با شمارش خطاها، اجرا شود.
این نوشته برای کسی است که تصمیم گرفته وبسرویس استعلام قبض برق را در محصولش بگذارد و حالا میپرسد کار را چطور بچیند. دربارهٔ این است که کدام خطا پول میگیرد و کدام نه، کی باید دوباره تلاش کرد، و کجا باید ایستاد.
چرا کار زمانبندیشده، نه استعلام در لحظهٔ ورود کاربر
فرض کنید یک نرمافزار مدیریت املاک دارید و هر مدیر ملک یک داشبورد دارد. وسوسه این است که با باز شدن داشبورد، برای همهٔ ملکها استعلام بزنید. سه مشکل دارد:
- داشبورد با ده کاربر همزمان، ده برابر درخواست میسازد برای دادهای که در چند ساعت عوض نمیشود.
- هر خطای موقتی مستقیم در چشم کاربر میافتد.
- نمیتوانید سقف درخواست را کنترل کنید، چون شما زمان باز شدن داشبورد را تعیین نمیکنید.
قبض برق در نهایت دورهای صادر میشود. یک استعلام روزانه برای هر شناسه برای یادآوری کافی است. اگر مهلت پرداخت نزدیک است، میتوانید برای همان ملکها تکرار را بیشتر کنید، ولی دلیلی برای پرسوجوی دقیقهای نیست.
کش مشترک و برچسب تازگی
پاسخ استعلامها در کشی مشترک نگه داشته میشود و کلیدش خود ورودی است. برای قبوض، پنجرهٔ تازگی فعلاً یک ساعت است و اگر سرویس مرجع در دسترس نباشد، تا یک روز پاسخ قبلی با برچسب «کهنه» برمیگردد. در بدنهٔ پاسخ، بخش source همین را میگوید:
json "source": { "cached": true, "stale": false, "fetchedAt": "2026-09-23T10:00:00.000Z" }
دو نتیجهٔ عملی دارد. اول اینکه استعلام دوبارهٔ همان شناسه در یک ساعت معمولاً چیز تازهای نمیآورد. دوم اینکه stale: true را در جدول خودتان ثبت کنید و در رابط کاربری «آخرین پاسخ معتبر، مال فلان زمان» بنویسید. پاسخ کهنه خطا نیست، ولی با پاسخ تازه یکی هم نیست.
کدام خطا پول میگیرد
این بخش بیشترین ارزش را برای برنامهریزی هزینه دارد، چون اشتباه فهمیدنش یا بودجه را میسوزاند یا تلاش لازم را قطع میکند. کد خطا را بخوانید و به متن پیام تکیه نکنید:
| کد | HTTP | هزینه | در کار شبانه چه کنید |
|---|---|---|---|
invalid_input | ۴۰۰ | ندارد | شناسه را علامت بزنید و دوباره نفرستید |
not_found | ۲۰۰ | دارد | «بدون رکورد» ثبت کنید، تکرار فوری نکنید |
provider_failed | ۵۰۲ | دارد | پاسخ قطعی منفی است، تکرار همان را میدهد |
provider_failed_retryable | ۵۰۲ | ندارد | بعداً دوباره تلاش کنید |
temporarily_unavailable | ۵۰۳ | ندارد | بعداً دوباره تلاش کنید |
insufficient_funds | ۴۰۲ | ندارد | کل کار را متوقف کنید |
rate_limited | ۴۲۹ | ندارد | به Retry-After احترام بگذارید |
دو سطر را برجسته کنید. not_found با HTTP ۲۰۰ میآید و فیلد ok در آن false است. چون سرویس مرجع پرسیده شده و جوابش «رکوردی نیست» بوده، این استعلام هزینه دارد. اگر کدتان فقط به کد HTTP نگاه کند، آن را موفق میگیرد؛ اگر فقط به ok نگاه کند، آن را خطای تلاشمجدد میگیرد، و هر دو غلط است.
سطر دوم provider_failed است: جواب قطعی منفی، هزینهدار، و تکرارش بیفایده. حلقهٔ تلاش مجددی که این را دوباره بفرستد، هر دور پول بیشتری میدهد برای همان جواب.
ساختار پیشنهادی کار
یک الگوی ساده که برای من قابل دفاع است:
- جدول شناسهها را با وضعیت هر شناسه نگه دارید: آخرین نتیجه، زمان آخرین تلاش، و یک شمارندهٔ خطا.
- کار را پشتسرهم یا با همزمانی کم اجرا کنید، نه همه با هم. وقتی
rate_limitedآمد، همان شناسه را بعد از زمانRetry-Afterبرگردانید. insufficient_fundsرا مثل خطای یک شناسه رفتار نکنید. این خطا یعنی موجودی تمام شده؛ ادامهٔ کار فقط صدها شکست پشتسرهم میسازد. کار را متوقف کنید و به مسئول هشدار بدهید.- به هر فراخوان
requestIdپاسخ را کنار ردیف ذخیره کنید. وقتی مغایرتی پیش آید، همین شناسه گفتوگو با پشتیبانی را کوتاه میکند. - مبلغ کسرشده را از
billing.amountRialهر پاسخ بخوانید و جمع بزنید. هر پاسخی که به مرحلهٔ تسویه برسد این فیلد را دارد و نبودنش یعنی چیزی جابهجا نشده.
یک فراخوان نمونه:
bash curl -X POST 'https://example.com/api/v1/bill-electricity/' \ -H 'Authorization: Bearer melli_live_…' \ -H 'Content-Type: application/json' \ -d '{"billId":"1234567890123"}'
نشانی و کلید در این نمونه جاینگهدارند. کلید را فقط سمت سرور نگه دارید و داخل کد مرورگر نگذارید.
مبلغ صفر، خطا نیست
در جدول نتیجهها دو حالت را از هم جدا کنید: «پاسخ موفق با مبلغ صفر» و «بدون رکورد». اولی یعنی قبض تسویه است و باید همچنان یک ردیف تاریخچه بسازد. دومی یعنی شرکت چیزی برای این شناسه ندارد، که معمولاً یعنی شناسه را باید دوباره با مشتری چک کنید.
آنچه این سرویس نمیکند
- خودش خبر نمیدهد؛ باید بپرسید. رویدادی از طرف ما نمیرسد که بگوید قبض تازه صادر شد.
- پرداخت انجام نمیدهد. شناسهٔ قبض و شناسهٔ پرداخت را میگیرید و پرداخت از درگاه شما است.
- ریز مصرف و عدد کنتور نمیدهد.
- با نام مالک یا نشانی جستوجو نمیکند، فقط با شناسه قبض.
برای شکل کامل خطاها و هدرها مستندات فنی API را ببینید.
تعداد استعلام در هر اجرا و سقف نرخ
اگر هزار شناسه دارید، همه را یکجا نفرستید. گروههای کوچک بسازید، بین گروهها مکث بگذارید و پیشرفت را ذخیره کنید تا اگر کار وسط راه قطع شد، از اول شروع نکنید. حساب سادهای که کمک میکند: کار را طوری طراحی کنید که اگر دو بار پشتسرهم اجرا شد، بار دوم فقط شناسههایی را بپرسد که امروز نپرسیده است. این ویژگی (تکرارپذیری) هم از هزینهٔ اضافه جلوگیری میکند هم از تصادف دو اجرای همزمان.
سقف نرخ را از پیش نمیشناسید و حدسش هم لازم نیست: وقتی از آن عبور کنید، پاسخ rate_limited با HTTP ۴۲۹ میآید و هدر Retry-After میگوید چقدر صبر کنید. کار شما فقط احترام به همین هدر است. برای ایمنی بیشتر، همین حالا دسترسی کلید را به IP سرور خود محدود کنید تا اگر کلید جایی نشت کرد، از جای دیگر قابلاستفاده نباشد. راهنمای فنی آن را شرح داده است.
اگر محصول شما چند مشتری دارد، شمارندههای خطا و هزینه را به تفکیک مشتری نگه دارید. وقتی یک مشتری شناسههای غلط وارد کرده باشد، لازم نیست بقیه تاوانش را بدهند.
چه چیزی را ثبت کنید که بعداً لازم میشود
هر ردیف نتیجه چهار چیز داشته باشد: شناسه، پاسخ خام، fetchedAt و requestId. پاسخ خام را دور نیندازید. دادهٔ خامی که امروز فکر میکنید لازم نیست، همان است که ماه بعد برای فهمیدن «چرا یادآور ملک فلان نیامد» لازم میشود. اگر میخواهید جزئیات سرویس را مرور کنید، صفحهٔ استعلام قبض برق فیلدهای پاسخ را فهرست کرده است.
همچنین هر اجرا را با یک شناسهٔ اجرا علامت بزنید و تعداد پاسخهای هر کد خطا را بشمارید. اگر ناگهان نسبت not_found بالا رفت، احتمالاً مشکل از دادههای ورودی شماست؛ اگر temporarily_unavailable بالا رفت، مشکل از بیرون است و صبر کردن کافی است.
در یک نگاه
سه قاعده: استعلام را زمانبندی کنید، not_found را هزینهدار و provider_failed را بیفایده در تکرار بدانید، و روی insufficient_funds کار را بایستانید. بقیهٔ طراحی، جزئیات پیادهسازی است.
وبسرویس مرتبط با این راهنما
API استعلام قبض برق
مبلغ و مهلت پرداخت قبض برق.
راهنماهای مرتبط
پرسش و تجربه کاربران
اگر این راهنما جوابتان را نداد، همینجا بپرسید. پرسشها را تیمملی ایپیآی پاسخ میدهد و هر نظر پیش از انتشار بررسی میشود.
هنوز پرسشی ثبت نشده، اولین نفر باشید.
