TIF_E41253310/Backend/app/config/database.py

65 lines
3.5 KiB
Python

# Mengimpor modul Any untuk type hint fleksibel dari modul standar typing Python
from typing import Any
# Mengimpor fungsi create_engine dari SQLAlchemy untuk membuat engine penghubung ke database
from sqlalchemy import create_engine
# Mengimpor sessionmaker dari SQLAlchemy ORM untuk membuat factory pembentuk sesi transaksi database
from sqlalchemy.orm import sessionmaker
# Mengimpor objek konfigurasi global settings yang berisi DATABASE_URL
from app.config.config import settings
# Memeriksa apakah database yang digunakan adalah SQLite berdasarkan awalan protokol connection string
is_sqlite = settings.DATABASE_URL.startswith("sqlite")
# Jika database adalah SQLite, nonaktifkan check_same_thread agar session dapat digunakan lintas thread FastAPI; jika MySQL/PostgreSQL gunakan dictionary kosong
connect_args = {"check_same_thread": False} if is_sqlite else {}
# Menyiapkan dictionary parameter konfigurasi untuk SQLAlchemy engine
engine_kwargs: dict[str, Any] = {
# Argumen koneksi level driver (khusus SQLite atau kosong untuk MySQL)
"connect_args": connect_args,
# Menentukan apakah setiap query mentah dicetak ke terminal (False = dinonaktifkan demi performa dan kebersihan log)
"echo": False, # Matikan SQL echo agar tidak memperlambat I/O console terminal
}
# Jika bukan SQLite (misal MySQL pada produksi atau pengembangan lokal), tambahkan konfigurasi connection pooling
if not is_sqlite:
engine_kwargs.update({
# pool_pre_ping: Memeriksa kesehatan koneksi sebelum query dijalankan untuk mencegah error koneksi mati (MySQL server has gone away)
"pool_pre_ping": True,
# pool_recycle: Mendaur ulang koneksi database setiap 1800 detik (30 menit) agar tidak diputus paksa oleh timeout server MySQL
"pool_recycle": 1800,
# pool_size: Jumlah koneksi database tetap yang dipertahankan dalam memory pool
"pool_size": 15,
# max_overflow: Jumlah koneksi tambahan maksimal yang diizinkan dibuat saat lalu lintas request sedang tinggi
"max_overflow": 25,
})
# Membuat instance Engine SQLAlchemy sebagai gerbang utama komunikasi antara aplikasi FastAPI dan server database
engine = create_engine(
# URL database (contoh: mysql+pymysql://root:@localhost:3306/tracerstudy_db)
settings.DATABASE_URL,
# Unpack dictionary argumen konfigurasi engine yang telah disesuaikan
**engine_kwargs
)
# Membuat class factory SessionLocal untuk menghasilkan sesi database baru pada setiap request
# autocommit=False: Transaksi tidak langsung di-commit otomatis (memungkinkan commit/rollback manual demi konsistensi data)
# autoflush=False: Mencegah perubahan di-flush ke database sebelum commit atau query eksplisit
# bind=engine: Mengikat sesi ini ke engine database yang telah dibuat
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# Fungsi Dependency Injection untuk FastAPI yang menyediakan sesi database ke setiap endpoint API
def get_db():
"""
Menghasilkan (yields) instance sesi database untuk satu request HTTP.
Memastikan koneksi selalu ditutup (closed) di blok finally bahkan jika terjadi error selama eksekusi request.
"""
# Membuka sesi database baru dari factory SessionLocal
db = SessionLocal()
try:
# Memberikan sesi database aktif ke controller/endpoint yang memanggilnya
yield db
finally:
# Menutup sesi database setelah request selesai diproses agar koneksi dikembalikan ke connection pool dan tidak terjadi memory leak
db.close()