MWSE/PORT-PROGRESS.md

5.1 KiB
Raw Blame History

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

# 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 ./...