Добавлены уведомления

This commit is contained in:
mi
2026-07-27 17:36:53 +03:00
parent a072005164
commit 958fba5f3e
149 changed files with 6371 additions and 110 deletions
+81 -2
View File
@@ -5,7 +5,7 @@ from datetime import UTC, datetime, timedelta
import httpx
import redis.asyncio as redis
import structlog
from sqlalchemy import select
from sqlalchemy import delete, select
from app.db import Database, DeliveryOutbox, Dialog, Message, MessageAttachment, SafetyTask
from app.integrations import (
@@ -15,8 +15,10 @@ from app.integrations import (
SafetyClient,
fresh_openlines_payload,
)
from app.notification_models import ClientUploadDraft
from app.notification_service import expire_notifications
from app.realtime import RealtimeFanout
from app.services import publish_dialog_status, publish_message_status
from app.services import load_settings, publish_dialog_status, publish_message_status
from app.settings import Settings, get_settings
log = structlog.get_logger()
@@ -222,6 +224,75 @@ async def loop(kind: str) -> None:
await db.close()
async def notification_expire_loop() -> None:
settings = get_settings()
db = Database(settings.database_url)
try:
while True:
async with db.sessions() as session:
snapshot = await load_settings(session)
run_at = snapshot.values["notification.expire_job.run_at"]
hour, minute = (int(value) for value in run_at.split(":", 1))
now = datetime.now(UTC)
target = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
if target <= now:
target += timedelta(days=1)
await asyncio.sleep((target - now).total_seconds())
async with db.sessions() as session:
personal, guest = await expire_notifications(session)
log.info(
"notification.expired_batch",
personal_count=personal,
guest_count=guest,
)
finally:
await db.close()
async def notification_draft_cleanup_once(db: Database, s3: S3Client) -> int:
async with db.sessions() as session:
snapshot = await load_settings(session)
cutoff = datetime.now(UTC) - timedelta(
days=snapshot.integer("notification.upload_draft.ttl_days")
)
rows = (
(
await session.execute(
select(ClientUploadDraft)
.where(ClientUploadDraft.created_at < cutoff)
.with_for_update(skip_locked=True)
.limit(100)
)
)
.scalars()
.all()
)
for row in rows:
if row.state != "submitted":
if row.quarantine_object_key:
await s3.delete_quarantine(row.quarantine_object_key)
elif row.object_key:
await s3.delete(row.storage_bucket, row.object_key)
await session.execute(
delete(ClientUploadDraft).where(ClientUploadDraft.id == row.id)
)
await session.commit()
return len(rows)
async def notification_draft_cleanup_loop() -> None:
settings = get_settings()
db = Database(settings.database_url)
s3 = S3Client(settings)
try:
while True:
count = await notification_draft_cleanup_once(db, s3)
if count < 100:
await asyncio.sleep(86400)
finally:
await db.close()
def delivery_main() -> None:
asyncio.run(loop("delivery"))
@@ -232,3 +303,11 @@ def safety_main() -> None:
def cleanup_main() -> None:
asyncio.run(loop("cleanup"))
def notification_expire_main() -> None:
asyncio.run(notification_expire_loop())
def notification_draft_cleanup_main() -> None:
asyncio.run(notification_draft_cleanup_loop())