Maqola · 2026-08-16 · ~7 daqiqa o‘qiladi · o'rta
Katalog botda emas, backend'da yashaydi: besh yil ishlagan arxitektura
Mundarija
Aladdin bot 2021-yilda yozilgan va hozirgacha ishlab turibdi. Qizig'i shundaki, shu besh yil ichida katalog minglab marta yangilangan, narxlar necha bor o'zgargan, yangi kategoriyalar qo'shilgan — lekin botning kodiga deyarli tegilmagan. Bugun ana shu natijani bergan arxitekturani ko'rib chiqamiz.
Birinchi yo'l va uning oqibati#
Katalog boti yozayotgan odam odatda eng qisqa yo'ldan boradi: tovarlarni botning o'z bazasiga saqlaydi. Boshida bu juda qulay tuyuladi, chunki hamma narsa bitta joyda va qo'shimcha xizmat kerak emas:
# Birinchi qarashda jozibali, lekin keyin qimmatga tushadigan yo'l:
# tovarlar botning SQLite bazasida
async def show_products(message: types.Message):
products = db.execute("SELECT * FROM products WHERE category_id = ?", (cat_id,))
Muammo bir-ikki oydan keyin boshlanadi. Menejer yangi tovar qo'shmoqchi — buning uchun dasturchiga yozadi. Narx o'zgardi — yana dasturchiga yozadi. Rasm almashtirish kerak — yana o'sha. Endi siz bot yozgan dasturchi emas, kompaniyaning kontent-operatorisiz. Aladdin'dagi kabi assortiment katta bo'lsa, bu yo'l bilan yashab bo'lmaydi.
To'g'ri yo'l: bot — bu ko'zgu#
Yechim shuki, ma'lumot va uni ko'rsatish bir-biridan ajratiladi. Tovarlar, kategoriyalar, narxlar va manzillar veb-backend'da yashaydi, u yerda menejerlar uchun oddiy admin-panel bor. Bot esa hech narsani o'zida saqlamaydi: kerak bo'lganda API'dan so'rab oladi va foydalanuvchiga ko'rsatadi, xolos.
Menejer ──► Admin-panel ──► Backend bazasi
│
REST API
│
Foydalanuvchi ──► Telegram bot ──┘ (faqat o'qiydi)
Shu ajratishdan keyin ikkala tomon o'z sur'atida yashaydi: katalog har kuni o'zgaradi, bot esa yillab o'zgarmaydi. Aynan shuning uchun 2021-yilgi kod 2026-yilda ham xizmat qilyapti.
Bot tomoni: API mijoz qatlami#
Loyihada API bilan ishlaydigan kodni bitta papkaga yig'amiz, handler'lar esa undan foydalanadi:
bot/
├── api/
│ ├── __init__.py
│ └── catalog.py ← backend bilan gaplashadigan yagona joy
├── handlers/
│ └── products.py ← foydalanuvchiga ko'rsatish
└── app.py
# bot/api/catalog.py
import aiohttp
BASE_URL = "https://catalog.misol.uz/api/telegram"
TIMEOUT = aiohttp.ClientTimeout(total=5) # backend javob bermasa 5 soniyada taslim
class CatalogAPI:
"""Backend'dagi katalogga read-only darcha.
Bot uchun backend — tashqi xizmat. Shuning uchun har chaqiruvda timeout
bor va xatolik alohida turga o'raladi: handler'lar aiohttp'ni bilmaydi.
"""
async def _get(self, path: str, **params) -> dict | list:
async with aiohttp.ClientSession(timeout=TIMEOUT) as session:
async with session.get(f"{BASE_URL}{path}", params=params) as resp:
resp.raise_for_status()
return await resp.json()
async def categories(self) -> list[dict]:
return await self._get("/categories/")
async def products(self, category_id: int) -> list[dict]:
return await self._get("/products/", category_id=category_id)
async def product(self, product_id: int) -> dict:
return await self._get(f"/products/{product_id}/")
catalog = CatalogAPI()
Handler endi juda sodda bo'lib qoladi, chunki uning ishi faqat ko'rsatish:
# bot/handlers/products.py
from aiogram import Router, types
from aiogram.exceptions import TelegramBadRequest
from bot.api.catalog import catalog
router = Router()
@router.callback_query(lambda c: c.data.startswith("cat:"))
async def show_category(callback: types.CallbackQuery):
category_id = int(callback.data.split(":")[1])
try:
products = await catalog.products(category_id)
except Exception:
# backend yotgan payt bot ham "yotib qolmasin":
# foydalanuvchiga halol javob beramiz va admin'ga xabar ketadi
await callback.message.answer(
"Katalog vaqtincha ishlamayapti, birozdan keyin urinib ko'ring."
)
return
# ... tovarlar ro'yxatini tugmalar bilan chiqarish (2-qismda batafsil)
Backend yotsa, bot nima qiladi?
Ajratilgan arxitekturaning narxi shu savol. Bot endi tashqi xizmatga bog'liq, demak u xizmat yotgan paytga tayyor turishi kerak: har so'rovda timeout, xatoda foydalanuvchiga tushunarli javob, adminlarga bildirishnoma. Bular bo'lmasa, backend'dagi besh daqiqalik uzilish "bot ishlamayapti" degan yuzlab shikoyatga aylanadi.
Backend tomoni: bot uchun alohida, kichik API#
Backend'da admin-panel qanday bo'lishi muhim emas — Django admin ham,
tayyor CMS ham bo'laveradi. Muhimi, bot uchun alohida, kichik endpoint'lar
ochib qo'yishdir. Aladdin'da bu /api/telegram/... yo'llari: ularda faqat
botga kerak maydonlar bor va hech qanday yozish yo'q.
# backend tomonida (Django misolida)
# catalog/views.py
from django.http import JsonResponse
from .models import Product
def telegram_products(request):
category_id = request.GET.get("category_id")
products = Product.objects.filter(category_id=category_id, is_active=True).values(
"id", "name", "price", "image_url"
)
# faqat botga kerak maydonlar — ichki narx, qoldiq, tannarx bu yerga chiqmaydi
return JsonResponse(list(products), safe=False)
Nega umumiy admin API'ni bermay, alohida qilamiz? Chunki bot — ochiq dunyoga qaragan mijoz. Unga qancha kam ma'lumot chiqsa, xatolik ehtimoli shuncha kam: tannarx, qoldiq, ichki izohlar kabi maydonlar tasodifan ham botga oqib tushmaydi.
Kesh haqida ikki og'iz
Kategoriyalar ro'yxati kuniga bir marta o'zgaradi, bot esa uni har bosishda so'raydi. Oddiy yechim — API mijozida qisqa muddatli kesh (masalan, 60 soniya). Bu backend'dagi yukni sezilarli kamaytiradi, foydalanuvchi esa farqni sezmaydi. Keshlash strategiyalari haqida alohida yozganman: Redis keshlash.
Bu arxitektura qachon ortiqcha?#
Halol javob: har doim ham kerak emas. Agar botingiz o'n-o'n besh tovarli kichik do'kon uchun bo'lsa va kontentni o'zingiz yangilab tursangiz, alohida backend ko'tarish — ortiqcha dabdaba. Ajratish o'zini oqlashi uchun ikki shart bo'lishi kerak: kontentni dasturchi bo'lmagan odam boshqarishi va kontent tez-tez o'zgarishi. Aladdin'da ikkalasi ham bor edi, shuning uchun arxitektura besh yildan beri o'zini oqlab kelyapti.
Xulosa#
Bot va kontentni ajratish — katta kompaniyalar uchun emas, uzoq yashashi kerak bo'lgan har qanday bot uchun qoida. Bot ko'rsatadi, backend saqlaydi, menejer admin-paneldan boshqaradi. Bot tashqi xizmatga bog'liq bo'lgani uchun timeout va halol xato-javoblar shart. Botga esa umumiy emas, maxsus kichik API ochiladi — ortiqcha ma'lumot tashqariga chiqmaydi.
Keyingi qismda shu katalogni foydalanuvchiga chiroyli ko'rsatishni o'rganamiz: kategoriya ichiga kirib, tovarni ochib, yana ortga qaytadigan ichma-ich tugmalar navigatsiyasi.