AI Hikaye Oyunu

Veritabanı Mimari Raporu — v3

6 tablo, 10 index, 4 JSONB kolonu, 2 HNSW vektör index'i. PostgreSQL + pgvector + Redis üzerine kurulu, Bun/ElysiaJS ile servis edilen interaktif hikaye motoru.

🚀

Bun

Runtime

🦊

ElysiaJS

Framework

🛡️

TypeBox

Validation

🐘

PostgreSQL 17

JSONB + pgvector

Redis

Cache + Lock

🌧️

Drizzle ORM

Type-safe SQL

6 Tablo
10 Index
4 JSONB Kolon
2 HNSW Vektör Index
~6KB / Embedding

Tablo İlişki Haritası

Tablolara tıklayarak detaylarına gidin. Oklar CASCADE silme yönünü gösterir.

🧑‍💻 users
Kök Tablo — PK: id (IDENTITY)
1:N →
🔐 auth_providers
OAuth — CASCADE
1 : N (SET NULL)
📖 stories
FK: user_id → users (SET NULL) — 2 JSONB (config+session_data) + 15 kolon
1:N
📝 story_chunks
Hızlı büyüyen — embedding vector(1536)
1:1
🔀 story_decisions
FK: chunk_id (UNIQUE) → chunks — RAG optimized
1:N
📤 outbox
Transactional Outbox — idempotency_key

stories.user_id ON DELETE SET NULL (kullanıcı silinse bile hikayeler korunur). Diğer tüm FK'lar ON DELETE CASCADE.

Veri Modeli Detayları

Tabloyu seçin, sonra Kolonlar / Indexler / SQL sekmelerini kullanarak detayları keşfedin.

Index Stratejisi

10 index — her biri belirli bir sorgu pattern'ine göre optimize edilmiş. Kategoriye göre filtreleyebilirsiniz.

JSONB Kolon Şemaları

PostgreSQL JSONB içeriğini doğrulamaz — validasyon ElysiaJS TypeBox katmanında yapılır. İçerik yapılarını inceleyin.

story_config

stories tablosunda


            

Alan Açıklamaları

5-Faz İstek Pipeline'ı

Kullanıcı her hamle yaptığında sırayla çalışan 5 faz. Tıklayarak her fazın detayını görün.

Transaction Simülatörü

Phase 4'teki atomik işlem zinciri. Senaryo seçerek başarılı ve başarısız akışları karşılaştırın.

Senaryo Seçin

Simülasyonu başlatmak için butona tıklayın.
Durum: Hazır 0 / 6

CASCADE Silme Zinciri

Bir tablodan kayıt sildiğinizde hangi tablolar otomatik etkilenir? Kutulara tıklayarak deneyin.

🧑‍💻
users
Kök
🔐
auth_providers
FK → users (CASCADE)
📖
stories
FK → users (SET NULL)
📝
story_chunks
FK → stories
🔀
story_decisions
FK → stories, chunks
📤
outbox
FK → stories

Ölçeklenebilirlik Projeksiyonu

1000 aktif kullanıcı, günde ortalama 20 hamle senaryosu.

Satır Sayısı Büyümesi

story_chunks vs story_decisions vs users (60 gün)

Disk Alanı Projeksiyonu

Tablo + Index boyutları (embedding ~6KB/satır)

Sorgu Performansı Karşılaştırması

Index optimizasyonlarının etkisi (ms — düşük = iyi)

Cache Dirty Akışı

Redis↔PostgreSQL senkronizasyon akışı

1
Phase 4 Write
stories.cache_dirty = true
2
COMMIT sonrası Redis'e yaz
SET story:{storyId} → session_data + story_config
3a
Redis OK → cache_dirty = false
3b
Redis FAIL → cache_dirty = true kalır. Sonraki Phase 2'de PG'den okunur.
Neden bu kadar karmaşık? Redis crash olsa bile veri kaybı olmaz. PG her zaman source of truth'tur. Redis sadece hız katmanı.

Ekip Geri Dönüşleri

Arkadaşlardan gelen sorular, öneriler ve alınan kararlar. Kartlara tıklayarak detayları görebilirsiniz.

0
Çözüldü
0
Bekliyor
0
Toplam

ER Diyagramı — Önce / Sonra

Çözülen soruların ER diyagramı üzerindeki etkisi. Değişen alanlar işaretlenmiştir.

👤 users 🔑 idUUID PK emailVARCHAR UNIQUE usernameVARCHAR(100) UNIQUE password_hashVARCHAR NULL timezoneVARCHAR(50) avatar_urlTEXT created_atTIMESTAMP 🔐 auth_providers 🔑 idUUID PK 🔗 user_idUUID FK CASCADE provider_typeVARCHAR(50) provider_idVARCHAR(255) display_nameVARCHAR(255) created_atTIMESTAMP 1:N 📖 stories 🔑 idUUID PK 🔗 user_idUUID FK → users CASCADE like_countINT CHECK≥0 llm_modelVARCHAR(50) image_model/frequencyVARCHAR cover_image_urlTEXT story_configJSONB ⚠️ (genre+summary dahil) created_atTIMESTAMP updated_atTIMESTAMP ⚡trigger 1:N 📝 story_chunks 🔑 idUUID PK 🔗 story_idUUID FK CASCADE chunk_indexINT (UNIQUE w/story) narrative_textTEXT NOT NULL user_input_*type + value choices, scene_typeJSONB, VARCHAR image_url/promptTEXT embeddingvector(1536) HNSW created_atTIMESTAMP 1:N 🧠 sessions 🔑 idUUID PK 🔗 story_idUNIQUE CASCADE memory_schemeJSONB ⚠️ memory_dataJSONB ⚠️ chunk_countINT (denormalize) cache_dirtyBOOLEAN versionINT (opt. lock) 🔒 created/updated_atTIMESTAMP 1:1 🎯 story_decisions 🔑 idUUID PK 🔗 story_idUUID FK CASCADE 🔗 chunk_idUUID FK UNIQUE CASCADE decision_textTEXT NOT NULL embeddingvector(1536) created_atTIMESTAMP 1:1 (chunk_id UNIQUE) 1:N 📤 outbox event_type, payload, status idempotency_key, retry_count 1:N v2 — Q1~Q15 sonrası (7 tablo)
🆕 Yeni Kolon / Tablo ⚠️ Değişen Kısıt 🗑️ Kaldırılan Q16: sessions kaldırıldı, stories yeniden yapılandırıldı (15 kolon), PK UUID → IDENTITY, title → JSONB, summary geri ayrı kolon, is_public + session_data + chunk_count + cache_dirty eklendi, cover_image → cover_image_url NN.
Durum: