1- import os
2- from fastapi import FastAPI , Depends , HTTPException , Request
3- from sqlalchemy .orm import Session
4- from slowapi import _rate_limit_exceeded_handler
5- from slowapi .errors import RateLimitExceeded
6- from app .mqtt .client import start_mqtt
1+ from fastapi import FastAPI
2+ from contextlib import asynccontextmanager
3+ import redis .asyncio as redis
4+ from fastapi_limiter import FastAPILimiter
75
8- # Import Module Kita
9- from app .core .database import engine , get_db , Base
10- from app .models .device import Device
6+ # Import komponen buatan kita
117from app .mqtt .client import start_mqtt
12- from app .api .v1 .devices import router as device_router
13- from app .core .limiter import limiter
14- from app .api .v1 import logs
8+ from app .api import logs
9+
10+ # --- SETTING LIFESPAN (Cara Modern Handle Startup/Shutdown) ---
11+ @asynccontextmanager
12+ async def lifespan (app : FastAPI ):
13+ # ==========================
14+ # 1. LOGIKA SAAT STARTUP
15+ # ==========================
16+ print ("🚀 System Starting Up..." )
17+
18+ # A. Nyalakan MQTT
19+ start_mqtt ()
20+ print ("✅ MQTT Listener Berjalan!" )
1521
16- # --- INIT DATABASE ---
17- Base .metadata .create_all (bind = engine )
22+ # B. Konek Redis & Init Rate Limiter
23+ try :
24+ # Gunakan "redis" karena itu nama service di docker-compose
25+ redis_connection = redis .from_url ("redis://redis:6379" , encoding = "utf-8" , decode_responses = True )
26+ await FastAPILimiter .init (redis_connection )
27+ print ("🛡️ Rate Limiter Activated!" )
28+ except Exception as e :
29+ print (f"⚠️ Gagal Konek Redis: { e } " )
1830
19- # --- SETUP APP ---
20- app = FastAPI (title = "IoT Backend API" )
31+ yield # <--- Di sini aplikasi berjalan melayani user
2132
22- # 1. Pasang State Limiter (Wajib di main.py)
23- app .state .limiter = limiter
24- app .add_exception_handler (RateLimitExceeded , _rate_limit_exceeded_handler )
33+ # ==========================
34+ # 2. LOGIKA SAAT SHUTDOWN
35+ # ==========================
36+ print ("🛑 System Shutting Down..." )
37+ await redis_connection .close ()
2538
26- # 2. Register Router
27- app .include_router (device_router , prefix = "/api/v1" , tags = ["Devices" ])
28- app .include_router (logs .router , prefix = "/api/logs" , tags = ["Sensor Logs" ])
39+ # --- INISIALISASI APP DENGAN LIFESPAN ---
40+ app = FastAPI (title = "PCB Backend API" , lifespan = lifespan )
2941
30- # --- STARTUP EVENTS ---
31- @app .on_event ("startup" )
32- async def startup_event ():
33- print ("🚀 Menyalakan Mesin MQTT..." )
34- print ("🚀 APLIKASI UPDATE DARI GITHUB ACTION BERHASIL!" )
35- start_mqtt ()
42+ # --- DAFTARKAN ROUTER ---
43+ app .include_router (logs .router , prefix = "/api/logs" , tags = ["Sensor Logs" ])
3644
37- # --- ROOT ENDPOINT (Contoh penggunaan di main.py) ---
3845@app .get ("/" )
39- @limiter .limit ("5/minute" ) # Contoh: IP yg sama cuma boleh refresh halaman ini 5x semenit
40- def read_root (request : Request ): # <--- JANGAN LUPA request: Request
41- return {
42- "status" : "Backend is Running" ,
43- "service" : "IoT Platform" ,
44- "docs_url" : "/docs"
45- }
46-
47- # --- ENDPOINT TEST DUMMY (Boleh dihapus nanti kalau production) ---
48- @app .post ("/test-create-device" )
49- def create_dummy_device (device_id : str , pin : str , db : Session = Depends (get_db )):
50- existing_device = db .query (Device ).filter (Device .device_id == device_id ).first ()
51- if existing_device :
52- raise HTTPException (status_code = 400 , detail = "Device ID sudah ada bro!" )
53- new_device = Device (device_id = device_id , pin_code = pin )
54- db .add (new_device )
55- db .commit ()
56- db .refresh (new_device )
57- return {"message" : "Sukses nambah alat!" , "data" : new_device }
46+ def read_root ():
47+ return {"message" : "PCB Backend is Running & Protected!" }
0 commit comments