Skip to content
Open
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
19 changes: 19 additions & 0 deletions Backend/app/db/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@

# Initialize async SQLAlchemy components
try:
# Supabase (and some other cloud providers) may have issues with IPv6.
# We can try to force parameters or handle connection logic robustly.
# For now, we wrap the engine creation in a try-except block to prevent
# the entire app from crashing if credentials are wrong or DB is unreachable.

# "ssl": "require" is critical for Supabase connections
engine = create_async_engine(
DATABASE_URL, echo=True, connect_args={"ssl": "require"}
)
Expand All @@ -30,11 +36,24 @@
print("✅ Database connected successfully!")
except SQLAlchemyError as e:
print(f"❌ Error connecting to the database: {e}")
# Set to None so main.py can check against them
engine = None
AsyncSessionLocal = None
Base = None


async def get_db():
"""
Dependency generator for database sessions.

Yields:
AsyncSession: An asynchronous database session.

Raises:
RuntimeError: If the database engine is not initialized.
"""
if AsyncSessionLocal is None:
raise RuntimeError("Database engine is not initialized. Check your connection settings.")

async with AsyncSessionLocal() as session:
yield session
32 changes: 31 additions & 1 deletion Backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@

# Async function to create database tables with exception handling
async def create_tables():
"""
Creates database tables asynchronously if the database engine is available.

This function attempts to create all tables defined in the SQLAlchemy models
(models.Base and chat.Base). It handles cases where the database engine
might not be initialized due to connection errors.
"""
if engine is None:
print("⚠️ Database engine is not available. Skipping table creation.")
return

try:
async with engine.begin() as conn:
await conn.run_sync(models.Base.metadata.create_all)
Expand All @@ -31,9 +42,22 @@ async def create_tables():
# Lifespan context manager for startup and shutdown events
@asynccontextmanager
async def lifespan(app: FastAPI):
"""
Lifespan context manager for the FastAPI application.

Handles startup and shutdown events. On startup, it attempts to
create database tables and seed the database.

Args:
app (FastAPI): The FastAPI application instance.
"""
print("App is starting...")
await create_tables()
await seed_db()
# verify engine is not None before seeding
if engine:
await seed_db()
else:
print("⚠️ Database engine is not available. Skipping data seeding.")
yield
print("App is shutting down...")

Expand All @@ -60,6 +84,12 @@ async def lifespan(app: FastAPI):

@app.get("/")
async def home():
"""
Root endpoint for the API.

Returns:
dict: A welcome message.
"""
try:
return {"message": "Welcome to Inpact API!"}
except Exception as e:
Expand Down
28 changes: 28 additions & 0 deletions Backend/app/services/db_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@


def match_creators_for_brand(sponsorship_id: str) -> List[Dict[str, Any]]:
"""
Finds creator matches for a given brand sponsorship.

Analyzes audience insights for all creators and calculates a match score
based on the sponsorship's requirements (age, location, engagement rate, budget).

Args:
sponsorship_id (str): The unique identifier of the sponsorship.

Returns:
List[Dict[str, Any]]: A list of matching creators, including their match details.
Returns an empty list if the sponsorship is not found or
no suitable creators are found.
"""
# Fetch sponsorship details
sponsorship_resp = supabase.table("sponsorships").select("*").eq("id", sponsorship_id).execute()
if not sponsorship_resp.data:
Expand Down Expand Up @@ -49,6 +63,20 @@ def match_creators_for_brand(sponsorship_id: str) -> List[Dict[str, Any]]:


def match_brands_for_creator(creator_id: str) -> List[Dict[str, Any]]:
"""
Finds brand sponsorship matches for a given creator.

Analyzes all available sponsorships and calculates a match score based on
the creator's audience insights (age, location, engagement, price).

Args:
creator_id (str): The unique identifier of the creator.

Returns:
List[Dict[str, Any]]: A list of matching sponsorships, including their match details.
Returns an empty list if the creator's audience data is not found
or no suitable sponsorships are found.
"""
# Fetch creator's audience insights
audience_resp = supabase.table("audience_insights").select("*").eq("user_id", creator_id).execute()
if not audience_resp.data:
Expand Down