Phase 5: Replace HTTP cart adoption with event-driven adoption
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 48s

Emit user.logged_in event instead of HTTP POST to /internal/cart/adopt.
Event is emitted inside the last_login_at transaction for atomicity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-14 17:35:55 +00:00
parent 75a5d520e8
commit a24e5c6407

View File

@@ -31,7 +31,7 @@ from shared.infrastructure.urls import coop_url
from sqlalchemy.orm import selectinload
from shared.browser.app.redis_cacher import clear_cache
from shared.infrastructure.cart_identity import current_cart_identity
from shared.infrastructure.internal_api import post as api_post
from shared.events import emit_event
from .services import pop_login_redirect_target, store_login_redirect_target
from .services.auth_operations import (
get_app_host,
@@ -254,20 +254,23 @@ def register(url_prefix="/auth"):
u2 = await s.get(User, user_id)
if u2:
u2.last_login_at = now
# s.begin() will commit on successful exit
# Emit adoption event inside this transaction
if anon_session_id:
await emit_event(
s,
"user.logged_in",
"user",
user_id,
{
"user_id": user_id,
"session_id": anon_session_id,
},
)
except SQLAlchemyError:
current_app.logger.exception(
"[auth] non-fatal DB update after Ghost upsert for user_id=%s", user_id
)
# Adopt cart + calendar entries via cart app internal API
if anon_session_id:
await api_post(
"cart",
"/internal/cart/adopt",
json={"user_id": user_id, "session_id": anon_session_id},
)
# ---- Finalize login ----
qsession[SESSION_USER_KEY] = user_id