quibbble-controller

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

Game Connection

Game Cleanup

REST API

POST /create (create a game) ##### Parameters > | name | type | data type | description | > |-----------|-----------|------------------------------------|-------------------------------------------------------------------| > | None | required | [QGN](/quibbble-controller/pkg/gamenotation/) | [QGN](/quibbble-controller/pkg/gamenotation/) 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` | ##### Example cURL > ```javascript > curl -X POST -H "Content-Type: application/qgn" --data @post.qgn https://api.quibbble.com/create > ```
DELETE /delete?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` | > | `404` | `text/plain;charset=UTF-8` | `Not Found` | > | `500` | `text/plain;charset=UTF-8` | `Internal Server Error` | ##### Example cURL > ```javascript > curl -X DELETE https://api.quibbble.com/delete?key={key}&id={id} > ```
WEBSOCKET /{key}/{id}/connect (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 | ##### Responses > None ##### Example wscat > ```javascript > wscat -c wss://api.quibbble.com/{key}/{id}/connect > ```
GET /{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](/quibbble-controller/pkg/gamenotation/) | > | `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 > ```javascript > curl -X GET https://api.quibbble.com/{key}/{id}/snapshot?format=json > ```
GET /stats (get all game stats) ##### Parameters > None ##### Responses > | http code | content-type | response | > |---------------|-----------------------------------------|---------------------------------------------------------------------| > | `200` | `application/json` | Stats for all games | > | `500` | `text/plain;charset=UTF-8` | `Internal Server Error` | ##### Example cURL > ```javascript > curl -X GET https://api.quibbble.com/stats > ```
GET /{key}/{id}/active (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 > ```javascript > curl -X GET https://api.quibbble.com/{key}/{id}/active > ```

Websocket Messaging

Sendable Messages

join (join a team) ##### Message ```json { "type": "join", "details": "$TEAM" } ```
action (perform a game action) ##### Message ```json { "type": "$ACTION", "details": {...} } ```
ai (ai plays for the current team) ##### Message ```json { "type": "ai", } ```
chat (send a chat message) ##### Message ```json { "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 ```json { "type": "snapshot", "details": {...} } ```
connection (retrieve player connection information) ##### Details Message sent to all players on every player connection, drop, or team change. ##### Message ```json { "type": "snapshot", "details": { "uid": "$UID1", "players": { "$UID1": "$TEAM1", "$UID2": "$TEAM2", "$UID3": null } } } ```
chat (retrieve chat message) ##### Details Message sent to all players on every sent chat message. ##### Message ```json { "type": "chat", "details": { "uid": "$UID", "team": "$TEAM", "message": "$MESSAGE", } } ```
error (retrieve error message) ##### Details Message sent to origin player on failed action message. ##### Message ```json { "type": "error", "details": "$MESSAGE" } ```