Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions backend/alwrity_utils/router_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,22 @@ def __init__(self, app: FastAPI):
self.app = app
self.included_routers = []
self.failed_routers = []
self._included_router_names = set()

def include_router_safely(self, router, router_name: str = None) -> bool:
"""Include a router safely with error handling."""
verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true"
router_name = router_name or getattr(router, 'prefix', 'unknown')

if router_name in self._included_router_names:
if verbose:
logger.info(f"↩️ Router already included, skipping duplicate: {router_name}")
return True

try:
self.app.include_router(router)
router_name = router_name or getattr(router, 'prefix', 'unknown')
self.included_routers.append(router_name)
self._included_router_names.add(router_name)
if verbose:
logger.info(f"✅ Router included successfully: {router_name}")
return True
Expand All @@ -40,19 +47,21 @@ def include_core_routers(self) -> bool:
# Import os locally to avoid UnboundLocalError if it's shadowed
import os
verbose = os.getenv("ALWRITY_VERBOSE", "false").lower() == "true"
demo_mode = os.getenv("ALWRITY_DEMO_MODE", "false").lower() == "true"

try:
if verbose:
logger.info("Including core routers...")
logger.info(f"Including core routers (demo_mode={demo_mode})...")

# Subscription router MUST always be included (including demo mode) so
# payment/preflight/subscription endpoints remain available.
from api.subscription import router as subscription_router
self.include_router_safely(subscription_router, "subscription")

# Component logic router
from api.component_logic import router as component_logic_router
self.include_router_safely(component_logic_router, "component_logic")

# Subscription router
from api.subscription import router as subscription_router
self.include_router_safely(subscription_router, "subscription")

# Step 3 Research router (core onboarding functionality)
from api.onboarding_utils.step3_routes import router as step3_research_router
self.include_router_safely(step3_research_router, "step3_research")
Expand Down
3 changes: 3 additions & 0 deletions backend/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,9 @@ async def onboarding_status():

# Include routers using modular utilities
router_manager.include_core_routers()
# Safety net: keep subscription routes available even if core inclusion flow changes
# in special modes (e.g., demo mode). De-dup is handled by RouterManager.
router_manager.include_router_safely(subscription_router, "subscription")
router_manager.include_optional_routers()

# Include assets serving router (must be mounted to serve generated images)
Expand Down
3 changes: 3 additions & 0 deletions backend/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,9 @@ async def onboarding_status():

# Include routers using modular utilities
router_manager.include_core_routers()
# Safety net: keep subscription routes available even if core inclusion flow changes
# in special modes (e.g., demo mode). De-dup is handled by RouterManager.
router_manager.include_router_safely(subscription_router, "subscription")
router_manager.include_optional_routers()

# SEO Dashboard endpoints
Expand Down