34 lines
4.4 KiB
Markdown
34 lines
4.4 KiB
Markdown
# decisions.md — Port Sırasında Alınan Kararlar
|
||
|
||
Geri-dönülebilir kararlar burada kayıt altına alındı; CLAUDE.md gereği seçildi, gerekçe yazıldı, devam edildi.
|
||
|
||
## Mimari
|
||
|
||
1. **Klasör yapısı: Go repo kökünde** (`go.mod` + `main.go` + `internal/`). Kullanıcı onayıyla. `loadtest/` ayrı modül. `frontend/` yerinde. Eski `Source/` referans olarak bırakıldı.
|
||
2. **WebSocket kütüphanesi: `gorilla/websocket` v1.5.3.** Kullanıcı onayıyla. En yaygın, en okunaklı; tek-yazıcı hub deseni doğrudan uyuyor. Modül önbelleğinde mevcut olduğundan ağ gerekmedi.
|
||
3. **Concurrency: RWMutex + bağlantı-başına-tek-yazıcı (actor yerine).** İzin verilen iki seçenekten (#22) bu seçildi çünkü gerçek race "tek yazıcı + `done` seçimli `Send`" ile zaten çözülüyor; RWMutex versiyonu yeni Go geliştiricisi için belirgin biçimde daha okunaklı. Actor (reply-channel) modeli senkron request/response handler'larına ceremoni ekler. → `REVIEW.md`'de onaya açık.
|
||
4. **Modül yolu:** `git.saqut.com/saqut/mwse` (engine), `git.saqut.com/saqut/mwse-loadtest` (yük testi). Mantıksal isim; repo dizininin Türkçe karakterli olması etkilemez.
|
||
5. **Dolu outbound buffer politikası: mesajı düşür, bağlantıyı KAPATMA.** İlk versiyon (gorilla hub örneği gibi) yavaş peer'i komple düşürüyordu; yük testinde bu, ani trafik altında zincirleme kopmalara yol açtı (relay'de %92 kayıp). Best-effort relay için doğru politika: tek frame'i düşür, bağlantıyı koru. Gerçekten ölü peer zaten write-deadline ile temizlenir. Düzeltme sonrası teslim %98.5'e çıktı. `Client.Dropped()` ile gözlemlenebilir.
|
||
|
||
## Node'daki hataların düzeltilmesi (tel sözleşmesi korunarak)
|
||
|
||
Kullanıcı talimatı: "tüm fonksiyonların aynı olması önemli değil; amaç/iş aynı kalsın." Node kaynağındaki bariz bug'lar **doğru çalışacak şekilde** yeniden yazıldı; mesaj isimleri/şekilleri (SDK'nın gördüğü tel) korundu:
|
||
|
||
- **Pairing akışı (Auth):** Node'da `accept/pair` yanlış tarafın `pairs` setini kontrol ediyordu (akış asla tamamlanmıyordu). Doğru el sıkışma uygulandı: `request/pair` isteyen tarafı kaydeder + hedefe `request/pair` sinyali; `accept/pair` isteyenin gerçekten istek attığını doğrular + `accepted/pair` sinyali. Frontend'in beklediği `{from, info}` yükü gönderiliyor.
|
||
- **`is/reachable`:** Node `otherPeer.pairs.has(to)` (kendi id'sini) kontrol ediyordu — her zaman false. Doğrusu: hedef pairing istemiyorsa VEYA gönderenle eşleşmişse erişilebilir.
|
||
- **Davet sistemi (Room `accept/invite-room` / `reject/invite-room`):** Node `Set` üzerinde `.includes`/`.filter` çağırıyordu (çalışmaz, HANDLER_ERROR) ve `joinType=='invite'` kontrolü ters çevrilmişti. Doğru akış: sadece davet odaları, sadece bekleme listesindeki id'ler.
|
||
- **`closeroom`:** Node `room.owner === client.id` ile Client nesnesini string'e kıyaslıyordu (her zaman false). Go'da `OwnerID string` tutuluyor; doğru kıyas.
|
||
- **`create-room` doğrulaması:** Node tanımsız `CreateRoomValidate` değişkenine referans veriyordu (throw). joi şemasının niyetini taşıyan hafif bir doğrulama yazıldı. (Not: Node'un doğrulama hatasında döndürdüğü `messages` anahtarı —tekil değil— korundu.)
|
||
- **`joinroom` invite dalı:** Node davet gönderdikten sonra `NOT-FOUND-ROOM` döndürüyordu (yanıltıcı). `{status:"success", message:"INVITE-REQUESTED"}` ile değiştirildi.
|
||
- **`pack/to` pairing kontrolü:** Node `otherPeer.pairs.has(to)` (kendi id'si) kullanıyordu. Doğrusu hedefin gönterene pairing'i: `other.HasPair(c.ID)`.
|
||
|
||
## Bilinçli sadakat (Node davranışı korundu)
|
||
|
||
- **`request/to` → 'E' yanıtı:** SDK request'i action 'R' ile gönderdiğinden generic dispatcher hemen `[null, id, 'E']` yanıtlar; eş cevabı `response/to` ile sonra gelir. Bu Node ile bire bir aynı (ve aynı uyumsuzluğu taşır). Dispatcher'ı özel-durumlamak tel sözleşmesini değiştirebileceğinden DOKUNULMADI. → `REVIEW.md`.
|
||
- **`auth/info` çift gönderim:** Hem pair hem roompair olan bir peer iki `pair/info` alır (Node ile aynı).
|
||
- **Heartbeat:** 10sn `saQut` ping; pong "saQut" değilse bağlantı kapanır (Node ile aynı).
|
||
|
||
## Session varsayılanları
|
||
|
||
`packrecaive`/`packsending`/`notifyPairInfo`/`notifyRoomInfo` varsayılanları **`NewClient` constructor'ında** set ediliyor (listener sırasından bağımsız her zaman mevcut). Session servisinin connect hook'u parite için yine de bunları yeniden uyguluyor.
|