Skip to content

quibbble/quibbble-controller

Repository files navigation

Quibbble K8s Controller

The project allows Quibbble games to be run in a K8s cluster. Games are spun up as individual pods with their entire lifecycle handled by the Quibbble controller. This allows Quibbble to take advantage of the power of K8s, primarily the ability to scale as well as to seperate and self heal in the event of any single game failure.

Setup

This controller currently requires the usage of NGINX to allow for dynamic routing of games. Meaning that if a game with key tictactoe and id example is created, then NGINX will handle the routing to that game over path /tictactoe/example.

Install NGINX

helm upgrade --install ingress-nginx ingress-nginx \
    --repo https://kubernetes.github.io/ingress-nginx \
    --namespace ingress-nginx --create-namespace

Install Quibbble Controller

helm upgrade --install quibbble-controller quibbble-controller \
    --repo https://quibbble.github.io/quibbble-controller \
    --namespace quibbble --create-namespace

Supported Games

Architecture

There are three main processes in this system.

  1. controller - Processes game create and delete requests.
  2. watcher - Periodically searches for and cleans up stale games.
  3. server - Runs a game instance.

Flows

Game Creation

  • Send POST https://<host>/game with some qqn such as [key "tictactoe"][id "example"][teams "red, blue"].
  • controller processes the request and, if valid, creates K8s ConfigMap, Pod, Service, and Ingress resources.
  • Game can now be accessed at https://<host>/game/tictactoe/example.

Game Connection

  • Join a game by connection to wss://<host>/game/tictactoe/example?name=<name> with websockets.
  • Connection should be open to a server instance and relevant game messages should be recieved.

Game Cleanup

  • watcher will kick off every X timeperiod.
  • Job requests data from all live games by calling GET https://<host>/game/<key>/<id>/activity for each game.
  • If there are no connected players and no recent updates then all K8s related resources are deleted.

REST API

POST /game (create a game)
Parameters
name type data type description
None required QGN QGN descibing the game to create
Responses
http code content-type response
201 text/plain;charset=UTF-8 Created
400 text/plain;charset=UTF-8 Bad Request
409 text/plain;charset=UTF-8 Conflict
500 text/plain;charset=UTF-8 Internal Server Error
503 text/plain;charset=UTF-8 Service Unavailable
Example cURL
 curl -X POST -H "Content-Type: application/qgn" --data @post.qgn https://api.quibbble.com/game
PUT /game (load a game from storage)
Parameters
name type data type description
key required string The name of the game i.e. tictactoe or connect4
id required string The unique id of the game instance to join
Responses
http code content-type response
200 text/plain;charset=UTF-8 OK
400 text/plain;charset=UTF-8 Bad Request
404 text/plain;charset=UTF-8 Not Found
500 text/plain;charset=UTF-8 Internal Server Error
503 text/plain;charset=UTF-8 Service Unavailable
Example cURL
 curl -X PUT https://api.quibbble.com/game?key={key}&id={id}
DELETE /game?key={key}&id={id} (delete a game)
Parameters
name type data type description
key required string The name of the game i.e. tictactoe or connect4
id required string The unique id of the game instance to join
Responses
http code content-type response
200 text/plain;charset=UTF-8 OK
400 text/plain;charset=UTF-8 Bad Request
404 text/plain;charset=UTF-8 Not Found
500 text/plain;charset=UTF-8 Internal Server Error
Example cURL
 curl -X DELETE https://api.quibbble.com/game?key={key}&id={id}
WEBSOCKET /game/{key}/{id}?name={name} (connect to a game)
Parameters
name type data type description
key required string The name of the game i.e. tictactoe or connect4
id required string The unique id of the game instance to join
name required string The name of the player connecting
Responses

None

Example wscat
 wscat -c wss://api.quibbble.com/game/{key}/{id}
GET /game/{key}/{id}/snapshot?format={format} (get game snapshot)
Parameters
name type data type description
key required string The name of the game i.e. tictactoe or connect4
id required string The unique id of the game instance to join
format required one of json or qgn The type of data to return
Responses
http code content-type response
200 application/json or application/qgn JSON or QGN
400 text/plain;charset=UTF-8 Bad Request
404 text/plain;charset=UTF-8 Not Found
500 text/plain;charset=UTF-8 Internal Server Error
Example cURL
 curl -X GET https://api.quibbble.com/game/{key}/{id}/snapshot?format=json
GET /game/activity (get all games activity)
Parameters

None

Responses
http code content-type response
200 application/json Activity for all games
500 text/plain;charset=UTF-8 Internal Server Error
Example cURL
 curl -X GET https://api.quibbble.com/game/activity
GET /game/{key}/{id}/activity (get game activity)
Parameters
name type data type description
key required string The name of the game i.e. tictactoe or connect4
id required string The unique id of the game instance to join
Responses
http code content-type response
200 application/json JSON data describing player count and last update time
404 text/plain;charset=UTF-8 Not Found
Example cURL
 curl -X GET https://api.quibbble.com/game/{key}/{id}/activity

Websocket Messaging

Sendable Messages

join (join a team)
Join
{
    "type": "join",
    "details": "$TEAM"
}
action (perform a game action)
Message
{
    "type": "$ACTION",
    "details": {...}
}
ai (ai plays for the current team)
Message
{
    "type": "ai",
}
chat (send a chat message)
Message
{
    "type": "chat",
    "details": "$MESSAGE"
}

Recievable Messages

snapshot (retrieve a snapshot of the game)
Details

Message sent to all players on every game state change.

Message
{
    "type": "snapshot",
    "details": {...}
}
connection (retrieve player connection information)
Details

Message sent to all players on every player connection, drop, or team change.

Message
{
    "type": "connection",
    "details": {
        "$NAME1": "$TEAM1",
        "$NAME2": "$TEAM2",
        "$NAME3": null
    }
}
chat (retrieve chat message)
Details

Message sent to all players on every sent chat message.

Message
{
    "type": "chat",
    "details": {
        "name": "$NAME",
        "team": "$TEAM",
        "message": "$MESSAGE",
    }
}
error (retrieve error message)
Details

Message sent to origin player on failed action message.

Message
{
    "type": "error",
    "details": "$MESSAGE"
}