From 64bdf5fc3d4467f8a331c373c70d201aaf243bd2 Mon Sep 17 00:00:00 2001 From: Amirmahdi Nourkazemi Date: Sat, 11 Jul 2026 22:43:59 +0330 Subject: [PATCH] fix: delay --- internal/ws/client.go | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/internal/ws/client.go b/internal/ws/client.go index bcf62e3..665f1fe 100644 --- a/internal/ws/client.go +++ b/internal/ws/client.go @@ -14,7 +14,9 @@ const ( pongWait = 60 * time.Second pingPeriod = (pongWait * 9) / 10 maxMessageSize = 4096 - sendBuffer = 32 + // بافرِ بزرگ‌تر تا در سرورِ تک‌هسته‌ای، هجومِ کوتاهِ وضعیت‌ها (پخشِ کارت + چند حرکتِ + // بات) روی کلاینتِ کند باعثِ دورریختنِ پیام نشود. + sendBuffer = 256 ) // Client یک اتصال WebSocket یک بازیکن. @@ -96,14 +98,29 @@ func (c *Client) writePump() { } } -// trySend ارسال غیرمسدودکننده؛ اگر اتصال بسته یا بافر پر بود پیام را می‌اندازد. +// trySend ارسالِ غیرمسدودکننده. اگر بافر پر باشد، به‌جای دورریختنِ پیامِ جدید، +// «قدیمی‌ترین» پیام دور ریخته می‌شود تا کلاینت روی جدیدترین وضعیت همگرا بماند +// (هر وضعیتِ کامل، وضعیتِ قبلی را باطل می‌کند). قبلاً جدیدترین دور ریخته می‌شد و +// کلاینت روی حالتِ کهنه گیر می‌کرد: کارت‌های دست دیده نمی‌شد ولی بات‌ها بازی می‌کردند. // send هیچ‌گاه close نمی‌شود؛ پس از done صرفاً پیام دور ریخته می‌شود (بدون panic). func (c *Client) trySend(b []byte) { - select { - case <-c.done: - case c.send <- b: - default: - slog.Warn("client send buffer full, dropping message", "user", c.UserID) + for { + select { + case <-c.done: + return + case c.send <- b: + return + default: + // بافر پر است: یک پیامِ قدیمی را خالی کن و دوباره تلاش کن. + select { + case <-c.send: + slog.Warn("client send buffer full, dropping oldest", "user", c.UserID) + case <-c.done: + return + default: + // بافر بین دو تلاش خالی شد (تولیدکننده‌ی دیگر آن را خالی کرد)؛ ادامه بده. + } + } } }