diff --git a/pkg/com/com.go b/pkg/com/com.go index 5a7380391..3bb930d2f 100644 --- a/pkg/com/com.go +++ b/pkg/com/com.go @@ -14,6 +14,7 @@ func NewNetMap[K comparable, T NetClient[K]]() NetMap[K, T] { } func (m *NetMap[K, T]) Add(client T) bool { return m.Put(client.Id(), client) } +func (m *NetMap[K, T]) Empty() bool { return m.Map.Len() == 0 } func (m *NetMap[K, T]) Remove(client T) { m.Map.Remove(client.Id()) } func (m *NetMap[K, T]) RemoveL(client T) int { return m.Map.RemoveL(client.Id()) } func (m *NetMap[K, T]) Reset() { m.Map = Map[K, T]{m: make(map[K]T, 10)} } diff --git a/pkg/worker/room/room.go b/pkg/worker/room/room.go index 6e777e806..67ac69609 100644 --- a/pkg/worker/room/room.go +++ b/pkg/worker/room/room.go @@ -25,6 +25,7 @@ type MediaPipe interface { type SessionManager[T Session] interface { Add(T) bool + Empty() bool Find(string) T ForEach(func(T)) RemoveL(T) int @@ -126,6 +127,7 @@ func (r *Router[T]) Close() { r.mu.Lock(); r.room.Close(); r.r func (r *Router[T]) FindUser(uid Uid) T { return r.users.Find(uid.Id()) } func (r *Router[T]) Room() *Room[T] { r.mu.Lock(); defer r.mu.Unlock(); return r.room } func (r *Router[T]) SetRoom(room *Room[T]) { r.mu.Lock(); r.room = room; r.mu.Unlock() } +func (r *Router[T]) HasRoom() bool { r.mu.Lock(); defer r.mu.Unlock(); return r.room != nil } func (r *Router[T]) Users() SessionManager[T] { return r.users } type AppSession struct { diff --git a/pkg/worker/watcher.go b/pkg/worker/watcher.go new file mode 100644 index 000000000..953b00361 --- /dev/null +++ b/pkg/worker/watcher.go @@ -0,0 +1,46 @@ +package worker + +import ( + "time" + + "github.com/giongto35/cloud-game/v3/pkg/logger" + "github.com/giongto35/cloud-game/v3/pkg/worker/room" +) + +type Watcher struct { + r *room.GameRouter + t *time.Ticker + done chan struct{} + log *logger.Logger +} + +func NewWatcher(p time.Duration, router *room.GameRouter, log *logger.Logger) *Watcher { + return &Watcher{ + r: router, + t: time.NewTicker(p), + done: make(chan struct{}), + log: log, + } +} + +func (w *Watcher) Run() { + go func() { + for { + select { + case <-w.t.C: + if w.r.HasRoom() && w.r.Users().Empty() { + w.r.Close() + w.log.Warn().Msgf("Forced room close!") + } + case <-w.done: + return + } + } + }() +} + +func (w *Watcher) Stop() error { + w.t.Stop() + close(w.done) + return nil +} diff --git a/pkg/worker/worker.go b/pkg/worker/worker.go index 0c0f1d5ab..04e3ae274 100644 --- a/pkg/worker/worker.go +++ b/pkg/worker/worker.go @@ -21,7 +21,7 @@ type Worker struct { log *logger.Logger mana *caged.Manager router *room.GameRouter - services [2]interface { + services [3]interface { Run() Stop() error } @@ -64,6 +64,7 @@ func New(conf config.WorkerConfig, log *logger.Logger) (*Worker, error) { log.Warn().Err(err).Msgf("cloud storage fail, using no storage") } worker.storage = st + worker.services[2] = NewWatcher(30*time.Minute, worker.router, log) return worker, nil }