Arsitektur

Komponen sistem yellow-bank-soal, alur data, dan pembagian tanggung jawab antar-lapisan.

Arsitektur

Diagram High-Level

flowchart LR
    WP["WordPress + Sejoli Tryout"]
    App["yellow-bank-soal (FastAPI)"]
    DB[("PostgreSQL")]
    Redis[("Redis + Celery")]
    AI["OpenRouter API"]
    Admin["Admin UI"]
    Siswa["Browser Siswa"]

    Siswa --> WP
    WP -->|"verify_session + create session"| App
    Admin -->|"CRUD + reports"| App
    App --> DB
    App --> Redis
    App -->|"generate soal"| AI
    App -->|"delivery soal + skor"| Siswa

Yellow Bank Soal adalah backend terpusat. Klien (browser siswa, admin UI, plugin Sejoli) berkomunikasi via REST API. Output dari sebuah sesi ujian adalah skor (NM, NN, theta) yang disimpan permanen di PostgreSQL.

Lapisan Aplikasi

Aplikasi mengikuti pola layered architecture klasik, dengan pemisahan jelas antara transport (HTTP), logika bisnis (services), dan persistensi (models).

flowchart TD
    A["API Layer (routers/api/v1)"] --> B["Service Layer (services/)"]
    B --> C["Data Layer (models/ + database.py)"]
    B --> D["External (OpenRouter, WordPress JWT)"]
    A --> E["Schema Layer (schemas/) — validasi Pydantic"]
    C --> F[("PostgreSQL via SQLAlchemy 2.0 async")]

1. API Layer (backend/app/routers/, backend/app/api/v1/)

Endpoint HTTP FastAPI. Bertugas:

  • Parsing & validasi request (via Pydantic schema)
  • Delegasi ke service layer
  • Format response JSON

Tidak boleh berisi logika bisnis. Hanya transport.

2. Service Layer (backend/app/services/)

Jantung aplikasi. Setiap file service punya satu domain tanggung jawab:

ServiceTanggung Jawab
ctt_scoring.pyHitung p, Bobot, NM, NN, kategori kesulitan, update statistik tryout
irt_calibration.pyRasch 1PL: probabilitas, Fisher information, MLE theta, kalibrasi b, SE
cat_selection.pyPemilihan soal (fixed / adaptive / hybrid), update theta, terminasi
normalization.pyStatistik Rataan & SB, mode static / dynamic
ai_generation.pyVarian soal via OpenRouter, caching & reuse per user
excel_import.pyImpor / ekspor Excel klien
wordpress_auth.pyVerifikasi WordPress JWT, multi-tenant
config_management.pyBaca/tulis konfigurasi tryout
reporting.pyLaporan performa siswa & analisis soal

3. Schema Layer (backend/app/schemas/)

Definisi Pydantic v2 untuk request body, response model, dan validasi. Memisahkan kontrak API dari struktur internal model database.

4. Data Layer (backend/app/models/, backend/app/database.py)

SQLAlchemy 2.0 async ORM. Migrasi via Alembic (backend/alembic/). Setiap model punya website_id untuk isolasi multi-tenant. Detail lengkap di Data → Data Models.

Alur Data Runtime vs Batch

Dua jalur data berbeda di aplikasi, dengan karakteristik berbeda:

flowchart LR
    subgraph RT["Runtime (real-time, saat sesi ujian)"]
        R1["Siswa jawab"] --> R2["cat_selection"]
        R2 --> R3["irt_calibration update theta"]
        R3 --> R4["UserAnswer"]
    end
    subgraph BG["Batch (async, lewat Celery)"]
        B1["Trigger kalibrate"] --> B2["irt_calibration joint MLE"]
        B2 --> B3["Update semua Item.b"]
        B4["Trigger AI generate"] --> B5["ai_generation"]
        B5 --> B6["Insert Item baru"]
    end
    R4 -.->|"menyumbang data"| B2
JalurPemicuLatensiContoh
RuntimeRequest HTTP siswa< 100msPilih soal berikutnya, update theta, hitung skor
BatchAdmin trigger atau cronDetik–menitKalibrasi IRT massal, AI generate batch soal

Batch job dijalankan via Celery + Redis agar tidak memblokir API. Saat ini kalibrasi IRT dan AI generation adalah kandidat utama untuk background processing.

Boundary dengan Sejoli Tryout

Pemisahan tanggung jawab yang tegas — detail lengkap di Integrasi → Sejoli Tryout:

DomainPemilik
Autentikasi WP, pembelian, quota attemptSejoli/WordPress
Pengiriman soal, scoring, record attempt, laporanyellow-bank-soal

App tidak mengurangi quota attempt atau memvalidasi pembayaran — itu tanggung jawab Sejoli sebelum sesi dimulai.

Boundary Internal Modul

Aturan penting untuk kontributor kode:

  • routers/ tidak boleh import langsung dari models/ — selalu lewat service.
  • services/ tidak boleh tahu soal HTTP (no Request, Response, status code).
  • models/ tidak boleh berisi logika bisnis — hanya deklarasi tabel, relationship, constraint.
  • Cross-service call dihindari; jika perlu, lewat function eksplisit (bukan circular import).

Bacaan Lanjutan

Last updated Jul 25, 2026