- Logger doesn't start with log level DEBUG by default, instead reads a environment variable - Added extensive debug logging - Wrote a readme - Changed database healthcheck loop to only catch pymsql errors
73 lines
2.4 KiB
Python
73 lines
2.4 KiB
Python
import aiohttp
|
|
import aiodns
|
|
import asyncio
|
|
from logger_handler import setup_logger
|
|
|
|
API_ENDPOINT="https://exp.host/--/api/v2/push/send"
|
|
logger = setup_logger(__name__)
|
|
|
|
retryable_exceptions = (
|
|
aiohttp.ClientConnectionError,
|
|
aiohttp.ServerDisconnectedError,
|
|
aiohttp.ClientOSError,
|
|
aiohttp.ServerTimeoutError,
|
|
asyncio.TimeoutError,
|
|
)
|
|
|
|
|
|
async def send_notification(message: dict, push_tokens, max_retries: int = 5, timeout: int = 5):
|
|
logger.debug(f"[Notification] Sending to {len(push_tokens)} push tokens")
|
|
results = {}
|
|
for uuid, token in push_tokens.items():
|
|
logger.debug(f"[Notification] Preparing to send to uuid={uuid}")
|
|
results[uuid] = await _send_to_token(token, uuid, message, max_retries, timeout)
|
|
return results
|
|
|
|
async def _send_to_token(token: str, uuid:str , message: dict, max_retries: int, timeout: int):
|
|
payload = create_payload(token, message)
|
|
logger.debug(f"[Notification] Payload for uuid={uuid}: {payload}")
|
|
|
|
resolver = aiohttp.AsyncResolver()
|
|
connector = aiohttp.TCPConnector(resolver=resolver)
|
|
|
|
for attempt in range(1, max_retries + 1):
|
|
try:
|
|
async with aiohttp.ClientSession(connector=connector) as session:
|
|
async with session.post(
|
|
url=API_ENDPOINT,
|
|
json=payload,
|
|
headers={"Content-Type": "application/json"},
|
|
timeout=timeout
|
|
) as response:
|
|
response.raise_for_status()
|
|
data = await response.json()
|
|
logger.info(f"Notification sent successfully to uuid {uuid}")
|
|
return {"status":"ok","data":data}
|
|
|
|
except retryable_exceptions as e:
|
|
logger.warning(f"[Notification] Attempt {attempt}/{max_retries} failed for uuid={uuid}: {type(e).__name__}: {e}", exc_info=True)
|
|
await asyncio.sleep(2 ** (attempt - 1))
|
|
logger.debug(f"[Notification] Retrying uuid={uuid}, attempt {attempt + 1}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"[Notification] Unexpected failure for uuid={uuid}: {e}", exc_info=True)
|
|
return {"status": "error", "exception": str(e)}
|
|
|
|
logger.error(f"Failed to send notification to uuid {uuid} after {max_retries} attempts")
|
|
return {"status": "failure"}
|
|
|
|
def create_payload(push_token: str, message: dict) -> dict:
|
|
payload = {
|
|
"to": push_token,
|
|
"title": message.get("title"),
|
|
"body": message.get("body"),
|
|
"data": {
|
|
"link": message.get("link"),
|
|
"category": message.get("category"),
|
|
"timestamp": message.get("timestamp")
|
|
},
|
|
"sound": "default",
|
|
"priority": "high"
|
|
}
|
|
logger.debug(f"[Notification] Created payload: {payload}")
|
|
return payload |