mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-29 12:06:51 +08:00
101 lines
3.5 KiB
Python
101 lines
3.5 KiB
Python
"""订阅写入事务适配器的启动装配。"""
|
|
|
|
from collections.abc import Callable
|
|
from contextlib import AbstractAsyncContextManager
|
|
from datetime import datetime, timezone
|
|
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.application.subscription.write import (
|
|
AfterCommitEffect,
|
|
AsyncAfterCommitEffect,
|
|
AsyncCreateSubscriptionCommand,
|
|
CreateSubscriptionCommand,
|
|
subscription_added_event_key,
|
|
)
|
|
from app.db.oper.subscribe import SubscribeOper
|
|
from app.db.uow import SqlAlchemyAsyncUnitOfWork, SqlAlchemyUnitOfWork
|
|
from app.startup.outbox import (
|
|
SqlAlchemyAsyncOutboxStager,
|
|
SqlAlchemyOutboxRepository,
|
|
)
|
|
|
|
|
|
class TransactionalSubscribeWriter:
|
|
"""为每次订阅新增创建独占会话,并把提交权交给 Application Command。"""
|
|
|
|
def __init__(
|
|
self,
|
|
sync_session: Callable[[], Session],
|
|
async_session: Callable[
|
|
[],
|
|
AbstractAsyncContextManager[AsyncSession],
|
|
],
|
|
) -> None:
|
|
"""注入同步会话工厂和异步会话作用域。"""
|
|
self._sync_session = sync_session
|
|
self._async_session = async_session
|
|
|
|
def add(
|
|
self,
|
|
identity: dict,
|
|
payload: dict,
|
|
username: str | None = None,
|
|
after_commit: AfterCommitEffect | None = None,
|
|
) -> tuple[int, str]:
|
|
"""在独占同步会话内执行一次完整订阅新增事务。"""
|
|
session = self._sync_session()
|
|
try:
|
|
outbox = SqlAlchemyOutboxRepository(session)
|
|
command = CreateSubscriptionCommand(
|
|
repository=SubscribeOper(session),
|
|
unit_of_work=SqlAlchemyUnitOfWork(session),
|
|
outbox=outbox,
|
|
)
|
|
|
|
def delivered(subscribe_id: int) -> None:
|
|
"""执行旧 post-commit 编排,全部成功后收口 durable intent。"""
|
|
if after_commit:
|
|
after_commit(subscribe_id)
|
|
outbox.complete_by_event_key(
|
|
subscription_added_event_key(subscribe_id, payload),
|
|
datetime.now(timezone.utc),
|
|
)
|
|
|
|
return command.execute(identity, payload, username, delivered)
|
|
finally:
|
|
session.close()
|
|
|
|
async def async_add(
|
|
self,
|
|
identity: dict,
|
|
payload: dict,
|
|
username: str | None = None,
|
|
after_commit: AsyncAfterCommitEffect | None = None,
|
|
) -> tuple[int, str]:
|
|
"""在独占异步会话作用域内执行一次完整订阅新增事务。"""
|
|
async with self._async_session() as session:
|
|
outbox = SqlAlchemyAsyncOutboxStager(session)
|
|
command = AsyncCreateSubscriptionCommand(
|
|
repository=SubscribeOper(session),
|
|
unit_of_work=SqlAlchemyAsyncUnitOfWork(session),
|
|
outbox=outbox,
|
|
)
|
|
|
|
async def delivered(subscribe_id: int) -> None:
|
|
"""异步执行旧编排,全部成功后收口 durable intent。"""
|
|
if after_commit:
|
|
await after_commit(subscribe_id)
|
|
await outbox.complete_by_event_key(
|
|
subscription_added_event_key(subscribe_id, payload),
|
|
datetime.now(timezone.utc),
|
|
)
|
|
|
|
return await command.execute(
|
|
identity,
|
|
payload,
|
|
username,
|
|
delivered,
|
|
)
|