All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m0s
Replace every direct cross-app services.* call with HTTP-based communication: call_action() for writes, fetch_data() for reads. Each app now registers only its own domain service. Infrastructure: - shared/infrastructure/actions.py — POST client for /internal/actions/ - shared/infrastructure/data_client.py — GET client for /internal/data/ - shared/contracts/dtos.py — dto_to_dict/dto_from_dict serialization Action endpoints (writes): - events: 8 handlers (ticket adjust, claim/confirm, toggle, adopt) - market: 2 handlers (create/soft-delete marketplace) - cart: 1 handler (adopt cart for user) Data endpoints (reads): - blog: 4 (post-by-slug/id, posts-by-ids, search-posts) - events: 10 (pending entries/tickets, entries/tickets for page/order, entry-ids, associated-entries, calendars, visible-entries-for-period) - market: 1 (marketplaces-for-container) - cart: 1 (cart-summary) Service registration cleanup: - blog→blog+federation, events→calendar+federation, market→market+federation, cart→cart only, federation→federation only, account→nothing - Stubs reduced to minimal StubFederationService Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
"""Typed singleton registry for domain services.
|
|
|
|
Each app registers ONLY its own domain service. Cross-app calls go
|
|
over HTTP via ``call_action()`` (writes) and ``fetch_data()`` (reads).
|
|
|
|
Usage::
|
|
|
|
from shared.services.registry import services
|
|
|
|
# Register at app startup (own domain only)
|
|
services.blog = SqlBlogService()
|
|
|
|
# Use locally within the owning app
|
|
post = await services.blog.get_post_by_slug(session, slug)
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from shared.contracts.protocols import (
|
|
BlogService,
|
|
CalendarService,
|
|
MarketService,
|
|
CartService,
|
|
FederationService,
|
|
)
|
|
|
|
|
|
class _ServiceRegistry:
|
|
"""Central registry holding one implementation per domain.
|
|
|
|
Properties return the registered implementation or raise
|
|
``RuntimeError`` if nothing is registered. Use ``has(name)``
|
|
to check before access when the domain might be absent.
|
|
"""
|
|
|
|
def __init__(self) -> None:
|
|
self._blog: BlogService | None = None
|
|
self._calendar: CalendarService | None = None
|
|
self._market: MarketService | None = None
|
|
self._cart: CartService | None = None
|
|
self._federation: FederationService | None = None
|
|
|
|
# -- blog -----------------------------------------------------------------
|
|
@property
|
|
def blog(self) -> BlogService:
|
|
if self._blog is None:
|
|
raise RuntimeError("BlogService not registered")
|
|
return self._blog
|
|
|
|
@blog.setter
|
|
def blog(self, impl: BlogService) -> None:
|
|
self._blog = impl
|
|
|
|
# -- calendar -------------------------------------------------------------
|
|
@property
|
|
def calendar(self) -> CalendarService:
|
|
if self._calendar is None:
|
|
raise RuntimeError("CalendarService not registered")
|
|
return self._calendar
|
|
|
|
@calendar.setter
|
|
def calendar(self, impl: CalendarService) -> None:
|
|
self._calendar = impl
|
|
|
|
# -- market ---------------------------------------------------------------
|
|
@property
|
|
def market(self) -> MarketService:
|
|
if self._market is None:
|
|
raise RuntimeError("MarketService not registered")
|
|
return self._market
|
|
|
|
@market.setter
|
|
def market(self, impl: MarketService) -> None:
|
|
self._market = impl
|
|
|
|
# -- cart -----------------------------------------------------------------
|
|
@property
|
|
def cart(self) -> CartService:
|
|
if self._cart is None:
|
|
raise RuntimeError("CartService not registered")
|
|
return self._cart
|
|
|
|
@cart.setter
|
|
def cart(self, impl: CartService) -> None:
|
|
self._cart = impl
|
|
|
|
# -- federation -----------------------------------------------------------
|
|
@property
|
|
def federation(self) -> FederationService:
|
|
if self._federation is None:
|
|
raise RuntimeError("FederationService not registered")
|
|
return self._federation
|
|
|
|
@federation.setter
|
|
def federation(self, impl: FederationService) -> None:
|
|
self._federation = impl
|
|
|
|
# -- introspection --------------------------------------------------------
|
|
def has(self, name: str) -> bool:
|
|
"""Check whether a domain service is registered."""
|
|
return getattr(self, f"_{name}", None) is not None
|
|
|
|
|
|
# Module-level singleton — import this everywhere.
|
|
services = _ServiceRegistry()
|