fix!: removed .commit() from repository level
This commit is contained in:
@@ -1,22 +1,17 @@
|
||||
import asyncio
|
||||
from datetime import UTC, datetime, timedelta
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.dialects.postgresql import insert
|
||||
|
||||
from config import cfg
|
||||
from db.models import ServiceNotification, Subscription
|
||||
from db.session import async_session
|
||||
from db.session import UnitOfWork, async_session
|
||||
from schemas.enums import NotificationType
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
|
||||
async def collect_subscription_notifications(
|
||||
session: "AsyncSession", now: datetime | None = None
|
||||
) -> int:
|
||||
async def collect_subscription_notifications(uow: UnitOfWork, now: datetime | None = None) -> int:
|
||||
session = uow.session
|
||||
now = now or datetime.now(UTC)
|
||||
periods = (
|
||||
(NotificationType.SEVEN_DAYS, now + timedelta(days=3), now + timedelta(days=7)),
|
||||
@@ -48,7 +43,7 @@ async def collect_subscription_notifications(
|
||||
result = await session.execute(stmt)
|
||||
created += result.rowcount or 0
|
||||
|
||||
await session.commit()
|
||||
await uow.commit()
|
||||
return created
|
||||
|
||||
|
||||
@@ -56,8 +51,8 @@ async def run_subscription_notifications() -> None:
|
||||
interval = cfg.notification_scan_interval * 60
|
||||
while True:
|
||||
try:
|
||||
async with async_session() as session:
|
||||
await collect_subscription_notifications(session)
|
||||
async with async_session() as session, UnitOfWork(session) as uow:
|
||||
await collect_subscription_notifications(uow)
|
||||
except Exception:
|
||||
# A failed iteration must not stop subsequent notification checks.
|
||||
pass
|
||||
|
||||
@@ -6,7 +6,8 @@ from datetime import UTC, datetime
|
||||
|
||||
from config import cfg
|
||||
from db.models.orders import OrderStatus
|
||||
from db.models.transactions import BalanceTransaction, BalanceTxType
|
||||
from db.models.transactions import BalanceTxType
|
||||
from db.session import UnitOfWork
|
||||
from repositories import AddonsRepository
|
||||
from repositories.invoices import InvoiceRepository
|
||||
from repositories.orders import OrderRepository
|
||||
@@ -32,16 +33,17 @@ def validate_pally_signature(out_sum: str, inv_id: str, signature_value: str) ->
|
||||
|
||||
|
||||
async def process_subscription_purchase( # noqa: PLR0911, PLR0912
|
||||
session,
|
||||
uow: UnitOfWork,
|
||||
*,
|
||||
invoice_id: int,
|
||||
trs_id: str,
|
||||
amount: int,
|
||||
) -> None:
|
||||
invoice_repo = InvoiceRepository(session)
|
||||
orders_repo = OrderRepository(session)
|
||||
users_repo = UserRepository(session)
|
||||
pricing_repo = PricingRepository(session)
|
||||
session = uow.session
|
||||
invoice_repo = InvoiceRepository(uow)
|
||||
orders_repo = OrderRepository(uow)
|
||||
users_repo = UserRepository(uow)
|
||||
pricing_repo = PricingRepository(uow)
|
||||
|
||||
invoice = await invoice_repo.get_by_id(invoice_id)
|
||||
|
||||
@@ -99,7 +101,7 @@ async def process_subscription_purchase( # noqa: PLR0911, PLR0912
|
||||
|
||||
subscription = user.subscription
|
||||
now = datetime.now(UTC)
|
||||
pricing = await get_pricing_model(AddonsRepository(session), pricing_repo)
|
||||
pricing = await get_pricing_model(AddonsRepository(uow), pricing_repo)
|
||||
|
||||
logger.info(
|
||||
"Processing payment: bill_id=%s, order_id=%s, user_id=%s, amount=%s",
|
||||
@@ -142,19 +144,14 @@ async def process_subscription_purchase( # noqa: PLR0911, PLR0912
|
||||
if referal_id is not None:
|
||||
referal_amount = math.floor(amount * (cfg.referal_bonus / 100))
|
||||
if referal_amount > 0:
|
||||
referal_user = await session.get(type(user), referal_id)
|
||||
referal_user = await users_repo.get_user_by_id(referal_id)
|
||||
if referal_user is not None:
|
||||
session.add(
|
||||
BalanceTransaction(
|
||||
user_id=referal_id,
|
||||
amount=referal_amount,
|
||||
tx_type=BalanceTxType.REFERRAL_BONUS,
|
||||
balance_before=referal_user.balance,
|
||||
balance_after=referal_user.balance + referal_amount,
|
||||
description=f"referral reward for user {invoice.creator_id} (TrsId: {trs_id})",
|
||||
)
|
||||
await users_repo.increase_balance(
|
||||
referal_id,
|
||||
referal_amount,
|
||||
BalanceTxType.REFERRAL_BONUS,
|
||||
f"referral reward for user {invoice.creator_id} (TrsId: {trs_id})",
|
||||
)
|
||||
referal_user.balance += referal_amount
|
||||
|
||||
logger.info(
|
||||
"Referral bonus processed: referrer_id=%s, amount=%s",
|
||||
@@ -169,6 +166,6 @@ async def process_subscription_purchase( # noqa: PLR0911, PLR0912
|
||||
trs_id,
|
||||
)
|
||||
|
||||
await session.commit()
|
||||
await uow.commit()
|
||||
|
||||
logger.info("Bill %s marked as PAID for TrsId %s", invoice_id, trs_id)
|
||||
|
||||
@@ -8,7 +8,7 @@ from sqlalchemy.dialects.postgresql import insert
|
||||
|
||||
from config import cfg
|
||||
from db.models import RWSyncOutbox, Subscription
|
||||
from db.session import async_session
|
||||
from db.session import UnitOfWork, async_session
|
||||
from external.rw import sync_subscription_by_telegram_id
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -48,7 +48,8 @@ async def enqueue_all_rw_syncs(session: "AsyncSession") -> int:
|
||||
return count
|
||||
|
||||
|
||||
async def process_rw_syncs(session: "AsyncSession", batch_size: int = 50) -> int:
|
||||
async def process_rw_syncs(uow: UnitOfWork, batch_size: int = 50) -> int:
|
||||
session = uow.session
|
||||
now = datetime.now(UTC)
|
||||
jobs = await session.scalars(
|
||||
select(RWSyncOutbox)
|
||||
@@ -63,7 +64,7 @@ async def process_rw_syncs(session: "AsyncSession", batch_size: int = 50) -> int
|
||||
jobs = list(jobs)
|
||||
for job in jobs:
|
||||
job.locked_until = now + LOCK_DURATION
|
||||
await session.commit()
|
||||
await uow.commit()
|
||||
|
||||
for job in jobs:
|
||||
subscription = job.subscription
|
||||
@@ -81,7 +82,7 @@ async def process_rw_syncs(session: "AsyncSession", batch_size: int = 50) -> int
|
||||
RWSyncOutbox.revision == job.revision,
|
||||
)
|
||||
)
|
||||
await session.commit()
|
||||
await uow.commit()
|
||||
continue
|
||||
|
||||
delay = min(timedelta(minutes=2**job.attempts), MAX_RETRY_DELAY)
|
||||
@@ -94,7 +95,7 @@ async def process_rw_syncs(session: "AsyncSession", batch_size: int = 50) -> int
|
||||
locked_until=None,
|
||||
)
|
||||
)
|
||||
await session.commit()
|
||||
await uow.commit()
|
||||
logger.warning("RW sync failed for subscription_id=%s", subscription.id)
|
||||
|
||||
return len(jobs)
|
||||
@@ -104,8 +105,8 @@ async def run_rw_sync_worker() -> None:
|
||||
interval = cfg.rw_sync_interval_minutes * 60
|
||||
while True:
|
||||
try:
|
||||
async with async_session() as session:
|
||||
await process_rw_syncs(session)
|
||||
async with async_session() as session, UnitOfWork(session) as uow:
|
||||
await process_rw_syncs(uow)
|
||||
except Exception:
|
||||
logger.exception("RW sync worker iteration failed")
|
||||
await asyncio.sleep(interval)
|
||||
@@ -116,8 +117,9 @@ async def run_rw_sync_reconciler() -> None:
|
||||
while True:
|
||||
try:
|
||||
async with async_session() as session:
|
||||
count = await enqueue_all_rw_syncs(session)
|
||||
await session.commit()
|
||||
async with UnitOfWork(session) as uow:
|
||||
count = await enqueue_all_rw_syncs(uow.session)
|
||||
await uow.commit()
|
||||
logger.info("Queued %s subscriptions for RW reconciliation", count)
|
||||
except Exception:
|
||||
logger.exception("RW reconciliation iteration failed")
|
||||
|
||||
Reference in New Issue
Block a user