Advertisement
Guest User

Untitled

a guest
Jun 1st, 2025
921
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.60 KB | None | 0 0
  1. #!/usr/bin/env python
  2. """
  3. Symulacja obciążenia /numer/api/validate-numer – wielu równoległych wywołań.
  4.  
  5. Autor: ChatGPT (c) 2025
  6. """
  7.  
  8. import asyncio
  9. import random
  10. import string
  11. import time
  12. from itertools import islice
  13.  
  14. import aiohttp
  15. from aiohttp import ClientSession
  16. from tqdm.asyncio import tqdm_asyncio  #  progress-bar dla zadań asynchronicznych
  17.  
  18. # --- Konfiguracja -----------------------------------------------------------
  19.  
  20. BASE_URL = "https://testnr.org/numer"   # ← zmień na produkcyjne / testowe
  21. TOTAL_REQUESTS = 1000                     # ile łącznie żądań wysłać
  22. CONCURRENCY = 5                          # maks. równoległych żądań
  23. TIMEOUT = aiohttp.ClientTimeout(total=10)  # seconds
  24.  
  25. # ---------------------------------------------------------------------------
  26.  
  27.  
  28. def random_numeric(length: int) -> str:
  29.     return "".join(random.choices(string.digits, k=length))
  30.  
  31.  
  32. async def fetch_captcha(session: ClientSession):
  33.     """Pobiera token i kod CAPTCHA z /…/generate-captcha."""
  34.     url = f"{BASE_URL}/api/generate-captcha"
  35.     async with session.post(url, json={}) as resp:
  36.         resp.raise_for_status()
  37.         data = await resp.json()
  38.         return data["token"], data["code"]
  39.  
  40.  
  41. async def validate_numer(session: ClientSession, numer: str, phone: str):
  42.     """
  43.    Wysyła pojedyncze zapytanie /api/validate-numer.
  44.    Zwraca (status_code, alreadyExists_flag, saved_flag) z odpowiedzi lub None
  45.    przy wyjątku.
  46.    """
  47.     try:
  48.         captcha_token, captcha_code = await fetch_captcha(session)
  49.  
  50.         payload = {
  51.             "numer": numer,
  52.             "phone": phone,
  53.             "captchaToken": captcha_token,
  54.             "captchaCode": captcha_code,
  55.         }
  56.         url = f"{BASE_URL}/api/validate-numer"
  57.         async with session.post(url, json=payload) as resp:
  58.             status = resp.status
  59.             data = await resp.json()
  60.             return status, data.get("alreadyExists"), data.get("saved")
  61.     except Exception as exc:
  62.         # Możesz tu dodać logging
  63.         return None
  64.  
  65.  
  66. async def producer(task_queue: asyncio.Queue):
  67.     """
  68.    Generuje pary (numer, phone) i wrzuca je do kolejki.
  69.    Tu: numer = losowa liczba 8-cyfrowa z prefiksem „99”, ale możesz podmienić
  70.    na cokolwiek (np. odczyt z pliku).
  71.    """
  72.     for _ in range(TOTAL_REQUESTS):
  73.         numer = "99" + random_numeric(6)
  74.         phone = random_numeric(9)
  75.         await task_queue.put((numer, phone))
  76.  
  77.     # sygnalizuj konsumentom, że więcej zadań nie będzie
  78.     for _ in range(CONCURRENCY):
  79.         await task_queue.put(None)
  80.  
  81.  
  82. async def consumer(task_queue: asyncio.Queue, session: ClientSession, stats: dict):
  83.     """Pobiera zadania z kolejki i wykonuje validate_numer()."""
  84.     while True:
  85.         item = await task_queue.get()
  86.         if item is None:  # koniec
  87.             break
  88.  
  89.         numer, phone = item
  90.         result = await validate_numer(session, numer, phone)
  91.         if result is None:
  92.             stats["errors"] += 1
  93.         else:
  94.             status, already_exists, saved = result
  95.             stats["status_counts"][status] = stats["status_counts"].get(status, 0) + 1
  96.             if status == 200:
  97.                 if already_exists:
  98.                     stats["duplicates"] += 1
  99.                 elif saved:
  100.                     stats["newly_saved"] += 1
  101.  
  102.  
  103. async def main():
  104.     task_queue: asyncio.Queue = asyncio.Queue(maxsize=CONCURRENCY * 2)
  105.     stats = {
  106.         "errors": 0,
  107.         "duplicates": 0,
  108.         "newly_saved": 0,
  109.         "status_counts": {},
  110.     }
  111.  
  112.     conn = aiohttp.TCPConnector(limit=CONCURRENCY, ssl=False)
  113.     async with aiohttp.ClientSession(connector=conn, timeout=TIMEOUT) as session:
  114.         prod = asyncio.create_task(producer(task_queue))
  115.         cons = [
  116.             asyncio.create_task(consumer(task_queue, session, stats))
  117.             for _ in range(CONCURRENCY)
  118.         ]
  119.  
  120.         start = time.perf_counter()
  121.         # Elegancka belka postępu
  122.         await tqdm_asyncio.gather(*cons, total=TOTAL_REQUESTS)
  123.         await prod
  124.         elapsed = time.perf_counter() - start
  125.  
  126.     # --- Podsumowanie --------------------------------------------------------
  127.     print("\n=== STATYSTYKI ===")
  128.     print(f"Łączny czas      : {elapsed:8.2f} s")
  129.     print(f"Żądania / sek.   : {TOTAL_REQUESTS / elapsed:8.2f}")
  130.     print(f"Błędy            : {stats['errors']}")
  131.     print(f"Duplikaty        : {stats['duplicates']}")
  132.     print(f"Dodane rekordy   : {stats['newly_saved']}")
  133.     print("Status HTTP      :", stats["status_counts"])
  134.  
  135.  
  136. if __name__ == "__main__":
  137.     asyncio.run(main())
  138.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement