Game Queue

The game has a queue service that stores all the Players that are waiting to be in a match, and the ongoing match in a game hash. They're saved on a Redis service.

The queue starts when the server receives a JoinQueue event from the Client.

websocket_pool.go
case client := <-pool.JoinQueue:
	redis.AddPlayerToQueue(client)

	firstPlayer, secondPlayer, created := redis.CreateGame()

	...

	break

After receiving that event, we call the redis package to enqueue the player.

websocket_pool.go
func AddPlayerToQueue(player *dto.Player) {
	val, err := json.Marshal(*player)

	if err != nil {
		log.Printf("Error trying to save player? %v", err)
		return
	}

	err = rdb.RPush(ctx, "players", val).Err()

	if err != nil {
		log.Printf("Error trying to save player: %v", err)
	}
}

We push the player information to a Redis List and, after that has been pushed, then we try to create the game hash.

websocket_pool.go
case client := <-pool.JoinQueue:
    ...
    
    firstPlayer, secondPlayer, created := redis.CreateGame()
    
    ...
    break
create_game.go
package redis

func CreateGame() (dto.Player, dto.Player, bool) {
	encodedGame, err := rdb.HGetAll(ctx, "game").Result()

	if err != nil {
		log.Printf("Error trying to get dto Hash: %v", err)
		return dto.Player{}, dto.Player{}, false
	}

	firstPlayer, secondPlayer, unavailable := getPlayersToMatch()

	if unavailable {
		return dto.Player{}, dto.Player{}, false
	}

	_, errorParsing := dto.ParseGameFromMap(encodedGame)

	if errorParsing != nil {
		encodedFirstPlayer, _ := dto.ConvertPlayerToJson(&firstPlayer)
		encodedSecondPlayer, _ := dto.ConvertPlayerToJson(&secondPlayer)

		err = rdb.HSet(ctx, "game", map[string]interface{}{
			"player1": encodedFirstPlayer,
			"player2": encodedSecondPlayer,
		}).Err()

		if err != nil {
			log.Printf("Error creating game: %v", err)
			return dto.Player{}, dto.Player{}, false
		}

		return firstPlayer, secondPlayer, true
	}

	return dto.Player{}, dto.Player{}, false
}

Here, we first try to fetch a game hash from the Redis instance. If there's a hash, it means that a match is on progress. Also, we try to get the players to create a match

firstPlayer, secondPlayer, unavailable := getPlayersToMatch()

The unavailable variable will be true if there's one of those players missing or if there was an error trying to fetch them from the Redis instance

We try to "parse" the hash

_, errorParsing := dto.ParseGameFromMap(encodedGame)

In this case, if there's an error (Meaning, either there's no hash or one of the two players does not exists in that hash), then we could create a new game

Last updated