Skip to content

Commit

Permalink
Merge pull request #102 from Arquisoft/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
marco-qg authored Apr 11, 2024
2 parents d00b57d + a83ff63 commit ab8b6b1
Show file tree
Hide file tree
Showing 58 changed files with 28,605 additions and 299 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ jobs:
- run: npm --prefix webapp ci
- run: npm --prefix storeQuestionService ci
- run: npm --prefix userStatsService ci
- run: npm --prefix gameservice ci
- run: npm --prefix users/authservice test -- --coverage
- run: npm --prefix users/userservice test -- --coverage
- run: npm --prefix gatewayservice test -- --coverage
- run: npm --prefix webapp test -- --coverage
- run: npm --prefix storeQuestionService test -- --coverage
- run: npm --prefix userStatsService test -- --coverage
# - run: npm --prefix gameservice test -- --coverage
- name: Analyze with SonarCloud
uses: sonarsource/sonarcloud-github-action@master
env:
Expand Down
22 changes: 22 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ jobs:
- run: npm --prefix storeQuestionService ci
- run: npm --prefix userStatsService ci
- run: npm --prefix webapp ci
- run: npm --prefix gameservice ci
- run: npm --prefix users/authservice test -- --coverage
- run: npm --prefix users/userservice test -- --coverage
- run: npm --prefix gatewayservice test -- --coverage
- run: npm --prefix webapp test -- --coverage
- run: npm --prefix storeQuestionService test -- --coverage
- run: npm --prefix userStatsService test -- --coverage
#- run: npm --prefix gameservice test -- --coverage
- name: Analyze with SonarCloud
uses: sonarsource/sonarcloud-github-action@master
env:
Expand Down Expand Up @@ -207,6 +209,26 @@ jobs:
registry: ghcr.io
workdir: userStatsService
platforms: linux/arm64
docker-push-gameservice:
name: Push game service Docker Image to GitHub Packages
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
needs: [e2e-tests]
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- uses: actions/checkout@v4
- name: Publish to Registry
uses: elgohr/Publish-Docker-Github-Action@v5
with:
name: arquisoft/wiq_es6c/gameservice
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
registry: ghcr.io
workdir: gameservice
platforms: linux/arm64
deploy:
name: Deploy over SSH
runs-on: ubuntu-latest
Expand Down
17 changes: 17 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ services:
environment:
MONGODB_URI: mongodb://mongodb:27017/userdb

gameservice:
container_name: gameservice-${teamname:-defaultASW}
image: ghcr.io/arquisoft/wiq_es6c/gameservice:latest
profiles: ["dev", "prod"]
build: ./gameservice
depends_on:
- questiongeneratorservice
ports:
- "8005:8005"
networks:
- mynetwork
environment:
QUESTIONS_GENERATOR_SERVICE_URL: http://questiongeneratorservice:8007
STORE_STATS_SERVICE: http://userstatsservice:8003

questiongeneratorservice:
container_name: questiongeneratorservice-${teamname:-defaultASW}
image: ghcr.io/arquisoft/wiq_es6c/questiongeneratorservice:latest
Expand Down Expand Up @@ -99,6 +114,8 @@ services:
USER_STATS_SERVICE_URL: http://userstatsservice:8003
STORE_QUESTION_SERVICE_URL: http://storequestionservice:8004
QUESTIONS_GENERATOR_SERVICE_URL: http://questiongeneratorservice:8007
GAME_SERVICE_URL: http://gameservice:8005


webapp:
container_name: webapp-${teamname:-defaultASW}
Expand Down
51 changes: 24 additions & 27 deletions docs/src/05_building_block_view.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ package "WIQ App" {
:User: -> [WebApp] : " Interacts "
[WebApp] <-> [Gateway Service] : Redirects Requests
[Gateway Service] <--down-> [Game Service] : Plays
[Gateway Service] <-- [Question Historic Service] : Loads data
[Gateway Service] <-- [User Statistics Service] : Loads data
[Gateway Service] <-- [Store Question Service] : Loads data
[Gateway Service] <-- [User Stats Service] : Loads data
[Gateway Service] <-> [UserAuth Service] : Logs in / Registers
[Game Service] -> [User Statistics Service] : Stores data
[Game Service] -> [User Stats Service] : Stores data
[Game Service] <-left-> [Questions Service] : Gets questions
[Questions Service] -up-> [Question Historic Service] : Stores data
[Questions Service] -up-> [Store Question Service] : Stores data
}
[Questions Service] <.left.> [WikiData] : " Gets data "
----
Expand Down Expand Up @@ -87,54 +87,51 @@ package "WIQ App"{
component "WebApp"
component "Gateway Service" as GatewayS
package "Game Service" {
component "Game Controller"
component "Game Service"
package "Store Question Service" as QHS{
component "Store-Q Service" as QHController
database "storedquestion" as QhDB
}
package "User Statistics Service" as USS {
component "Statistics Controller"
database "Database" as USDB
}
package "Questions Historic Service" as QHS{
component "Question Historic Controller" as QHController
database "Database" as QhDB
}
package "Questions Service"{
component "Wikidata Extractor"
component "Questions Generator"
database "Database" as QSDB
package "User Stats Service" as USS {
component "User Stats Service"
database " statsdb " as USDB
}
package "UserAuth Service" {
component "Auth Service"
component "User Service"
database "Database" as UADB
database "userdb" as UADB
}
package "Questions Service"{
component "Wikidata Extractor"
component "Questions Generator Service"
database "questions" as QSDB
}
}
User -right-> WebApp : Uses
WebApp <-right-> GatewayS: Redirects requests
GatewayS <--up--> "UserAuth Service" : "Handles user\nlogin/registry"
GatewayS <-down-> "Game Service" : "Handles user current game\n"
GatewayS <-down-> "Game Service" : "Handles user current game"
GatewayS <--up-- "QHS" : "\nReceives generated\nquestions"
GatewayS <--- "USS" : "Receives\t\t\t\nuser statistics\t\t\t"
"Game Service" <---> "Questions Service" : "Receives question petitions,\nsends questions\n\n"
"Game Service" ---> "USS" : "Sends user\t\nstatistics\t\t"
"Questions Service" -up-> "QHS" : "Sends\ngenerated\nquestions"
"Questions Service" -up-> "QHS" : " Sends\n generated\n questions"
"Wikidata" .up.> "Wikidata Extractor" : "Returns data"
"Wikidata" <.up. "Wikidata Extractor" : "Queries"
"Wikidata Extractor" --> QSDB
"Questions Generator" <-- QSDB
"Questions Generator" --> QSDB
"Questions Generator Service" <-- QSDB
"Questions Generator Service" --> QSDB
"QHController" --> QhDB
"QHController" <-- QhDB
"Statistics Controller" --> USDB
"Statistics Controller" <-- USDB
"User Stats Service" --> USDB
"User Stats Service" <-- USDB
"Auth Service" --> UADB
"Auth Service" <-- UADB
Expand Down
43 changes: 24 additions & 19 deletions docs/src/07_deployment_view.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,26 @@ cloud "Azure Cloud\n" {
node "Gateway Container"{
node "Gateway Service"
}
node " User Container "{
node "User Container"{
node "User Service"
}
node " Auth Container "{
node "Auth Container"{
node "Auth Service"
}
node "\tGame Container\t"{
node "Game Generator Service"
node "Game Container"{
node "Game Service"
}
node "Questions History Container"{
node "Questions History Service"
node "Store Question Container"{
node "Store Question Service"
}
node "User Stats Container\t"{
node "User Stats Service"
}
node "Questions Generator Container"{
node "Questions Generator Service"
node "Question Generator Container"{
node "Question Generator Service"
}
node "Wikidata Extractor Container"{
node "Wikidata Extractor Service"
}
}
}
Expand All @@ -49,28 +52,30 @@ actor "User"
"Web App" -- "Gateway Service" : "port: 8000"
"Gateway Service" -- "Questions History Service" : "port: 8004 "
"Gateway Service" -- "Store Question Service" : "port: 8004"
"Gateway Service" -- "User Stats Service" : "port: 8003"
"Gateway Service" -up- "Auth Service" : "port: 8002 "
"Gateway Service" -up- "User Service" : "port: 8001"
"Gateway Service" -right- "Game Generator Service" : " port: 8005 "
"Gateway Service" -right- "Game Service" : " port: 8005 "
"Game Service" -- "User Stats Service" : "port: 8003"
"Game Service" -- "Question Generator Service" : " port: 8007"
"Game Generator Service" -- "User Stats Service" : "port: 8003"
"Game Generator Service" -- "Questions Generator Service" : " port: 8006"
"Question Generator Service" -- "Store Question Service" : "port: 8004"
"Question Generator Service" -- "Wikidata Extractor Service" : "port: 8008"
"Questions Generator Service" -- "Questions History Service" : "port: 8004"
"Questions Generator Service" -- "Wikidata" : "HTTPS"
"Wikidata Extractor Service" -- "Wikidata" : "HTTPS"
----

In addition to what is shown in the diagram, we will also use Graphana and Prometheus during the production stage as code monitoring systems.

Motivation::

Our goal is to run the application with Docker in a Azure VM.
Despite our initial goal being to run the application with Docker in an Azure VM, as we were running out of Azure Credits, we decided to switch to an Oracle VM.
However, during the production stage, each contributor will deploy the project locally.
Final product will be deployed in http://wiq.sytes.net/ (if that does not work, try http://20.77.37.219:3000/).
Final product will be deployed in http://wiq.sytes.net/ (if that does not work, try http://158.179.212.42:3000/).

Quality and/or Performance Features::
As for performance features, our current Azure MV has 2 GiB RAM and 1vCPU.
If that was not enough, we can always switch to an Oracle VM, which has better resources for free.
Each microservice has its own container as well as its own database in case of needing one.
Previously, we had an Azure VM with 2 GiB RAM and 1vCPU. When we decided to change to the Oracle VM, we also improve our resources, as it was free.
Finally, our Oracle VM has 24 GiB RAM and 4vCPU.
Each microservice has its own container. There are also two databases, one for the Question Generator and Wikidata Extractor services, and another one for the rest of the containers which may need it.
2 changes: 2 additions & 0 deletions gameservice/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
coverage
20 changes: 20 additions & 0 deletions gameservice/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Use an official Node.js runtime as a parent image
FROM node:20

# Set the working directory in the container
WORKDIR /usr/src/gameService

# Copy package.json and package-lock.json to the working directory
COPY package*.json ./

# Install app dependencies
RUN npm install

# Copy the app source code to the working directory
COPY . .

# Expose the port the app runs on
EXPOSE 8005

# Define the command to run your app
CMD ["node", "game-service.js"]
109 changes: 109 additions & 0 deletions gameservice/game-service.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
const express = require('express');
const cors = require('cors');
const axios = require('axios');

const app = express();
const port = 8005;

const questionService = process.env.QUESTIONS_GENERATOR_SERVICE_URL || 'http://localhost:8007';
const userStatsService = process.env.STORE_STATS_SERVICE ||'http://localhost:8003';

function generateAleatoryString() {
let characters = 'abcdefghijklmnopqrstuvwxyz0123456789'; // Caracteres alfanuméricos
let len = 24;
let result = '';
for (let i = 0; i < len; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
}


// Middleware to parse JSON in request body
app.use(express.json());

// Middleware to enable CORS (cross-origin resource sharing). In order for the API to be accessible by other origins (domains).
app.use(cors());

var gameId = 0;

app.get('/generateGameUnlimitedQuestions', async (req, res) => {
try {
console.log("Llegamos a crear un id del juego")
var gameId = generateAleatoryString()
res.json(gameId)
} catch (error) {
res.status(500).json({ error: 'Internal Server Error' })
}
})


// Route for getting questions
app.get('/gameUnlimitedQuestions', async (req, res) => {
try {
// TODO: Implement logic to fetch questions from MongoDB and send response
// const questions = await Question.find()
console.log("Llegamos a pedir preguntas")
const questionGenerated = await axios.get(`${questionService}/questions?n_preguntas=${1}`);
console.log("Pedimos las preguntas")
res.json(questionGenerated.data);
} catch (error) {
// res.status(500).json({ message: error.message })
res.status(500).json({ error: 'Internal Server Error' });
}
});

app.post('/storeGame', async (req, res) => {
try {
//hay que preparar los datos para enviarlos al servicio
var id = req.body.id
var username = req.body.username
var points = req.body.points
var questions = req.body.questions
console.log("Vamos a guardar resultado")
const store = await axios.post(`${userStatsService}/history/game`, {id, username, points, questions})
console.log("Guardamos resultado")
res.json(store.data)
} catch (error) {
res.status(500).json({ error: 'Internal Server Error' });
}
})

app.use((err, req, res, next) => {
console.error(`An error occurred: ${err}`);
res.status(500).send(`An error occurred: ${err.message}`);
});



//libraries required for OpenAPI-Swagger
const swaggerUi = require('swagger-ui-express');
const fs = require("fs")
const YAML = require('yaml')

// Read the OpenAPI YAML file synchronously
openapiPath='./openapi.yaml'
if (fs.existsSync(openapiPath)) {
const file = fs.readFileSync(openapiPath, 'utf8');

// Parse the YAML content into a JavaScript object representing the Swagger document
const swaggerDocument = YAML.parse(file);

// Serve the Swagger UI documentation at the '/api-doc' endpoint
// This middleware serves the Swagger UI files and sets up the Swagger UI page
// It takes the parsed Swagger document as input
app.use('/api-doc', swaggerUi.serve, swaggerUi.setup(swaggerDocument));
} else {
console.log("Not configuring OpenAPI. Configuration file not present.")
}

// Start the server
const server = app.listen(port, () => {
console.log(`Game Service listening at http://localhost:${port}`);
});

server.on('close', () => {
// Close the Mongoose connection
});

module.exports = server
Loading

0 comments on commit ab8b6b1

Please sign in to comment.