دليل برمجي لبناء مجموعة أدوات تطوير برمجيات (SDK) متزامنة عالية الأداء بلغة بايثون مع تحديد معدل الاستجابة، والتخزين المؤقت في الذاكرة، والمصادقة
يقدم هذا الدليل الشامل خطوات بناء مجموعة أدوات تطوير برمجيات (SDK) متزامنة بلغة بايثون، مُصممة لتلبية متطلبات الإنتاج، مع التركيز على الأداء والكفاءة. سنتناول في هذا الدليل مكونات أساسية تضمن استقرار وفعالية مجموعة الأدوات، بدءًا من تثبيت وتكوين مكتبات HTTP المتزامنة الأساسية ووصولاً إلى إدارة الاستثناءات وإمكانية التوسعة.
1. التثبيت والتكوين
نقوم أولاً بتثبيت وتكوين بيئة العمل اللازمة باستخدام المكتبات التالية:
asyncio
: لإدارة العمليات المتزامنة.aiohttp
: لإجراء طلبات HTTP المتزامنة.nest_asyncio
: لتمكين تشغيل حلقة الأحداث داخل بيئات مثل Jupyter Notebook أو Google Colab.dataclasses
: لإنشاء نماذج بيانات منظمة.hashlib
: لإنشاء مفاتيح التجزئة للتخزين المؤقت.datetime
: لإدارة تواريخ وأوقات انتهاء صلاحية البيانات المخزنة مؤقتًا.logging
: لإدارة السجلات.
يمكن تثبيت هذه المكتبات باستخدام أمر pip
:
pip install aiohttp nest_asyncio
2. تصميم كائن الاستجابة
سنبدأ بتعريف كائن APIResponse
لاستقبال الاستجابات من الخادم، وهو كائن بيانات منظم (dataclass) يحتوي على:
data
: بيانات الاستجابة.status_code
: رمز حالة الاستجابة (مثلاً: 200 للنجاح).headers
: عناوين الاستجابة.timestamp
: وقت استلام الاستجابة.
from dataclasses import dataclass, asdict
from datetime import datetime
from typing import Any, Dict
@dataclass
class APIResponse:
"""كائن بيانات منظم لاستجابة API"""
data: Any
status_code: int
headers: Dict[str, str]
timestamp: datetime
def to_dict(self) -> Dict:
return asdict(self)
3. محدد معدل الاستجابة (Rate Limiter)
لتجنب تجاوز حدود معدل الاستجابة للخادم، سنستخدم RateLimiter
الذي يطبق سياسة “Token Bucket” لتحديد عدد الطلبات المسموح بها خلال فترة زمنية معينة:
import time
class RateLimiter:
"""محدد معدل الاستجابة باستخدام سياسة Token Bucket"""
def __init__(self, max_calls: int = 100, time_window: int = 60):
self.max_calls = max_calls
self.time_window = time_window
self.calls = []
def can_proceed(self) -> bool:
now = time.time()
self.calls = [call_time for call_time in self.calls if now - call_time < self.time_window]
if len(self.calls) < self.max_calls:
self.calls.append(now)
return True
return False
def wait_time(self) -> float:
if not self.calls:
return 0
return max(0, self.time_window - (time.time() - self.calls[0]))
4. التخزين المؤقت (Cache)
لتحسين الأداء، سنستخدم Cache
لتخزين الاستجابات مؤقتًا في الذاكرة مع تحديد وقت انتهاء صلاحيتها (TTL):
import hashlib
from datetime import timedelta
class Cache:
"""تخزين مؤقت بسيط في الذاكرة مع TTL"""
def __init__(self, default_ttl: int = 300):
self.cache = {}
self.default_ttl = default_ttl
def _generate_key(self, method: str, url: str, params: Dict = None) -> str:
key_data = f"{method}:{url}:{json.dumps(params or {}, sort_keys=True)}"
return hashlib.md5(key_data.encode()).hexdigest()
def get(self, method: str, url: str, params: Dict = None) -> Optional[APIResponse]:
key = self._generate_key(method, url, params)
if key in self.cache:
response, expiry = self.cache[key]
if datetime.now() < expiry:
return response
del self.cache[key]
return None
def set(self, method: str, url: str, response: APIResponse, params: Dict = None, ttl: int = None):
key = self._generate_key(method, url, params)
expiry = datetime.now() + timedelta(seconds=ttl or self.default_ttl)
self.cache[key] = (response, expiry)
5. مجموعة أدوات تطوير البرمجيات (AdvancedSDK)
تجمع هذه الفئة جميع المكونات السابقة معًا:
import aiohttp
import logging
from typing import Dict, Optional
class AdvancedSDK:
"""مجموعة أدوات تطوير برمجيات متقدمة مع أنماط بايثون الحديثة"""
def __init__(self, base_url: str, api_key: str = None, rate_limit: int = 100):
self.base_url = base_url.rstrip('/')
self.api_key = api_key
self.session = None
self.rate_limiter = RateLimiter(max_calls=rate_limit)
self.cache = Cache()
self.logger = self._setup_logger()
def _setup_logger(self) -> logging.Logger:
# ... ( نفس الكود من المثال الأصلي ) ...
async def __aenter__(self):
self.session = aiohttp.ClientSession()
return self
async def __aexit__(self, exc_type, exc_val, exc_tb):
if self.session:
await self.session.close()
def _get_headers(self) -> Dict[str, str]:
# ... ( نفس الكود من المثال الأصلي ) ...
async def _make_request(self, method: str, endpoint: str, params: Dict = None, data: Dict = None, use_cache: bool = True) -> APIResponse:
# ... ( نفس الكود من المثال الأصلي مع تعديلات طفيفة في التعليقات ) ...
async def get(self, endpoint: str, params: Dict = None, use_cache: bool = True) -> APIResponse:
return await self._make_request('GET', endpoint, params=params, use_cache=use_cache)
async def post(self, endpoint: str, data: Dict = None) -> APIResponse:
return await self._make_request('POST', endpoint, data=data, use_cache=False)
async def put(self, endpoint: str, data: Dict = None) -> APIResponse:
return await self._make_request('PUT', endpoint, data=data, use_cache=False)
async def delete(self, endpoint: str) -> APIResponse:
return await self._make_request('DELETE', endpoint, use_cache=False)
6. مثال عملي (Demo)
يوضح هذا المثال كيفية استخدام AdvancedSDK
:
import asyncio
async def demo_sdk():
# ... ( نفس الكود من المثال الأصلي مع تعديلات طفيفة في التعليقات ) ...
async def run_demo():
await demo_sdk()
# ... ( نفس الكود من المثال الأصلي لـ nest_asyncio ) ...
7. نمط Builder
يُسهّل هذا النمط تكوين AdvancedSDK
:
class SDKBuilder:
"""نمط Builder لتكوين SDK"""
def __init__(self, base_url: str):
self.base_url = base_url
self.config = {}
def with_auth(self, api_key: str):
self.config['api_key'] = api_key
return self
def with_rate_limit(self, calls_per_minute: int):
self.config['rate_limit'] = calls_per_minute
return self
def build(self) -> AdvancedSDK:
return AdvancedSDK(self.base_url, **self.config)
الخاتمة
يُعد هذا الدليل بمثابة أساس متين لبناء SDKs متزامنة فعالة وقابلة للتوسعة، وذلك من خلال دمج أنماط بايثون الحديثة مع أدوات عملية مثل محدد معدل الاستجابة، والتخزين المؤقت، وإدارة السجلات. باستخدام الأنماط الموضحة هنا، يمكن للفرق تطوير SDKs جديدة بسرعة مع ضمان القدرة على التنبؤ، والمراقبة، والمرونة.
اترك تعليقاً