JeremyMikaleff commited on
Commit
20197fb
·
1 Parent(s): 0fbbb00

feat: connect FastAPI to Neon PostgreSQL

Browse files
Files changed (3) hide show
  1. app.py +25 -3
  2. database.py +31 -0
  3. requirements.txt +5 -0
app.py CHANGED
@@ -1,8 +1,13 @@
1
- from fastapi import FastAPI
 
 
2
 
3
  app = FastAPI(
4
  title="Anderson — Semantic Retrieval for RAG",
5
- description="Démonstration de recherche sémantique destinée à alimenter un système RAG.",
 
 
 
6
  version="0.1.0",
7
  )
8
 
@@ -17,4 +22,21 @@ def root():
17
 
18
  @app.get("/health")
19
  def health():
20
- return {"status": "ok"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException, status
2
+
3
+ from database import check_database_connection
4
 
5
  app = FastAPI(
6
  title="Anderson — Semantic Retrieval for RAG",
7
+ description=(
8
+ "Démonstration de recherche sémantique destinée "
9
+ "à alimenter un système RAG."
10
+ ),
11
  version="0.1.0",
12
  )
13
 
 
22
 
23
  @app.get("/health")
24
  def health():
25
+ return {"status": "ok"}
26
+
27
+
28
+ @app.get("/health/database")
29
+ def database_health():
30
+ try:
31
+ connected = check_database_connection()
32
+ except Exception:
33
+ raise HTTPException(
34
+ status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
35
+ detail="Database unavailable",
36
+ )
37
+
38
+ return {
39
+ "status": "ok",
40
+ "database": "connected",
41
+ "connection_test": connected,
42
+ }
database.py ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from dotenv import load_dotenv
4
+ from sqlalchemy import create_engine, text
5
+
6
+ load_dotenv()
7
+
8
+ database_url = os.getenv("DATABASE_URL")
9
+
10
+ if not database_url:
11
+ raise RuntimeError("La variable DATABASE_URL est absente.")
12
+
13
+ # SQLAlchemy doit utiliser explicitement le pilote psycopg.
14
+ sqlalchemy_database_url = database_url.replace(
15
+ "postgresql://",
16
+ "postgresql+psycopg://",
17
+ 1,
18
+ )
19
+
20
+ engine = create_engine(
21
+ sqlalchemy_database_url,
22
+ pool_pre_ping=True,
23
+ pool_size=5,
24
+ max_overflow=5,
25
+ )
26
+
27
+
28
+ def check_database_connection() -> bool:
29
+ with engine.connect() as connection:
30
+ result = connection.execute(text("SELECT 1"))
31
+ return result.scalar_one() == 1
requirements.txt CHANGED
@@ -7,6 +7,7 @@ colorama==0.4.6
7
  fastapi==0.141.1
8
  filelock==3.32.3
9
  fsspec==2026.7.0
 
10
  h11==0.16.0
11
  hf-xet==1.6.0
12
  httpcore==1.0.9
@@ -15,14 +16,18 @@ httpx==0.28.1
15
  huggingface_hub==1.28.0
16
  idna==3.19
17
  packaging==26.3
 
 
18
  pydantic==2.13.4
19
  pydantic_core==2.46.4
20
  python-dotenv==1.2.3
21
  PyYAML==6.0.3
 
22
  starlette==1.6.0
23
  tqdm==4.70.0
24
  typing-inspection==0.4.4
25
  typing_extensions==4.16.0
 
26
  uvicorn==0.52.4
27
  watchfiles==1.2.0
28
  websockets==17.0.1
 
7
  fastapi==0.141.1
8
  filelock==3.32.3
9
  fsspec==2026.7.0
10
+ greenlet==3.5.5
11
  h11==0.16.0
12
  hf-xet==1.6.0
13
  httpcore==1.0.9
 
16
  huggingface_hub==1.28.0
17
  idna==3.19
18
  packaging==26.3
19
+ psycopg==3.3.4
20
+ psycopg-binary==3.3.4
21
  pydantic==2.13.4
22
  pydantic_core==2.46.4
23
  python-dotenv==1.2.3
24
  PyYAML==6.0.3
25
+ SQLAlchemy==2.0.52
26
  starlette==1.6.0
27
  tqdm==4.70.0
28
  typing-inspection==0.4.4
29
  typing_extensions==4.16.0
30
+ tzdata==2026.3
31
  uvicorn==0.52.4
32
  watchfiles==1.2.0
33
  websockets==17.0.1