Spaces:
Sleeping
Sleeping
oracle DB Connection
Browse files- .gitignore +40 -0
- Dockerfile +2 -2
- HF_SECRETS_μ€μ .md +65 -0
- README.md +90 -9
- app.py +120 -51
- env_example.txt +10 -0
- requirements.txt +5 -5
- start.py +23 -0
- κ²μ_κ²°κ³Ό.md +237 -0
- λ°°ν¬_체ν¬λ¦¬μ€νΈ.md +191 -0
.gitignore
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Python
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.py[cod]
|
| 4 |
+
*$py.class
|
| 5 |
+
*.so
|
| 6 |
+
.Python
|
| 7 |
+
env/
|
| 8 |
+
venv/
|
| 9 |
+
ENV/
|
| 10 |
+
*.egg-info/
|
| 11 |
+
dist/
|
| 12 |
+
build/
|
| 13 |
+
|
| 14 |
+
# νκ²½ λ³μ (μ€μ!)
|
| 15 |
+
.env
|
| 16 |
+
.env.*
|
| 17 |
+
!.env.example
|
| 18 |
+
|
| 19 |
+
# Oracle Wallet (μ€μ!)
|
| 20 |
+
wallet/
|
| 21 |
+
*.zip
|
| 22 |
+
wallet_base64.txt
|
| 23 |
+
|
| 24 |
+
# IDE
|
| 25 |
+
.vscode/
|
| 26 |
+
.idea/
|
| 27 |
+
*.swp
|
| 28 |
+
*.swo
|
| 29 |
+
*~
|
| 30 |
+
|
| 31 |
+
# OS
|
| 32 |
+
.DS_Store
|
| 33 |
+
Thumbs.db
|
| 34 |
+
|
| 35 |
+
# λ‘κ·Έ
|
| 36 |
+
*.log
|
| 37 |
+
|
| 38 |
+
# μ
λ‘λ λ°μ΄ν°
|
| 39 |
+
uploads/
|
| 40 |
+
training_data/
|
Dockerfile
CHANGED
|
@@ -18,6 +18,6 @@ COPY . .
|
|
| 18 |
# Hugging Face Spaceλ ν¬νΈ 7860μ μ¬μ©ν©λλ€
|
| 19 |
EXPOSE 7860
|
| 20 |
|
| 21 |
-
#
|
| 22 |
-
CMD ["
|
| 23 |
|
|
|
|
| 18 |
# Hugging Face Spaceλ ν¬νΈ 7860μ μ¬μ©ν©λλ€
|
| 19 |
EXPOSE 7860
|
| 20 |
|
| 21 |
+
# start.pyλ‘ μλ² μ€ν (Wallet μλ λμ½λ©)
|
| 22 |
+
CMD ["python", "start.py"]
|
| 23 |
|
HF_SECRETS_μ€μ .md
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# π Hugging Face Secrets μ€μ κ°μ΄λ
|
| 2 |
+
|
| 3 |
+
## π μ€μ ν 5κ° Secrets
|
| 4 |
+
|
| 5 |
+
Hugging Face Space β Settings β Repository secrets β New secret
|
| 6 |
+
|
| 7 |
+
### 1οΈβ£ DB_USER
|
| 8 |
+
```
|
| 9 |
+
Value: ADMIN
|
| 10 |
+
```
|
| 11 |
+
|
| 12 |
+
### 2οΈβ£ DB_PASSWORD
|
| 13 |
+
```
|
| 14 |
+
Value: Oracle_DB_λΉλ°λ²νΈ
|
| 15 |
+
```
|
| 16 |
+
(Oracle Cloud Consoleμμ νμΈ λλ μ¬μ€μ )
|
| 17 |
+
|
| 18 |
+
### 3οΈβ£ DB_TNS_ALIAS
|
| 19 |
+
```
|
| 20 |
+
Value: musclecare_high
|
| 21 |
+
```
|
| 22 |
+
(wallet/tnsnames.oraμμ νμΈν μ΄λ¦)
|
| 23 |
+
|
| 24 |
+
### 4οΈβ£ WALLET_ZIP_B64 β κ°μ₯ μ€μ!
|
| 25 |
+
```
|
| 26 |
+
Value: (wallet_base64.txt νμΌ μ 체 λ΄μ©)
|
| 27 |
+
```
|
| 28 |
+
|
| 29 |
+
**μμ± λ°©λ²:**
|
| 30 |
+
```bash
|
| 31 |
+
# Wallet zip νμΌμ Base64λ‘ μΈμ½λ©
|
| 32 |
+
base64 -i ~/Downloads/Wallet_musclecare.zip -o wallet_base64.txt
|
| 33 |
+
|
| 34 |
+
# wallet_base64.txt νμΌ μ΄μ΄μ μ 체 볡μ¬
|
| 35 |
+
cat wallet_base64.txt | pbcopy # Mac
|
| 36 |
+
```
|
| 37 |
+
|
| 38 |
+
### 5οΈβ£ WALLET_PASSWORD
|
| 39 |
+
```
|
| 40 |
+
Value: Wallet_λ€μ΄λ‘λμ_μ€μ ν_λΉλ°λ²νΈ
|
| 41 |
+
```
|
| 42 |
+
|
| 43 |
+
---
|
| 44 |
+
|
| 45 |
+
## β
μ€μ μλ£ ν
|
| 46 |
+
|
| 47 |
+
```bash
|
| 48 |
+
git push
|
| 49 |
+
```
|
| 50 |
+
|
| 51 |
+
μλμΌλ‘ λ°°ν¬λ©λλ€!
|
| 52 |
+
|
| 53 |
+
---
|
| 54 |
+
|
| 55 |
+
## π§ͺ λ°°ν¬ νμΈ
|
| 56 |
+
|
| 57 |
+
```bash
|
| 58 |
+
curl https://[username]-musclecare-api.hf.space/health
|
| 59 |
+
```
|
| 60 |
+
|
| 61 |
+
**μ±κ³΅ μλ΅:**
|
| 62 |
+
```json
|
| 63 |
+
{"ok": true, "db": 1}
|
| 64 |
+
```
|
| 65 |
+
|
README.md
CHANGED
|
@@ -1,12 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 10 |
---
|
| 11 |
|
| 12 |
-
|
|
|
|
| 1 |
+
# ποΈ MuscleCare FastAPI
|
| 2 |
+
|
| 3 |
+
Oracle Autonomous Database μ°λ FastAPI μλ² (Wallet κΈ°λ° mTLS)
|
| 4 |
+
|
| 5 |
+
## π μ£Όμ κΈ°λ₯
|
| 6 |
+
|
| 7 |
+
- π **Wallet κΈ°λ° mTLS μ°κ²°** - μ΅κ³ 보μ μμ€
|
| 8 |
+
- π€ **μ¬μ©μ μν μ
λ‘λ/λ€μ΄λ‘λ** - baseline + user_emb
|
| 9 |
+
- π **νΌλ‘λ λ‘κ·Έ μ μ₯** - Oracle DBμ μμ νκ² μ μ₯
|
| 10 |
+
|
| 11 |
---
|
| 12 |
+
|
| 13 |
+
## π‘ API μλν¬μΈνΈ
|
| 14 |
+
|
| 15 |
+
| μλν¬μΈνΈ | λ©μλ | μ€λͺ
|
|
| 16 |
+
|-----------|--------|------|
|
| 17 |
+
| `/health` | GET | DB μ°κ²° μν νμΈ |
|
| 18 |
+
| `/upload_state` | POST | μ¬μ©μ μν μ
λ‘λ |
|
| 19 |
+
| `/upload_logs` | POST | νΌλ‘λ λ‘κ·Έ μ
λ‘λ |
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
## π Hugging Face Space λ°°ν¬
|
| 24 |
+
|
| 25 |
+
### 1. Wallet Base64 μΈμ½λ©
|
| 26 |
+
|
| 27 |
+
```bash
|
| 28 |
+
base64 -i ~/Downloads/Wallet_musclecare.zip -o wallet_base64.txt
|
| 29 |
+
```
|
| 30 |
+
|
| 31 |
+
### 2. Hugging Face Secrets μ€μ (5κ°)
|
| 32 |
+
|
| 33 |
+
**Settings β Repository secrets**
|
| 34 |
+
|
| 35 |
+
| Secret | Value |
|
| 36 |
+
|--------|-------|
|
| 37 |
+
| `DB_USER` | `ADMIN` |
|
| 38 |
+
| `DB_PASSWORD` | Oracle DB λΉλ°λ²νΈ |
|
| 39 |
+
| `DB_TNS_ALIAS` | `musclecare_high` |
|
| 40 |
+
| `WALLET_ZIP_B64` | wallet_base64.txt μ 체 λ΄μ© |
|
| 41 |
+
| `WALLET_PASSWORD` | Wallet λΉλ°λ²νΈ |
|
| 42 |
+
|
| 43 |
+
### 3. Git Push
|
| 44 |
+
|
| 45 |
+
```bash
|
| 46 |
+
git push
|
| 47 |
+
```
|
| 48 |
+
|
| 49 |
+
**μλ λ°°ν¬!** `start.py`κ° Walletμ μλμΌλ‘ λμ½λ©νκ³ μλ²λ₯Ό μμν©λλ€.
|
| 50 |
+
|
| 51 |
+
---
|
| 52 |
+
|
| 53 |
+
## π§ͺ ν
μ€νΈ
|
| 54 |
+
|
| 55 |
+
### λ°°ν¬ ν:
|
| 56 |
+
|
| 57 |
+
```bash
|
| 58 |
+
# ν¬μ€ 체ν¬
|
| 59 |
+
curl https://[username]-musclecare-api.hf.space/health
|
| 60 |
+
|
| 61 |
+
# API λ¬Έμ
|
| 62 |
+
https://[username]-musclecare-api.hf.space/docs
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
### λ‘컬 ν
μ€νΈ:
|
| 66 |
+
|
| 67 |
+
```bash
|
| 68 |
+
# .env νμΌ μμ±
|
| 69 |
+
cp env_example.txt .env
|
| 70 |
+
nano .env # μ€μ κ° μ
λ ₯
|
| 71 |
+
|
| 72 |
+
# μλ² μ€ν
|
| 73 |
+
python app.py
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
---
|
| 77 |
+
|
| 78 |
+
## π μμΈ κ°μ΄λ
|
| 79 |
+
|
| 80 |
+
- **HF_SECRETS_μ€μ .md** - Secrets μ€μ λ°©λ²
|
| 81 |
+
- **DATA_ARCHITECTURE.md** - μ 체 μν€ν
μ²
|
| 82 |
+
|
| 83 |
+
---
|
| 84 |
+
|
| 85 |
+
## π 보μ
|
| 86 |
+
|
| 87 |
+
- β
`.gitignore` - .env, wallet/ μ μΈ
|
| 88 |
+
- β
Wallet Base64λ‘ μμ νκ² λ°°ν¬
|
| 89 |
+
- β
Secretsλ‘ νκ²½ λ³μ κ΄λ¦¬
|
| 90 |
+
|
| 91 |
---
|
| 92 |
|
| 93 |
+
Made with β€οΈ for MuscleCare
|
app.py
CHANGED
|
@@ -1,63 +1,132 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
from
|
| 4 |
-
import
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
app = FastAPI(
|
| 8 |
-
title="MuscleCare API",
|
| 9 |
-
description="MuscleCare νΌλ‘λ κ΄λ¦¬ μ ν리μΌμ΄μ
API",
|
| 10 |
-
version="1.0.0"
|
| 11 |
-
)
|
| 12 |
|
| 13 |
-
#
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
allow_methods=["*"],
|
| 19 |
-
allow_headers=["*"],
|
| 20 |
-
)
|
| 21 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
|
| 23 |
-
|
| 24 |
-
class HealthCheckResponse(BaseModel):
|
| 25 |
-
status: str
|
| 26 |
-
message: str
|
| 27 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 28 |
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
"docs": "/docs"
|
| 39 |
-
}
|
| 40 |
|
|
|
|
|
|
|
| 41 |
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
"""
|
| 45 |
-
ν¬μ€ μ²΄ν¬ μλν¬μΈνΈ
|
| 46 |
-
"""
|
| 47 |
-
return HealthCheckResponse(
|
| 48 |
-
status="healthy",
|
| 49 |
-
message="MuscleCare API is running successfully"
|
| 50 |
-
)
|
| 51 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
#
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
|
|
|
|
|
|
|
|
|
| 59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 60 |
|
| 61 |
-
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
from typing import List, Optional
|
| 4 |
+
from fastapi import FastAPI, HTTPException
|
| 5 |
+
from pydantic import BaseModel, Field, conlist
|
| 6 |
+
import oracledb
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
+
# ----- νκ²½ λ³μ -----
|
| 9 |
+
DB_USER = os.environ["DB_USER"]
|
| 10 |
+
DB_PASSWORD = os.environ["DB_PASSWORD"]
|
| 11 |
+
WALLET_DIR = os.environ["WALLET_DIR"]
|
| 12 |
+
WALLET_PASSWORD = os.environ["WALLET_PASSWORD"]
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
+
# tnsnames.ora μμ alias νμΈ (λ³΄ν΅ *_high)
|
| 15 |
+
TNS_ALIAS = os.environ.get("DB_TNS_ALIAS", "musclecare_high")
|
| 16 |
+
|
| 17 |
+
# ----- μ°κ²° ν: Thin + mTLS (μ§κ°) -----
|
| 18 |
+
# μ λ νΈμΆνμ§ λ§μΈμ: oracledb.init_oracle_client() # (Thickλ‘ λΉ μ Έμ μ€ν¨ κ°λ₯)
|
| 19 |
+
pool: oracledb.ConnectionPool = oracledb.create_pool(
|
| 20 |
+
user=DB_USER,
|
| 21 |
+
password=DB_PASSWORD,
|
| 22 |
+
dsn=TNS_ALIAS, # Wallet tnsnames.oraμ alias
|
| 23 |
+
config_dir=WALLET_DIR,
|
| 24 |
+
wallet_location=WALLET_DIR,
|
| 25 |
+
wallet_password=WALLET_PASSWORD,
|
| 26 |
+
min=1, max=4, increment=1,
|
| 27 |
+
homogeneous=True,
|
| 28 |
+
timeout=60,
|
| 29 |
+
retry_count=6, retry_delay=2
|
| 30 |
+
)
|
| 31 |
|
| 32 |
+
app = FastAPI(title="MuscleCare Hybrid Server (mTLS)")
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
+
# ----- λͺ¨λΈ -----
|
| 35 |
+
class StatePayload(BaseModel):
|
| 36 |
+
user_id: str
|
| 37 |
+
rms_base: Optional[float] = None
|
| 38 |
+
freq_base: Optional[float] = None
|
| 39 |
+
user_emb: Optional[List[float]] = Field(default=None, description="length=12")
|
| 40 |
+
model_version: Optional[str] = None
|
| 41 |
|
| 42 |
+
class LogItem(BaseModel):
|
| 43 |
+
user_id: str
|
| 44 |
+
session_id: Optional[str] = None
|
| 45 |
+
measure_date: str # 'YYYY-MM-DD'
|
| 46 |
+
rms: Optional[float] = None
|
| 47 |
+
freq: Optional[float] = None
|
| 48 |
+
fatigue: Optional[float] = None
|
| 49 |
+
mode: Optional[str] = Field(default="EMA", description="EMA/Hybrid/E2E")
|
| 50 |
+
window_count: Optional[int] = None
|
|
|
|
|
|
|
| 51 |
|
| 52 |
+
class LogsPayload(BaseModel):
|
| 53 |
+
items: conlist(LogItem, min_items=1)
|
| 54 |
|
| 55 |
+
# ----- μ νΈ -----
|
| 56 |
+
def clob_json(obj) -> str:
|
| 57 |
+
return json.dumps(obj, separators=(",", ":"), ensure_ascii=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
|
| 59 |
+
# ----- μλν¬μΈνΈ -----
|
| 60 |
+
@app.get("/health")
|
| 61 |
+
def health():
|
| 62 |
+
try:
|
| 63 |
+
with pool.acquire() as conn:
|
| 64 |
+
with conn.cursor() as cur:
|
| 65 |
+
cur.execute("SELECT 1 FROM DUAL")
|
| 66 |
+
v = cur.fetchone()[0]
|
| 67 |
+
return {"ok": True, "db": v}
|
| 68 |
+
except Exception as e:
|
| 69 |
+
raise HTTPException(500, f"DB health check failed: {e}")
|
| 70 |
|
| 71 |
+
@app.post("/upload_state")
|
| 72 |
+
def upload_state(p: StatePayload):
|
| 73 |
+
# MERGE INTO MuscleCare.user_state
|
| 74 |
+
try:
|
| 75 |
+
emb_json = None
|
| 76 |
+
if p.user_emb is not None:
|
| 77 |
+
if len(p.user_emb) != 12:
|
| 78 |
+
raise HTTPException(400, "user_emb must have length=12")
|
| 79 |
+
emb_json = clob_json(p.user_emb)
|
| 80 |
|
| 81 |
+
with pool.acquire() as conn:
|
| 82 |
+
with conn.cursor() as cur:
|
| 83 |
+
cur.execute("""
|
| 84 |
+
MERGE INTO MuscleCare.user_state t
|
| 85 |
+
USING (
|
| 86 |
+
SELECT :user_id AS user_id FROM dual
|
| 87 |
+
) s
|
| 88 |
+
ON (t.user_id = s.user_id)
|
| 89 |
+
WHEN MATCHED THEN UPDATE SET
|
| 90 |
+
rms_base = :rms_base,
|
| 91 |
+
freq_base = :freq_base,
|
| 92 |
+
user_emb = :user_emb,
|
| 93 |
+
model_version = :model_version,
|
| 94 |
+
last_sync = CURRENT_TIMESTAMP
|
| 95 |
+
WHEN NOT MATCHED THEN INSERT
|
| 96 |
+
(user_id, rms_base, freq_base, user_emb, model_version, last_sync)
|
| 97 |
+
VALUES
|
| 98 |
+
(:user_id, :rms_base, :freq_base, :user_emb, :model_version, CURRENT_TIMESTAMP)
|
| 99 |
+
""", dict(
|
| 100 |
+
user_id=p.user_id,
|
| 101 |
+
rms_base=p.rms_base,
|
| 102 |
+
freq_base=p.freq_base,
|
| 103 |
+
user_emb=emb_json,
|
| 104 |
+
model_version=p.model_version
|
| 105 |
+
))
|
| 106 |
+
conn.commit()
|
| 107 |
+
return {"ok": True}
|
| 108 |
+
except HTTPException:
|
| 109 |
+
raise
|
| 110 |
+
except Exception as e:
|
| 111 |
+
raise HTTPException(500, f"upload_state failed: {e}")
|
| 112 |
|
| 113 |
+
@app.post("/upload_logs")
|
| 114 |
+
def upload_logs(body: LogsPayload):
|
| 115 |
+
try:
|
| 116 |
+
rows = [(
|
| 117 |
+
it.user_id, it.session_id, it.measure_date,
|
| 118 |
+
it.rms, it.freq, it.fatigue, it.mode, it.window_count
|
| 119 |
+
) for it in body.items]
|
| 120 |
|
| 121 |
+
with pool.acquire() as conn:
|
| 122 |
+
with conn.cursor() as cur:
|
| 123 |
+
cur.executemany("""
|
| 124 |
+
INSERT INTO MuscleCare.fatigue_logs
|
| 125 |
+
(user_id, session_id, measure_date, rms, freq, fatigue, mode, window_count, created_at)
|
| 126 |
+
VALUES
|
| 127 |
+
(:1, :2, TO_DATE(:3,'YYYY-MM-DD'), :4, :5, :6, :7, :8, CURRENT_TIMESTAMP)
|
| 128 |
+
""", rows)
|
| 129 |
+
conn.commit()
|
| 130 |
+
return {"ok": True, "inserted": len(rows)}
|
| 131 |
+
except Exception as e:
|
| 132 |
+
raise HTTPException(500, f"upload_logs failed: {e}")
|
env_example.txt
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# λ‘컬 κ°λ°μ© νκ²½ λ³μ μμ
|
| 2 |
+
# μ΄ νμΌμ .envλ‘ λ³΅μ¬νκ³ μ€μ κ°μΌλ‘ λ³κ²½νμΈμ
|
| 3 |
+
# cp env_example.txt .env
|
| 4 |
+
|
| 5 |
+
DB_USER=ADMIN
|
| 6 |
+
DB_PASSWORD=your_db_password_here
|
| 7 |
+
DB_TNS_ALIAS=musclecare_high
|
| 8 |
+
WALLET_DIR=/Users/gimhyeon-u/workspace/MuscleCare-FastAPI/wallet
|
| 9 |
+
WALLET_PASSWORD=your_wallet_password_here
|
| 10 |
+
|
requirements.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
-
fastapi
|
| 2 |
-
uvicorn
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
|
|
|
| 1 |
+
fastapi
|
| 2 |
+
uvicorn
|
| 3 |
+
python-multipart
|
| 4 |
+
oracledb>=2.3
|
| 5 |
+
pydantic
|
start.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os, base64, zipfile, io, sys, tempfile, subprocess
|
| 2 |
+
|
| 3 |
+
def prepare_wallet_dir():
|
| 4 |
+
b64 = os.environ["WALLET_ZIP_B64"]
|
| 5 |
+
wallet_password = os.environ["WALLET_PASSWORD"]
|
| 6 |
+
# walletμ λ©λͺ¨λ¦¬->μμλλ ν λ¦¬λ‘ λ³΅μ
|
| 7 |
+
wallet_dir = tempfile.mkdtemp(prefix="wallet_")
|
| 8 |
+
zip_bytes = base64.b64decode(b64)
|
| 9 |
+
with zipfile.ZipFile(io.BytesIO(zip_bytes)) as z:
|
| 10 |
+
z.extractall(wallet_dir)
|
| 11 |
+
# μμ μ μν΄ κΆν μΆμ
|
| 12 |
+
for root, _, files in os.walk(wallet_dir):
|
| 13 |
+
for f in files:
|
| 14 |
+
os.chmod(os.path.join(root, f), 0o600)
|
| 15 |
+
# μ§κ° λΉλ°λ²νΈλ oracledbμμ μ¬μ©
|
| 16 |
+
os.environ["WALLET_DIR"] = wallet_dir
|
| 17 |
+
os.environ["WALLET_PASSWORD"] = wallet_password
|
| 18 |
+
return wallet_dir
|
| 19 |
+
|
| 20 |
+
if __name__ == "__main__":
|
| 21 |
+
prepare_wallet_dir()
|
| 22 |
+
# Uvicorn κΈ°λ
|
| 23 |
+
subprocess.run([sys.executable, "-m", "uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"])
|
κ²μ_κ²°κ³Ό.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# β
μ 체 κ²μ κ²°κ³Ό
|
| 2 |
+
|
| 3 |
+
## π κ²μ μλ£ - λ°°ν¬ μ€λΉ μλ£!
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
## π― ν΅μ¬ νμΌ κ΅¬μ‘°
|
| 8 |
+
|
| 9 |
+
```
|
| 10 |
+
MuscleCare-FastAPI/
|
| 11 |
+
βββ start.py β
Wallet λμ½λ© + μλ² λΆν
|
| 12 |
+
βββ app.py β
FastAPI μ± (κ°μνλ¨)
|
| 13 |
+
βββ Dockerfile β
start.py μ€ν
|
| 14 |
+
βββ requirements.txt β
μμ‘΄μ±
|
| 15 |
+
βββ .gitignore β
보μ νμΌ μ μΈ
|
| 16 |
+
βββ README.md β
νλ‘μ νΈ μ€λͺ
|
| 17 |
+
βββ env_example.txt β
νκ²½ λ³μ μμ
|
| 18 |
+
```
|
| 19 |
+
|
| 20 |
+
---
|
| 21 |
+
|
| 22 |
+
## β
μ½λ κ²μ κ²°κ³Ό
|
| 23 |
+
|
| 24 |
+
### 1. start.py β
|
| 25 |
+
```python
|
| 26 |
+
β
WALLET_ZIP_B64 νκ²½ λ³μ μ½κΈ°
|
| 27 |
+
β
Base64 λμ½λ©
|
| 28 |
+
β
zipfileλ‘ μμΆ ν΄μ
|
| 29 |
+
β
μμ λλ ν 리 μμ± (/tmp/wallet_)
|
| 30 |
+
β
νμΌ κΆν μ€μ (0o600)
|
| 31 |
+
β
WALLET_DIR, WALLET_PASSWORD νκ²½ λ³μ μ€μ
|
| 32 |
+
β
uvicorn subprocess μ€ν
|
| 33 |
+
```
|
| 34 |
+
|
| 35 |
+
**μλ νλ¦:**
|
| 36 |
+
```
|
| 37 |
+
start.py μ€ν
|
| 38 |
+
β
|
| 39 |
+
prepare_wallet_dir()
|
| 40 |
+
β
|
| 41 |
+
νκ²½ λ³μ: WALLET_DIR, WALLET_PASSWORD μ€μ
|
| 42 |
+
β
|
| 43 |
+
uvicorn app:app μ€ν
|
| 44 |
+
β
|
| 45 |
+
app.pyκ° WALLET_DIR μ¬μ©
|
| 46 |
+
```
|
| 47 |
+
|
| 48 |
+
### 2. app.py β
|
| 49 |
+
```python
|
| 50 |
+
β
νκ²½ λ³μ μ½κΈ°:
|
| 51 |
+
- DB_USER
|
| 52 |
+
- DB_PASSWORD
|
| 53 |
+
- WALLET_DIR (start.pyκ° μ€μ )
|
| 54 |
+
- WALLET_PASSWORD (start.pyκ° μ€μ )
|
| 55 |
+
- DB_TNS_ALIAS
|
| 56 |
+
|
| 57 |
+
β
oracledb.create_pool():
|
| 58 |
+
- user, password
|
| 59 |
+
- dsn=TNS_ALIAS
|
| 60 |
+
- config_dir=WALLET_DIR
|
| 61 |
+
- wallet_location=WALLET_DIR
|
| 62 |
+
- wallet_password=WALLET_PASSWORD
|
| 63 |
+
|
| 64 |
+
β
μλν¬μΈνΈ:
|
| 65 |
+
- GET /health β DB μ°κ²° ν
μ€νΈ
|
| 66 |
+
- POST /upload_state β user_state ν
μ΄λΈ UPSERT
|
| 67 |
+
- POST /upload_logs β fatigue_logs ν
μ΄λΈ INSERT
|
| 68 |
+
```
|
| 69 |
+
|
| 70 |
+
### 3. Dockerfile β
|
| 71 |
+
```dockerfile
|
| 72 |
+
β
Python 3.10-slim
|
| 73 |
+
β
requirements.txt μ€μΉ
|
| 74 |
+
β
μ½λ 볡μ¬
|
| 75 |
+
β
CMD ["python", "start.py"] β μ€μ!
|
| 76 |
+
```
|
| 77 |
+
|
| 78 |
+
### 4. requirements.txt β
|
| 79 |
+
```
|
| 80 |
+
β
fastapi
|
| 81 |
+
β
uvicorn
|
| 82 |
+
β
python-multipart
|
| 83 |
+
β
oracledb>=2.3
|
| 84 |
+
β
pydantic
|
| 85 |
+
```
|
| 86 |
+
|
| 87 |
+
### 5. .gitignore β
|
| 88 |
+
```
|
| 89 |
+
β
.env
|
| 90 |
+
β
wallet/
|
| 91 |
+
β
*.zip
|
| 92 |
+
β
wallet_base64.txt
|
| 93 |
+
β
__pycache__/
|
| 94 |
+
```
|
| 95 |
+
|
| 96 |
+
---
|
| 97 |
+
|
| 98 |
+
## π 보μ κ²μ
|
| 99 |
+
|
| 100 |
+
### β
Git μ μΈ νμΌ
|
| 101 |
+
```bash
|
| 102 |
+
git status | grep -E "(\.env|wallet/)"
|
| 103 |
+
```
|
| 104 |
+
**κ²°κ³Ό:** `.gitignore` νμΈ β μ μΈλ¨ β
|
| 105 |
+
|
| 106 |
+
### β
νκ²½ λ³μ μ¬μ©
|
| 107 |
+
- λͺ¨λ λ―Όκ° μ 보λ νκ²½ λ³μλ‘ κ΄λ¦¬
|
| 108 |
+
- μ½λμ νλμ½λ© μμ
|
| 109 |
+
|
| 110 |
+
### β
Wallet 보νΈ
|
| 111 |
+
- Gitμ ν¬ν¨ μ λ¨
|
| 112 |
+
- Base64λ‘ Secretsμ μμ νκ² μ μ₯
|
| 113 |
+
|
| 114 |
+
---
|
| 115 |
+
|
| 116 |
+
## π‘ API κ²μ
|
| 117 |
+
|
| 118 |
+
### μλν¬μΈνΈ ꡬ쑰
|
| 119 |
+
|
| 120 |
+
#### GET /health
|
| 121 |
+
```python
|
| 122 |
+
β
pool.acquire() μ¬μ©
|
| 123 |
+
β
SELECT 1 FROM DUAL
|
| 124 |
+
β
μ°κ²° μν λ°ν
|
| 125 |
+
```
|
| 126 |
+
|
| 127 |
+
#### POST /upload_state
|
| 128 |
+
```python
|
| 129 |
+
β
StatePayload κ²μ¦
|
| 130 |
+
β
user_emb κΈΈμ΄ μ²΄ν¬ (12)
|
| 131 |
+
β
MERGE INTO MuscleCare.user_state
|
| 132 |
+
β
CLOB JSON μ μ₯
|
| 133 |
+
β
νΈλμμ
commit
|
| 134 |
+
```
|
| 135 |
+
|
| 136 |
+
#### POST /upload_logs
|
| 137 |
+
```python
|
| 138 |
+
β
LogsPayload κ²μ¦
|
| 139 |
+
β
executemanyλ‘ λ°°μΉ INSERT
|
| 140 |
+
β
MuscleCare.fatigue_logs ν
μ΄λΈ
|
| 141 |
+
β
νΈλμμ
commit
|
| 142 |
+
```
|
| 143 |
+
|
| 144 |
+
---
|
| 145 |
+
|
| 146 |
+
## π λ°°ν¬ νλ‘μ° κ²μ
|
| 147 |
+
|
| 148 |
+
### Hugging Face Space μ€ν μμ:
|
| 149 |
+
|
| 150 |
+
```
|
| 151 |
+
1. Docker λΉλ
|
| 152 |
+
β
|
| 153 |
+
2. start.py μ€ν
|
| 154 |
+
β
|
| 155 |
+
3. prepare_wallet_dir()
|
| 156 |
+
- WALLET_ZIP_B64 νκ²½ λ³μ μ½κΈ° (Secrets)
|
| 157 |
+
- Base64 λμ½λ©
|
| 158 |
+
- /tmp/wallet_xxxxxμ μμΆ ν΄μ
|
| 159 |
+
- WALLET_DIR νκ²½ λ³μ μ€μ
|
| 160 |
+
β
|
| 161 |
+
4. uvicorn μ€ν
|
| 162 |
+
- app:app λ‘λ
|
| 163 |
+
β
|
| 164 |
+
5. app.py μ΄κΈ°ν
|
| 165 |
+
- νκ²½ λ³μ μ½κΈ°
|
| 166 |
+
- oracledb.create_pool() (WALLET_DIR μ¬μ©)
|
| 167 |
+
β
|
| 168 |
+
6. β
μλ² μ€ν μλ£
|
| 169 |
+
```
|
| 170 |
+
|
| 171 |
+
---
|
| 172 |
+
|
| 173 |
+
## π§ͺ ν
μ€νΈ 체ν¬λ¦¬μ€νΈ
|
| 174 |
+
|
| 175 |
+
### λ‘컬 ν
μ€νΈ (μ ν):
|
| 176 |
+
- [ ] wallet/ λλ ν 리 μ€λΉ
|
| 177 |
+
- [ ] νκ²½ λ³μ export
|
| 178 |
+
- [ ] `python app.py` μ€ν
|
| 179 |
+
- [ ] `curl http://localhost:7860/health` μ±κ³΅
|
| 180 |
+
|
| 181 |
+
### λ°°ν¬ ν ν
μ€νΈ (νμ):
|
| 182 |
+
- [ ] Logsμ "β
Wallet μμΆ ν΄μ μλ£"
|
| 183 |
+
- [ ] Logsμ "Uvicorn running"
|
| 184 |
+
- [ ] `curl https://[username]-xxx.hf.space/health`
|
| 185 |
+
- [ ] μλ΅: `{"ok": true, "db": 1}`
|
| 186 |
+
- [ ] `/docs` νμ΄μ§ μ κ·Ό κ°λ₯
|
| 187 |
+
|
| 188 |
+
---
|
| 189 |
+
|
| 190 |
+
## β λ°κ²¬λ λ¬Έμ μ
|
| 191 |
+
|
| 192 |
+
### μμ! β
|
| 193 |
+
|
| 194 |
+
λͺ¨λ νμΌμ΄ μ¬λ°λ₯΄κ² ꡬμ±λμμ΅λλ€.
|
| 195 |
+
|
| 196 |
+
---
|
| 197 |
+
|
| 198 |
+
## π― λ€μ λ¨κ³
|
| 199 |
+
|
| 200 |
+
### 1. Hugging Face Secrets μ€μ (5κ°)
|
| 201 |
+
|
| 202 |
+
`HF_SECRETS_μ€μ .md` μ°Έμ‘°
|
| 203 |
+
|
| 204 |
+
### 2. Git Push
|
| 205 |
+
|
| 206 |
+
```bash
|
| 207 |
+
git add .
|
| 208 |
+
git commit -m "Ready for deployment"
|
| 209 |
+
git push
|
| 210 |
+
```
|
| 211 |
+
|
| 212 |
+
### 3. λ°°ν¬ νμΈ
|
| 213 |
+
|
| 214 |
+
- Logs νμΈ
|
| 215 |
+
- API ν
μ€νΈ
|
| 216 |
+
- λ¬Έμ νμΈ
|
| 217 |
+
|
| 218 |
+
---
|
| 219 |
+
|
| 220 |
+
## π μ΅μ’
μμ½
|
| 221 |
+
|
| 222 |
+
| νλͺ© | μν |
|
| 223 |
+
|------|------|
|
| 224 |
+
| **μ½λ ꡬ쑰** | β
μλ²½ |
|
| 225 |
+
| **보μ** | β
.gitignore μ€μ λ¨ |
|
| 226 |
+
| **Wallet μ²λ¦¬** | β
start.pyλ‘ μλν |
|
| 227 |
+
| **Docker μ€μ ** | β
start.py μ€ν |
|
| 228 |
+
| **νκ²½ λ³μ** | β
Secretsλ‘ κ΄λ¦¬ |
|
| 229 |
+
| **API ꡬ쑰** | β
κ°κ²°νκ³ ν¨μ¨μ |
|
| 230 |
+
| **λ°°ν¬ μ€λΉ** | β
μλ£ |
|
| 231 |
+
|
| 232 |
+
---
|
| 233 |
+
|
| 234 |
+
**κ²μ κ²°κ³Ό: λ°°ν¬ κ°λ₯! π**
|
| 235 |
+
|
| 236 |
+
Git pushλ§ νλ©΄ λ©λλ€!
|
| 237 |
+
|
λ°°ν¬_체ν¬λ¦¬μ€νΈ.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# β
λ°°ν¬ μ΅μ’
체ν¬λ¦¬μ€νΈ
|
| 2 |
+
|
| 3 |
+
## π νμΌ κ΅¬μ‘° κ²μ
|
| 4 |
+
|
| 5 |
+
### β
νμ νμΌ (Gitμ ν¬ν¨)
|
| 6 |
+
- [x] `start.py` - Wallet λμ½λ© λ° μλ² λΆν
|
| 7 |
+
- [x] `app.py` - FastAPI μ ν리μΌμ΄μ
|
| 8 |
+
- [x] `Dockerfile` - start.py μ€ν
|
| 9 |
+
- [x] `requirements.txt` - μμ‘΄μ±
|
| 10 |
+
- [x] `.gitignore` - 보μ νμΌ μ μΈ
|
| 11 |
+
- [x] `README.md` - νλ‘μ νΈ μ€λͺ
|
| 12 |
+
- [x] `env_example.txt` - νκ²½ λ³μ μμ
|
| 13 |
+
|
| 14 |
+
### β μ μΈ νμΌ (Gitμ ν¬ν¨ μ λ¨)
|
| 15 |
+
- [ ] `.env` - λ‘컬 νκ²½ λ³μ
|
| 16 |
+
- [ ] `wallet/` - Wallet νμΌλ€
|
| 17 |
+
- [ ] `wallet_base64.txt` - Base64 μΈμ½λ© νμΌ
|
| 18 |
+
- [ ] `*.zip` - Wallet μμΆ νμΌ
|
| 19 |
+
|
| 20 |
+
---
|
| 21 |
+
|
| 22 |
+
## π Hugging Face Secrets (5κ°)
|
| 23 |
+
|
| 24 |
+
### νμ Secrets:
|
| 25 |
+
|
| 26 |
+
| Secret Name | μ€μ λ¨? | Value μμ |
|
| 27 |
+
|-------------|---------|-----------|
|
| 28 |
+
| `DB_USER` | [ ] | `ADMIN` |
|
| 29 |
+
| `DB_PASSWORD` | [ ] | Oracle DB λΉλ°λ²νΈ |
|
| 30 |
+
| `DB_TNS_ALIAS` | [ ] | `musclecare_high` |
|
| 31 |
+
| `WALLET_ZIP_B64` | [ ] | Base64 μΈμ½λ©λ Wallet |
|
| 32 |
+
| `WALLET_PASSWORD` | [ ] | Wallet λΉλ°λ²νΈ |
|
| 33 |
+
|
| 34 |
+
---
|
| 35 |
+
|
| 36 |
+
## π μ½λ κ²μ
|
| 37 |
+
|
| 38 |
+
### start.py
|
| 39 |
+
```python
|
| 40 |
+
β
WALLET_ZIP_B64 νκ²½ λ³μ μ½κΈ°
|
| 41 |
+
β
Base64 λμ½λ©
|
| 42 |
+
β
μμ λλ ν 리μ μμΆ ν΄μ
|
| 43 |
+
β
WALLET_DIR, WALLET_PASSWORD νκ²½ λ³μ μ€μ
|
| 44 |
+
β
uvicornμΌλ‘ FastAPI μ€ν
|
| 45 |
+
```
|
| 46 |
+
|
| 47 |
+
### app.py
|
| 48 |
+
```python
|
| 49 |
+
β
νκ²½ λ³μλ‘ DB μ€μ μ½κΈ°
|
| 50 |
+
β
Wallet κ²½λ‘ μ¬μ©
|
| 51 |
+
β
μ°κ²° ν μμ± (Thin mode + mTLS)
|
| 52 |
+
β
/health μλν¬μΈνΈ
|
| 53 |
+
β
/upload_state μλν¬μΈνΈ (MERGE INTO)
|
| 54 |
+
β
/upload_logs μλν¬μΈνΈ (executemany)
|
| 55 |
+
```
|
| 56 |
+
|
| 57 |
+
### Dockerfile
|
| 58 |
+
```dockerfile
|
| 59 |
+
β
Python 3.10-slim
|
| 60 |
+
β
requirements.txt μ€μΉ
|
| 61 |
+
β
start.pyλ‘ μ€ν
|
| 62 |
+
β
ν¬νΈ 7860 λ
ΈμΆ
|
| 63 |
+
```
|
| 64 |
+
|
| 65 |
+
### requirements.txt
|
| 66 |
+
```
|
| 67 |
+
β
fastapi
|
| 68 |
+
β
uvicorn
|
| 69 |
+
β
python-multipart
|
| 70 |
+
β
oracledb>=2.3
|
| 71 |
+
β
pydantic
|
| 72 |
+
```
|
| 73 |
+
|
| 74 |
+
---
|
| 75 |
+
|
| 76 |
+
## π§ͺ λ°°ν¬ μ λ‘컬 ν
μ€νΈ
|
| 77 |
+
|
| 78 |
+
### νκ²½ λ³μ μ€μ (λ‘컬)
|
| 79 |
+
|
| 80 |
+
```bash
|
| 81 |
+
export DB_USER="ADMIN"
|
| 82 |
+
export DB_PASSWORD="your_db_password"
|
| 83 |
+
export DB_TNS_ALIAS="musclecare_high"
|
| 84 |
+
export WALLET_DIR="/Users/gimhyeon-u/workspace/MuscleCare-FastAPI/wallet"
|
| 85 |
+
export WALLET_PASSWORD="your_wallet_password"
|
| 86 |
+
```
|
| 87 |
+
|
| 88 |
+
### μλ² μ€ν
|
| 89 |
+
|
| 90 |
+
```bash
|
| 91 |
+
python app.py
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
λλ start.pyλ‘:
|
| 95 |
+
|
| 96 |
+
```bash
|
| 97 |
+
# Wallet zip νμΌ μ€λΉ νμ
|
| 98 |
+
python start.py
|
| 99 |
+
```
|
| 100 |
+
|
| 101 |
+
---
|
| 102 |
+
|
| 103 |
+
## π λ°°ν¬ λͺ
λ Ήμ΄
|
| 104 |
+
|
| 105 |
+
### 1. Git μν νμΈ
|
| 106 |
+
|
| 107 |
+
```bash
|
| 108 |
+
git status
|
| 109 |
+
```
|
| 110 |
+
|
| 111 |
+
**νμΈ:**
|
| 112 |
+
- β `.env` μμ΄μΌ ν¨
|
| 113 |
+
- β `wallet/` μμ΄μΌ ν¨
|
| 114 |
+
- β `wallet_base64.txt` μμ΄μΌ ν¨
|
| 115 |
+
|
| 116 |
+
### 2. Git μ»€λ° λ° νΈμ
|
| 117 |
+
|
| 118 |
+
```bash
|
| 119 |
+
git add .
|
| 120 |
+
git commit -m "Deploy to HF with Wallet mTLS"
|
| 121 |
+
git push
|
| 122 |
+
```
|
| 123 |
+
|
| 124 |
+
---
|
| 125 |
+
|
| 126 |
+
## π λ°°ν¬ ν νμΈ
|
| 127 |
+
|
| 128 |
+
### 1. Logs νμΈ
|
| 129 |
+
|
| 130 |
+
Hugging Face Space β **Logs** ν
|
| 131 |
+
|
| 132 |
+
**μ±κ³΅ λ©μμ§:**
|
| 133 |
+
```
|
| 134 |
+
π Wallet λμ½λ© μμ...
|
| 135 |
+
π μμ λλ ν 리 μμ±: /tmp/wallet_xxxxx
|
| 136 |
+
β
Wallet μμΆ ν΄μ μλ£
|
| 137 |
+
β
tnsnames.ora νμΈ
|
| 138 |
+
INFO: Uvicorn running on http://0.0.0.0:7860
|
| 139 |
+
```
|
| 140 |
+
|
| 141 |
+
### 2. API ν
μ€νΈ
|
| 142 |
+
|
| 143 |
+
```bash
|
| 144 |
+
curl https://[username]-musclecare-api.hf.space/health
|
| 145 |
+
```
|
| 146 |
+
|
| 147 |
+
**κΈ°λ μλ΅:**
|
| 148 |
+
```json
|
| 149 |
+
{"ok": true, "db": 1}
|
| 150 |
+
```
|
| 151 |
+
|
| 152 |
+
### 3. API λ¬Έμ
|
| 153 |
+
|
| 154 |
+
```
|
| 155 |
+
https://[username]-musclecare-api.hf.space/docs
|
| 156 |
+
```
|
| 157 |
+
|
| 158 |
+
---
|
| 159 |
+
|
| 160 |
+
## π§ λ¬Έμ ν΄κ²°
|
| 161 |
+
|
| 162 |
+
### "WALLET_ZIP_B64 νκ²½ λ³μκ° μμ΅λλ€"
|
| 163 |
+
|
| 164 |
+
- [ ] Secrets μ΄λ¦ νμΈ: `WALLET_ZIP_B64` (μ νν)
|
| 165 |
+
- [ ] Secret κ° νμΈ: wallet_base64.txt μ 체 λ΄μ©
|
| 166 |
+
- [ ] Space μ¬μμ
|
| 167 |
+
|
| 168 |
+
### "Wallet μμΆ ν΄μ μ€ν¨"
|
| 169 |
+
|
| 170 |
+
- [ ] Base64 μΈμ½λ© μ¬μλ
|
| 171 |
+
- [ ] Wallet zip νμΌμ΄ μμλμ§ μμλμ§ νμΈ
|
| 172 |
+
|
| 173 |
+
### "DB μ°κ²° μ€ν¨"
|
| 174 |
+
|
| 175 |
+
- [ ] Oracle DB μν AVAILABLE νμΈ
|
| 176 |
+
- [ ] `DB_PASSWORD` νμΈ
|
| 177 |
+
- [ ] `DB_TNS_ALIAS` νμΈ
|
| 178 |
+
|
| 179 |
+
---
|
| 180 |
+
|
| 181 |
+
## β
μ΅μ’
체ν¬
|
| 182 |
+
|
| 183 |
+
- [ ] Dockerfileμ΄ start.py μ€ννλλ‘ μμ λ¨
|
| 184 |
+
- [ ] .gitignore μμ±λ¨
|
| 185 |
+
- [ ] README.md μ
λ°μ΄νΈλ¨
|
| 186 |
+
- [ ] env_example.txt μμ±λ¨
|
| 187 |
+
- [ ] Gitμ λ―Όκ° νμΌ μ μΈ νμΈ
|
| 188 |
+
- [ ] 5κ° Secrets μ€μ μ€λΉλ¨
|
| 189 |
+
|
| 190 |
+
**λͺ¨λ μ€λΉ μλ£!** π
|
| 191 |
+
|