Decouple cart/market DBs: denormalize product data, AP internal inbox, OAuth scraper auth
Remove cross-DB relationships (CartItem.product, CartItem.market_place, OrderItem.product) that break with per-service databases. Denormalize product and marketplace fields onto cart_items/order_items at write time. - Add AP internal inbox infrastructure (shared/infrastructure/internal_inbox*) for synchronous inter-service writes via HMAC-authenticated POST - Cart inbox blueprint handles Add/Remove/Update rose:CartItem activities - Market app sends AP activities to cart inbox instead of writing CartItem directly - Cart services use denormalized columns instead of cross-DB hydration/joins - Add marketplaces-by-ids data endpoint to market service - Alembic migration adds denormalized columns to cart_items and order_items - Add OAuth device flow auth to market scraper persist_api (artdag client pattern) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -410,19 +410,18 @@ class CartItem(Base):
|
||||
nullable=True,
|
||||
)
|
||||
|
||||
# Cross-domain relationships — explicit join, viewonly (no FK constraint)
|
||||
market_place: Mapped["MarketPlace | None"] = relationship(
|
||||
"MarketPlace",
|
||||
primaryjoin="CartItem.market_place_id == MarketPlace.id",
|
||||
foreign_keys="[CartItem.market_place_id]",
|
||||
viewonly=True,
|
||||
)
|
||||
product: Mapped["Product"] = relationship(
|
||||
"Product",
|
||||
primaryjoin="CartItem.product_id == Product.id",
|
||||
foreign_keys="[CartItem.product_id]",
|
||||
viewonly=True,
|
||||
)
|
||||
# Denormalized product data (snapshotted at write time)
|
||||
product_title: Mapped[str | None] = mapped_column(String(512), nullable=True)
|
||||
product_slug: Mapped[str | None] = mapped_column(String(512), nullable=True)
|
||||
product_image: Mapped[str | None] = mapped_column(Text, nullable=True)
|
||||
product_brand: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
product_regular_price: Mapped[float | None] = mapped_column(Numeric(12, 2), nullable=True)
|
||||
product_special_price: Mapped[float | None] = mapped_column(Numeric(12, 2), nullable=True)
|
||||
product_price_currency: Mapped[str | None] = mapped_column(String(16), nullable=True)
|
||||
|
||||
# Denormalized marketplace data (snapshotted at write time)
|
||||
market_place_name: Mapped[str | None] = mapped_column(String(255), nullable=True)
|
||||
market_place_container_id: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
|
||||
__table_args__ = (
|
||||
Index("ix_cart_items_user_product", "user_id", "product_id"),
|
||||
|
||||
@@ -87,6 +87,8 @@ class OrderItem(Base):
|
||||
nullable=False,
|
||||
)
|
||||
product_title: Mapped[Optional[str]] = mapped_column(String(512), nullable=True)
|
||||
product_slug: Mapped[Optional[str]] = mapped_column(String(512), nullable=True)
|
||||
product_image: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
||||
|
||||
quantity: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
|
||||
unit_price: Mapped[float] = mapped_column(Numeric(12, 2), nullable=False)
|
||||
@@ -102,12 +104,3 @@ class OrderItem(Base):
|
||||
"Order",
|
||||
back_populates="items",
|
||||
)
|
||||
|
||||
# Cross-domain relationship — explicit join, viewonly (no FK constraint)
|
||||
product: Mapped["Product"] = relationship(
|
||||
"Product",
|
||||
primaryjoin="OrderItem.product_id == Product.id",
|
||||
foreign_keys="[OrderItem.product_id]",
|
||||
viewonly=True,
|
||||
lazy="selectin",
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user