Track connected user count of workers. (#328)

If a worker (game) is shared, then without tracking players it's impossible to tell when it becomes available for a new game which leads to emulator share and crashes.
This commit is contained in:
sergystepanov 2021-07-05 19:11:12 +03:00 committed by GitHub
parent 35ee35d730
commit cbabe69f30
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 33 additions and 10 deletions

View file

@ -217,7 +217,9 @@ func (o *Server) WS(w http.ResponseWriter, r *http.Request) {
// Assign available worker to browserClient
bc.WorkerID = wc.WorkerID
wc.IsAvailable = false
wc.ChangeUserQuantityBy(1)
defer wc.ChangeUserQuantityBy(-1)
// Everything is cool
// Attach to Server instance with sessionID
@ -237,9 +239,6 @@ func (o *Server) WS(w http.ResponseWriter, r *http.Request) {
// Notify worker to clean session
wc.Send(api.TerminateSessionPacket(sessionID), nil)
// WorkerClient become available again
wc.IsAvailable = true
}
func (o *Server) getBestWorkerClient(client *BrowserClient, zone string) (*WorkerClient, error) {
@ -269,7 +268,7 @@ func (o *Server) getBestWorkerClient(client *BrowserClient, zone string) (*Worke
func (o *Server) getAvailableWorkers() map[string]*WorkerClient {
workerClients := map[string]*WorkerClient{}
for k, w := range o.workerClients {
if w.IsAvailable {
if w.HasGameSlot() {
workerClients[k] = w
}
}
@ -280,7 +279,7 @@ func (o *Server) getAvailableWorkers() map[string]*WorkerClient {
// getWorkerFromAddress returns the worker has given address
func (o *Server) getWorkerFromAddress(address string) *WorkerClient {
for _, w := range o.workerClients {
if w.IsAvailable && w.Address == address {
if w.HasGameSlot() && w.Address == address {
return w
}
}

View file

@ -3,6 +3,7 @@ package coordinator
import (
"fmt"
"log"
"sync"
"github.com/giongto35/cloud-game/v2/pkg/cws"
"github.com/gorilla/websocket"
@ -16,20 +17,43 @@ type WorkerClient struct {
// public server used for ping check (Cannot use worker address because they are not publicly exposed)
PingServer string
StunTurnServer string
IsAvailable bool
userCount int // may be atomic
Zone string
mu sync.Mutex
}
// NewWorkerClient returns a client connecting to worker.
// This connection exchanges information between workers and server.
func NewWorkerClient(c *websocket.Conn, workerID string) *WorkerClient {
return &WorkerClient{
Client: cws.NewClient(c),
WorkerID: workerID,
IsAvailable: true,
Client: cws.NewClient(c),
WorkerID: workerID,
}
}
// ChangeUserQuantityBy increases or decreases the total amount of
// users connected to the current worker.
// We count users to determine when the worker becomes new game ready.
func (wc *WorkerClient) ChangeUserQuantityBy(n int) {
wc.mu.Lock()
wc.userCount += n
// just to be on a safe side
if wc.userCount < 0 {
wc.userCount = 0
}
wc.mu.Unlock()
}
// HasGameSlot tells whether the current worker has a
// free slot to start a new game.
// Workers support only one game at a time.
func (wc *WorkerClient) HasGameSlot() bool {
wc.mu.Lock()
defer wc.mu.Unlock()
return wc.userCount == 0
}
func (wc *WorkerClient) Printf(format string, args ...interface{}) {
log.Printf(fmt.Sprintf("Worker %s] %s", wc.WorkerID, format), args...)
}