Skip to content
This repository has been archived by the owner on Jul 7, 2022. It is now read-only.

Commit

Permalink
documentation updates
Browse files Browse the repository at this point in the history
  • Loading branch information
dgkanatsios committed Jan 12, 2018
1 parent 1a2ce88 commit 885796c
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 25 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
[![unofficial Google Analytics for GitHub](https://gaforgithub.azurewebsites.net/api?repo=AzureFunctionsNodeLeaderboardsCosmos)](https://github.com/dgkanatsios/gaforgithub)

This project is a starter kit that allows you to set up a RESTful API service that stores game leaderboards (scores) and exposes them via HTTP(s) methods/operations. A game developer can use this API service in their game and post new scores, get the top scores, find out the latest ones and get surrounding (ranked) top players of a current user. A Unity client is also provided with a corresponding C# SDK. You can read some of the thought process that drove the creation of this project in the blog post [here](https://dgkanatsios.com/2018/01/08/designing-a-general-purpose-game-leaderboard/).
This project is a starter kit that allows you to set up a RESTful API service that stores game leaderboards (scores) and exposes them via HTTP(s) methods/operations. A game developer can use this API service in their game and post new scores, get the top scores, find out the latest ones more. A Unity client is also provided with a corresponding C# SDK. You can read some of the thought process that drove the creation of this project in the blog post [here](https://dgkanatsios.com/2018/01/08/designing-a-general-purpose-game-leaderboard/).

## Deployment

Expand All @@ -14,11 +14,11 @@ One-click deployment via [Azure ARM template](https://docs.microsoft.com/en-us/a
<a href="https://portal.azure.com/#create/Microsoft.Template/uri/https%3A%2F%2Fraw.githubusercontent.com%2Fdgkanatsios%2FAzureFunctionsNodeLeaderboard%2Fmaster%2Fazuredeploy.json" target="_blank"><img src="http://azuredeploy.net/deploybutton.png"/></a>

The deployment will take some time to execute (due to resources' creation and time to pull code from GitHub), please be patient.
Be aware that App name, Storage account name and CosmosDB database name must all be globally unique. Otherwise, the deployment will fail to complete and you will see an error message in the Azure portal. In this case, you should delete the created Resource Group and try again.
Be aware that App name, Storage account name and Cosmos DB database name must all be globally unique. Otherwise, the deployment will fail to complete and you will see an error message in the Azure portal. In this case, you should delete the created Resource Group and try again.

## High level architecture

Proposed technology/architecture stack includes an [Express](https://expressjs.com/) [Node.js](https://nodejs.org/) app hosted on an [Azure Function](https://azure.microsoft.com/en-us/services/functions/) that talks to a [CosmosDB](https://azure.microsoft.com/en-us/services/cosmos-db/) database via its [MongoDB API]((https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-introduction)). [Azure Application Insights](https://azure.microsoft.com/en-us/services/application-insights/) service is used to provide information and metrics regarding application performance and behavior. A Unity game engine client is also provided, with a relevant SDK to access the leaderboards API.
The technology/architecture stack includes an [Express](https://expressjs.com/) [Node.js](https://nodejs.org/) app hosted on an [Azure Function](https://azure.microsoft.com/en-us/services/functions/) that talks to a [Cosmos DB](https://azure.microsoft.com/en-us/services/cosmos-db/) database via its [MongoDB API]((https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-introduction)). [Azure Application Insights](https://azure.microsoft.com/en-us/services/application-insights/) service is used to provide information and metrics regarding application performance and behavior. A Unity game engine client is also provided, with a relevant SDK to access the leaderboards API.

![alt text](https://github.com/dgkanatsios/AzureFunctionsNodeLeaderboards-Cosmos/blob/master/media/functions.JPG?raw=true "Reference architecture")

Expand All @@ -40,15 +40,15 @@ Leaderboards within games can easily vary. In designing this library, we tried t
## Usage
After you deploy the script, you will have an Azure Resource Group containing the following resources:

- A CosmosDB database that uses the MongoDB API
- A Cosmos DB database that uses the MongoDB API
- A Storage Account
- An App Service Name that hosts the Azure Function with its relevant App Service Plan
- The Azure Function that will pull the code from the GitHub repo you designate and an Application Insights service to monitor its execution

Now, you can call the available web service operations from your game. You can visit the Azure Portal to get the Azure Function URL, it will be in the format https://**functionName**.azurewebsites.net

## Authentication
All requests to the leaderboards API **must** contain two headers on each request: `x-ms-client-principal-id` and `x-ms-client-principal-name`. If these values are missing, then the request will fail. The `x-ms-client-principal-id` should be unique for each user. Meaning, each time you use the same `x-ms-client-principal-id` for inserting a new score, this score will belong to the same user. The implemented leaderboards API does not impose any method to validate/verify these values, so you are free to implement whatever you like. However, App Service supports various authentication methods which automatically set the required headers, you can check them [here](https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-overview). For more details on authentication/authorization, please check [here](docs/technicalDetails.md).
All requests to the leaderboards API **must** contain two headers on each request: `x-ms-client-principal-id` and `x-ms-client-principal-name`. If these values are missing, then the request will fail. The `x-ms-client-principal-id` should be unique for each user. Meaning, each time you use the same `x-ms-client-principal-id` for inserting a new score, this score will belong to the same user. The implemented leaderboards API does not impose any method to validate/verify these values, so you are free to implement whatever you like. However, App Service supports various authentication methods which automatically set the required headers, you can check them [here](https://docs.microsoft.com/en-us/azure/app-service/app-service-authentication-overview). The Unity client sample in this repo contains code to set these headers with current user's details. For more details on authentication/authorization, please check [the tech details file here](docs/technicalDetails.md).

## Operations supported

Expand All @@ -69,7 +69,7 @@ Here you can see a short list/summary of all the operations that are supported,
| GET | https://**functionURL**/api/health | Gets the application's health |

## Docker
You might notice that there is a Dockerfile inside the Azure Functions code. Check the [docs/technicalDetails.md](docs/technicalDetails.md) file for instructions on how to build and run the projet on a Docker container.
You might notice that there is a Dockerfile inside the Azure Functions code. Check the [docs/technicalDetails.md](docs/technicalDetails.md) file for instructions on how to build and run the project on a Docker container and on a Kubernetes cluster.

## More details
- Check the [docs/FAQ.md](docs/FAQ.md) for answers to common questions you may have about the project.
Expand Down
2 changes: 1 addition & 1 deletion azuredeploy.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"databaseAccountName": {
"type": "string",
"metadata": {
"description": "The CosmosDB database account name (server name). Needs to be globally unique."
"description": "The Cosmos DB database account name (server name). Needs to be globally unique."
}
},
"hostingPlanName": {
Expand Down
4 changes: 2 additions & 2 deletions client-unity/Assets/LeaderboardsSDKUIScript.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ public void Start()

//get the authentication token(s) somehow...
//e.g. for facebook, check the Unity Facebook SDK at https://developers.facebook.com/docs/unity
LeaderboardsSDKClient.Instance.userID = "12345";
LeaderboardsSDKClient.Instance.username = "dimitris2";
LeaderboardsSDKClient.Instance.userID = "CURRENT_PLAYER_UNIQUE_ID";
LeaderboardsSDKClient.Instance.username = "CURRENT_PLAYER_USERNAME";

//check here for more information regarding authentication and authorization in Azure App Service
//https://azure.microsoft.com/en-us/documentation/articles/app-service-authentication-overview/
Expand Down
24 changes: 12 additions & 12 deletions docs/FAQ.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ PORT=3000
AZURE_FUNCTIONS_RUNTIME=false
NODE_ENV=development
```
### How can I see the data on my CosmosDB instance?
[Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/) is a free and cross-platform tool that allows you to browse your Azure Storage accounts as well as your CosmosDB databases. You can also use familiar MongoDB related tools, like [MongoChef](https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-mongochef) and [Robomongo](https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-robomongo).
### How can I see the data on my Cosmos DB instance?
[Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/) is a free and cross-platform tool that allows you to browse your Azure Storage accounts as well as your Cosmos DB databases. You can also use familiar MongoDB related tools, like [MongoChef](https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-mongochef) and [Robomongo](https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-robomongo).


### What can I use for authentication/authorization?
Expand Down Expand Up @@ -78,16 +78,16 @@ Since your API is stateless, you should use a store to preserve state in order t

## Monitoring

### What are Request Units (RUs) in CosmosDB?
CosmosDB is a multi-tenant database. As such, you don't rent a CosmosDB server with specific hardware specifications. When you use CosmosDB, you pay for something called 'Request Units' (RUs) which is a measure of the computing resources that are needed in order to serve a specific client request. To find out more about RUs, check the official documentation [here](https://docs.microsoft.com/en-us/azure/cosmos-db/request-units#request-units-and-request-charges).
### What are Request Units (RUs) in Cosmos DB?
Cosmos DB is a multi-tenant database. As such, you don't rent a Cosmos DB server with specific hardware specifications. When you use Cosmos DB, you pay for something called 'Request Units' (RUs) which is a measure of the computing resources that are needed in order to serve a specific client request. To find out more about RUs, check the official documentation [here](https://docs.microsoft.com/en-us/azure/cosmos-db/request-units#request-units-and-request-charges).

### How much do I pay for the CosmosDB database this project is creating?
### How much do I pay for the Cosmos DB database this project is creating?
For the most updated pricing details, check out the official pricing documentation [here](https://azure.microsoft.com/en-us/pricing/details/cosmos-db/). Be aware that the collection that is created by the project uses 1000RUs (this is the default), you can modify it via Azure Portal or programmatically and scale it down to 400RUs (that's the minimum), if you don't need the extra horse power. If you do need it though, you could as easily scale it up to 10.000 RUs.

### How can I see how many (RUs) my queries are consuming?
There are various ways that you can monitor your RUs consumption, check the official documentation [here](https://docs.microsoft.com/en-us/azure/cosmos-db/request-units#use-api-for-mongodbs-portal-metrics) to see some of them. If you happen to have many similar queries hitting the database in a short amount of time, maybe you should consider refactoring the project to add a caching layer (we recommend [Azure Redis Cache](https://azure.microsoft.com/en-us/services/cache/)) for your data.

### Tell me more about CosmosDB partitioning and scaling
### Tell me more about Cosmos DB partitioning and scaling
Please check the official and frequently updated documentation [here](https://docs.microsoft.com/en-us/azure/cosmos-db/partition-data).

### Where is the Application Insights documentation?
Expand All @@ -103,7 +103,7 @@ The Function gets configured to use Application Insights for instrumentation. Ch

### What resources are created by the ARM template deployment (azuredeploy.json file)?
You should the following resources created in your Azure subscription
- A CosmosDB database account
- A Cosmos DB database account
- A Storage account (that backs your Azure Function)
- An App Service Plan (uses the Consumption plan)
- An App Service (hosts your Function)
Expand Down Expand Up @@ -132,13 +132,13 @@ Other two options to prevent this behavior would be
Moreover, on the very first call to your Azure Function (the so-called "cold start") there will be a delay as node installs, reads and loads all module files. They are cached, though, so subsequent executions have significantly better performance. You can check [here](https://github.com/Azure/azure-functions-pack) for a way this can be improved (even though this approach hasn't been tested with current project).

### I saw you're using Mongoose discriminators. Why?
To save you some money. CosmosDB charges per collection, check [here](https://anthonychu.ca/post/cosmos-db-mongoose-discriminators/) for a relevant blog post.
To save you some money. Cosmos DB charges per collection, check [here](https://anthonychu.ca/post/cosmos-db-mongoose-discriminators/) for a relevant blog post.

### How much does CosmosDB cost?
You can read [here](https://azure.microsoft.com/en-us/pricing/details/cosmos-db/) in order to undestand CosmosDB pricing.
### How much does Cosmos DB cost?
You can read [here](https://azure.microsoft.com/en-us/pricing/details/cosmos-db/) in order to undestand Cosmos DB pricing.

### Can I try CosmosDB for free?
Yup! Check [here](https://azure.microsoft.com/en-us/try/cosmosdb/). Also, check [here](https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-introduction) to learn more about MongoDB API for CosmosDB. For CosmosDB use cases, check [here](https://docs.microsoft.com/en-us/azure/cosmos-db/use-cases). For some free Azure resources, check [here](https://azure.microsoft.com/en-us/free/).
### Can I try Cosmos DB for free?
Yup! Check [here](https://azure.microsoft.com/en-us/try/cosmosdb/). Also, check [here](https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-introduction) to learn more about MongoDB API for Cosmos DB. For Cosmos DB use cases, check [here](https://docs.microsoft.com/en-us/azure/cosmos-db/use-cases). For some free Azure resources, check [here](https://azure.microsoft.com/en-us/free/).

### Where is the Azure Functions documentation? How are Functions charged?
Check [here](https://docs.microsoft.com/en-us/azure/azure-functions/). When you deploy the Function via the ARM template provided, you are billed by Azure Functions consumption plan. Great thing with consumption plan is that the first million calls per month are free. It's a pretty cost-effecive plan, for the specifics rest you should check the relevant pricing page [here](https://docs.microsoft.com/en-us/azure/cosmos-db/mongodb-feature-support).
Expand Down
17 changes: 15 additions & 2 deletions docs/technicalDetails.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

## Database architecture

You can easily get acquainted with the database architecture by checking the User and Score Mongoose models on `scores/api/models` folder. We're using Mongoose discriminators to save everything on a single CosmosDB collection. That's why you'll aso find a base model schema, that refers to a single collection called `gamedata`.
You can easily get acquainted with the database architecture by checking the User and Score Mongoose models on `scores/api/models` folder. We're using Mongoose discriminators to save everything on a single Cosmos DB collection. That's why you'll aso find a base model schema, that refers to a single collection called `gamedata`.

### Score schema

Expand Down Expand Up @@ -54,7 +54,7 @@ Of course, you can (should!) replace **username**,**azurefunctionsnodeleaderboar
docker run -d -p 3000:3000 -e "MONGODB_CONNECTION_STRING=mongodb://node-scores:12345678@node-scores.documents.azure.com:10255/?ssl=true&replicaSet=globaldb" --name leaderoardsapi username/azurefunctionsnodeleaderboards:0.1
```

Don't forget to set your correct CosmosDB connection string and your Docker image name.
Don't forget to set your correct Cosmos DB connection string and your Docker image name.

- To see how you can host your Docker image on Azure Web App for Containers, check [here](https://docs.microsoft.com/en-us/azure/app-service/containers/tutorial-custom-docker-image)
- To create a managed Kubernetes Azure Container Service (AKS) cluster, check [here](https://docs.microsoft.com/en-us/azure/aks/kubernetes-walkthrough)
Expand Down Expand Up @@ -113,3 +113,16 @@ public void ListTopScoresForAllUsers()
StatusText.text = "Loading...";
}
```

### Authentication

You need to set two required HTTP headers when calling the leaderboard API methods. These are set in the sample game with the following lines of code:

```csharp
//get the authentication token(s) somehow...
//e.g. for facebook, check the Unity Facebook SDK at https://developers.facebook.com/docs/unity
LeaderboardsSDKClient.Instance.userID = "CURRENT_PLAYER_UNIQUE_ID";
LeaderboardsSDKClient.Instance.username = "CURRENT_PLAYER_USERNAME";
```

You need to somehow set them yourself, either using unique values stored in game's local storage, or get them via a web service you own, or use custom authentication means (like [Facebook login](https://developers.facebook.com/docs/unity)).
2 changes: 1 addition & 1 deletion leaderboardsFunctionApp/scores/api/models/baseModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,5 @@ const Base = mongoose.model('Base', new mongoose.Schema({}, baseOptions));

module.exports = Base;

//check this blog post on why Mongoose discriminators is a great option when using MongoDB API with CosmosDB
//check this blog post on why Mongoose discriminators is a great option when using MongoDB API with Cosmos DB
//https://anthonychu.ca/post/cosmos-db-mongoose-discriminators/
2 changes: 1 addition & 1 deletion various/kubedeploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ metadata:
name: mysecret
type: Opaque
data:
mongoconnectionstring: <YOUR BASE64 ENCODED COSMOSDB CONNECTION STRING>
mongoconnectionstring: <YOUR BASE64 ENCODED COSMOS DB CONNECTION STRING>
---
apiVersion: apps/v1beta1
kind: Deployment
Expand Down

0 comments on commit 885796c

Please sign in to comment.