구독자 알림 발송 개선

This commit is contained in:
2023-04-27 15:57:47 +09:00
parent c1ff253356
commit 97a9ad6c72
3 changed files with 46 additions and 21 deletions

View File

@ -9,7 +9,7 @@ import configparser
from pydantic import BaseModel
from datetime import datetime
from aiohttp import ClientSession
import aiohttp
class StatusEndpointFilter(logging.Filter):
def filter(self, record):
@ -79,10 +79,12 @@ class Donate(BaseModel):
class DaminationAPI():
def __init__(self):
self.WIDGET_IDS = WIDGET_IDS
self.queue = asyncio.Queue()
self.fetch_tasks = []
self.stop_event = asyncio.Event()
self.subscribers = {}
self.session = aiohttp.ClientSession()
def add_subscriber(self, widget_id: str, url: str) -> bool:
@ -108,8 +110,8 @@ class DaminationAPI():
현재 설정된 모든 위젯 ID 목록을 반환합니다.
"""
logger.debug(f"get widget {WIDGET_IDS}")
return WIDGET_IDS
logger.debug(f"get widget {self.WIDGET_IDS}")
return self.WIDGET_IDS
def add_widget_id(self, widget_id:str):
"""
@ -118,7 +120,7 @@ class DaminationAPI():
"""
try:
WIDGET_IDS.append(widget_id)
self.WIDGET_IDS.append(widget_id)
logger.debug(f"add widget {widget_id}")
except Exception as e:
@ -132,8 +134,8 @@ class DaminationAPI():
"""
try:
if widget_id in WIDGET_IDS:
widget = WIDGET_IDS.pop(WIDGET_IDS.index(widget_id))
if widget_id in self.WIDGET_IDS:
widget = self.WIDGET_IDS.pop(self.WIDGET_IDS.index(widget_id))
logger.debug(f"delete widget {widget}")
return widget
@ -217,7 +219,7 @@ class DaminationAPI():
self.stop_event.clear() # 추가: 중단 이벤트를 초기화합니다.
for widget_id in WIDGET_IDS:
for widget_id in self.WIDGET_IDS:
task = asyncio.create_task(self.fetch_alerts(self.queue, widget_id))
self.fetch_tasks.append(task)
@ -239,7 +241,7 @@ class DaminationAPI():
widget_id: 추가할 위젯 ID
"""
if widget_id not in WIDGET_IDS:
if widget_id not in self.WIDGET_IDS:
self.add_widget_id(widget_id)
task = asyncio.create_task(self.fetch_alerts(self.queue, widget_id))
self.fetch_tasks.append(task)
@ -252,8 +254,8 @@ class DaminationAPI():
주어진 widget_id를 위젯 ID 목록에서 제거하고 알림을 가져오는 작업을 중단합니다.
widget_id: 제거할 위젯 ID
"""
if widget_id in WIDGET_IDS:
index = WIDGET_IDS.index(widget_id)
if widget_id in self.WIDGET_IDS:
index = self.WIDGET_IDS.index(widget_id)
self.remove_widget_id(widget_id)
fetch_task = self.fetch_tasks.pop(index)
fetch_task.cancel()
@ -273,16 +275,39 @@ class DaminationAPI():
else:
return None
def get_subscribers(self, widget_id: str) -> list:
"""
주어진 widget_id에 해당하는 구독자 목록을 반환합니다.
widget_id: 구독자 목록을 얻을 위젯 ID
"""
async def notify_subscribers(self, widget_id: str, donate):
if widget_id not in self.subscribers:
return
if widget_id in self.subscribers:
return self.subscribers[widget_id]
else:
return []
for subscriber_url in self.subscribers[widget_id]:
async with ClientSession() as session:
await session.post(subscriber_url, json=donate)
async def notify_subscribers(self, widget_id, donate):
"""
주어진 widget_id에 해당하는 모든 구독자들에게 알림을 전송합니다.
widget_id: 알림을 보낼 구독자들의 위젯 ID
donate: 전송할 알림 데이터
"""
subscribers = self.get_subscribers(widget_id)
tasks = [self.notify_subscriber(self.session, subscriber_url, donate) for subscriber_url in subscribers] # 변경: 기존 클래스 세션 사용
await asyncio.gather(*tasks)
logger.info(f"send to subscriber({widget_id}: {donate})")
async def notify_subscriber(self, session, subscriber_url, donate):
"""
주어진 구독자에게 알림을 전송합니다.
session: aiohttp ClientSession 객체
subscriber_url: 알림을 받을 구독자의 URL
donate: 전송할 알림 데이터
"""
async with session.post(subscriber_url, json=donate) as response:
if response.status // 100 == 2:
logger.info(f"Successfully sent notification to {subscriber_url}.")
else:
logger.error(f"Failed to send notification to {subscriber_url} with status code {response.status}.")
async def run(self):

View File

@ -11,7 +11,7 @@ RUN apk --no-cache add tzdata && \
COPY ./requirements.txt /
RUN pip install --no-cache-dir -r requirements.txt
COPY . /app
COPY ./app /app
WORKDIR /app
EXPOSE 80
@ -20,4 +20,4 @@ HEALTHCHECK --interval=5s --timeout=3s --start-period=10s --retries=3 \
CMD curl --fail http://localhost/status || exit 1
CMD ["python", "damination.py"]
CMD ["python", "main.py"]