/nodejs-game-statistics

A Node.js application to generate simple game statistics.

Primary LanguageTypeScript

Node.js + TypeScript Application

A Node.js application gets a list of games with its popularity points from an external service and generates the following statistics: top 5, top 10 and top 100 games by their popularity and a list of those games grouped by their first letter in their name. These statistics are saved so then authorized clients can consume it by hitting this application's API. Some of the clients can even be notified when statistics are regenerated so they can only request for it when notified.

Installing

MariaDB Server

docker run --name some-mariadb -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mariadb:10.3
docker exec -it some-mariadb bash
mysql -p
> root

In a real world application I'd use the concept of migrations to create the necessary tables on the database and seeds to populate them as required. But for now let's just make that by hand.

-- Insert the following on the container.
CREATE DATABASE db_games_stats;
USE db_games_stats;

-- Only insert this data after booting the application at least once.
-- On application first boot tables are going to be created based on the Models.
INSERT INTO user (clientId, isLazy, validUntil, deletedAt) VALUES ('tokenTestForLazyClient', 1, TIMESTAMPADD(MONTH, 1, NOW()), NULL);
INSERT INTO user (clientId, isLazy, validUntil, deletedAt) VALUES ('tokenTestForLazyClient__1', 1, TIMESTAMPADD(MONTH, 1, NOW()), NULL);
INSERT INTO user (clientId, isLazy, validUntil, deletedAt) VALUES ('tokenTestForEagerClient', 0, TIMESTAMPADD(MONTH, 1, NOW()), NULL);

Redis Server

docker run -p 6379:6379 redis

Game Data Service

Just make sure you have any API at http://localhost:8080/api/v1/games that returns to you a list of games like the following:

[{
    "id": 123,
    "name": "Some cool game :)",
    "popularity": 321
}, {
    "id": 124,
    "name": "Some other cool game as well! :)",
    "popularity": 564
}]

Application

cd application
npm install
npm run start

How it works

Statistics are generated by a scheduled task that runs hourly and set in Redis.
A client hits the API using an HTTP post request. After client validation, previously generated statistics are read from the Redis Server

Generate Statistics Workflow

A scheduled task runs every 1 hour to get the list of games from the Game Data Service.

  1. Top 5, 10 and 100 more popular games statistics are generated.
  2. Top Statistics are set in Redis to the key 'topStatistics'.
  3. Grouped by game name's first letter statistics are generated.
  4. Grouped by game name statistics are set in Redis to the key 'groupedByFirstLetterStatistics'.

Consuming Statistics Workflow

A client makes an HTTP POST request to one of the API's endpoints.

  1. It is verified if the client is valid.
  2. On valid client, statistics are read from Redis and sent back to the client.

API's Endpoints

Both top statistics and grouped by first letter statistics can be consumed like the following:
Remember that you need an actual valid client token to consume the API. Check the Installing section.

Method Endpoint
POST /topstatistics
POST /popularityalphabetsorted

Top Statistics return

{
    "top5": [{
        "id": 503401,
        "name": "Game 1",
        "popularity": 10000000
    }],
    "top10": [{
        "id": 503401,
        "name": "Game 1",
        "popularity": 10000000
    }],
    "top100": [{
        "id": 503401,
        "name": "Game 1",
        "popularity": 10000000
    }]
}

Grouped by Name's First Letter return

{
    "a": {
        "totalPopularity": "213912931293",
        "totalGames": 10,
        "games": [{
            "id": 503401,
            "name": "a game 1",
            "popularity": 10000000
        }]
    },
    "b": {
        "totalPopularity": "123092139",
        "totalGames": 8,
        "games": [{
            "id": 503401,
            "name": "b game 1",
            "popularity": 342
        }]
    }
}

Unauthorized Client return

{
    "status": 401,
    "message": "Unauthorized."
}