MWSE/PORT-PROGRESS.md

74 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PORT-PROGRESS — MWSE Node.js → Go Çekirdek Portu
> Bu oturumun çıktısı. Branch: `go-rewrite`. `stable`'a dokunulmadı, deploy yapılmadı, hiçbir issue kapatılmadı. Yarın insan incelemesi için yazıldı.
## TL;DR
MWSE engine (Node.js `Source/`) **performans odaklı, race-free bir Go projesine** taşındı. SDK ile konuşulan **WSTS tel formatı (giriş/çıkış sözleşmesi) korundu**. Frontend (`frontend/`) hiç dokunulmadan yerinde duruyor. İkinci bir Go projesi (`loadtest/`) yük testi + benchmark için yazıldı.
- `go build ./...` ✅ · `go vet ./...` ✅ · `go test -race ./...`
- Uçtan uca doğrulandı: engine + loadtest birlikte çalıştırıldı.
- **ping** modu: ~140k istek/sn, p50 ~200µs, 0 hata.
- **relay** modu: ~190k mesaj/sn, %98.5 teslim, bağlantı çökmesi yok.
## Klasör yapısı (karar: Go repo kökünde)
```
go.mod # modül: git.saqut.com/saqut/mwse
main.go # giriş noktası, graceful shutdown, sinyal yönetimi
internal/
protocol/ # WSTS tel formatı (encode/decode) — DONMUŞ sözleşme
ws/ # çekirdek: Client, Room, Hub, Server (concurrency burada)
services/ # handler portu: YourID, Session, Auth, Room, IPPressure, DataTransfer
config/ # env tabanlı yapılandırma
httpserver/ # HTTP yüzeyi: WS upgrade + statik + /api + graceful shutdown
testutil/ # testler için in-memory sahte bağlantı (FakeConn)
loadtest/ # AYRI Go modülü: yük/benchmark istemcisi (ping + relay)
frontend/ # DOKUNULMADI (TS SDK, parcel ile derleniyor)
Source/ # eski Node.js engine — referans olarak bırakıldı
```
## Concurrency modeli (#22 — ASIL SEBEP)
Node'daki "biri odadan ayrılırken başka thread o peer'e yazınca race" sorunu, Go'da **iki katmanlı bir garantiyle** kökten çözüldü:
1. **Bağlantı başına TEK yazıcı goroutine.** Sokete yazan tek şey `writePump`'tır. Üreticiler sokete asla dokunmaz; mesajı `outbound` kanalına koyar. Böylece gorilla'nın "aynı anda tek yazıcı" kuralı yapısal olarak garanti edilir, eşzamanlı yazma imkânsızdır.
2. **`Send` her zaman `done` kanalını da seçer.** Bir gönderim, kapanmakta olan bir peer ile yarışırsa panik/race yerine **sessizce düşürülür**. Bu, "ayrılırken-yazma" senaryosunu güvenli kılan tam noktadır.
3. **Paylaşılan durum kilitli.** `Hub` (client/room kayıtları), `Room` (üyelik) ve `Client` (info/store/pairs/rooms) her biri kendi `sync.RWMutex`'i ile korunur. `Room.Broadcast` üyeleri kilit altında **snapshot**'lar, sonra kilit olmadan gönderir → ne deadlock ne race.
Neden actor değil de RWMutex + tek-yazıcı? → `decisions.md`. Özet: gerçek race zaten (1)+(2) ile çözülüyor; RWMutex versiyonu yeni başlayan bir Go geliştiricisi için çok daha okunaklı. Bu seçim `REVIEW.md`'de insan onayına bırakıldı.
**Regresyon testi:** `internal/ws/ws_test.go → TestLeaveWhileSendRace` — bir odaya 4 goroutine broadcast ederken 30 üye eşzamanlı `Eject`/`Join` yapar; `-race` ile temiz geçer. Node'da çöken senaryonun bire bir karşılığı.
## Ne yapıldı (issue eşlemesi — SADECE spec olarak okundu, KAPATILMADI)
- **#21** WS sunucu iskeleti + yaşam döngüsü → `internal/ws/server.go` (upgrade, read loop, heartbeat `saQut` ping/pong, tek-yazıcı writePump).
- **#22** Concurrency modeli → yukarıdaki tasarım + regresyon testi.
- **#23** WSTS protokolü → `internal/protocol/` (request/response/stream/signal, numeric id round-trip dahil). Frontend ile bire bir uyumlu.
- **#24** MessageRouter + Services → `internal/ws/hub.go` (router + event bus) + `internal/services/*`.
- **#25** Config + HTTP + graceful shutdown → `internal/config`, `internal/httpserver`, `main.go`.
- **#26** `go test -race` süreç/yarış testleri → `internal/ws/ws_test.go`, `internal/services/services_test.go`, `internal/protocol/protocol_test.go`.
## Ne kaldı / sonraki adımlar
- `/api` kontrol düzleminde **server'ın odaya katılması (join/leave)** ve **webhook** uçları ertelendi (Node'daki sahte-client deseni Go'da farklı tasarlanmalı). Detay → `REVIEW.md`.
- P2P `request/to` + `response/to` zincirinde Node'dan gelen **bir tasarım uyumsuzluğu** var (request, action 'R' ile gönderildiği için sunucu hemen 'E' ile yanıtlıyor; eş yanıtı sonra geliyor). Sadık port yapıldı, sözleşme değiştirilmedi → `REVIEW.md`.
- Binary protokol (2.5.0), WebRTC signaling (1.0.0+), studio (2.0.0) kapsam dışı.
- IPPressure'ın çok-süreçli "canlı panel" IPC'si (`process.send`) tek-node çekirdek için `Announcer` arayüzünün arkasına soyutlandı (varsayılan no-op). Cluster entegrasyonu sonra.
## Çalıştırma
```bash
# Engine
go run . # 0.0.0.0:7707
MWSE_PORT=8080 go run . # env ile yapılandırma
# Yük testi / benchmark (engine ayaktayken, ayrı modül)
cd loadtest
go run . -mode ping -clients 100 -dur 10s
go run . -mode relay -clients 100 -dur 10s
# Testler
go test -race ./...
```