Skip to content

Commit

Permalink
fix(functions-load-balancing): fix functions build
Browse files Browse the repository at this point in the history
  • Loading branch information
albertodigioacchino committed Jan 25, 2021
1 parent 9e5c261 commit c9e8133
Show file tree
Hide file tree
Showing 8 changed files with 585 additions and 255 deletions.
755 changes: 535 additions & 220 deletions packages/functions/package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"firebase-admin": "^9.2.0",
"firebase-functions": "^3.11.0",
"axios": "^0.21.1",
"@pipeline/common": "^0.1.0",
"@pipeline/common": "file:./_packages_copy/common",
"express": "^4.17.1",
"lodash": "^4.17.20"
},
Expand All @@ -33,4 +33,4 @@
},
"private": true,
"version": "0.2.0"
}
}
22 changes: 15 additions & 7 deletions packages/functions/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
import * as functions from 'firebase-functions';
import * as admin from "firebase-admin";

admin.initializeApp();

if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'onOnlineGameStatusUpdate') {
exports.onOnlineGameStatusUpdate = require('./load-balancing/onOnlineGameStatusUpdate').onOnlineGameStatusUpdate;
}

if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'selectBestRTDBInstance') {
exports.selectBestRTDBInstance = require('./load-balancing/selectBestRTDBInstance').selectBestRTDBInstance;
}

if (!process.env.FUNCTION_NAME || process.env.FUNCTION_NAME === 'scheduledSyncStatusJob') {
exports.scheduledSyncStatusJob = require('./load-balancing/syncStatusJob').scheduledSyncStatusJob;
}

// Start writing Firebase Functions
// https://firebase.google.com/docs/functions/typescript

export const helloWorld = functions.https.onRequest((request, response) => {
functions.logger.info("Hello logs!", {structuredData: true});
response.send("Hello from Firebase!");
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as admin from "firebase-admin";
import {FirebaseCollection, RTDBInstance, RTDBPaths, Status} from "@pipeline/common";
import {PROJECT_ID} from "../utils/rtdb";
import FieldValue = admin.firestore.FieldValue;
import {end, RTDB_LOCATION} from "../utils/general";
import {RTDB_LOCATION} from "../utils/general";
import {moveGameFromRTDBToFirestore} from "./moveGameFromRTDBToFirestore";

const db = admin.firestore();
Expand All @@ -21,6 +21,9 @@ const INSTANCE_ID = `${PROJECT_ID}-default-rtdb`
* Next, if the new status is 'offline', an RTDB query is performed to look for the online users for that game.
* If more than one are found (because one is the one we were updating), this means there is still someone in the game
* Otherwise, we can move the game from RTDB back to Firestore
*
* TODO check if locked cards should be unlocked
*
*/

export const onOnlineGameStatusUpdate = functions.database.instance(INSTANCE_ID).ref(`/${RTDBPaths.Statuses}/{userId}`)
Expand All @@ -35,7 +38,7 @@ export const onOnlineGameStatusUpdate = functions.database.instance(INSTANCE_ID)

if (originalStatus.state !== nextStatus.state) {

const gameId = nextStatus.gameId;
const gameId = nextStatus.gameId as string;

logger.log(`User ${userId} from game ${gameId} going from ${originalStatus.state} to ${nextStatus.state}`);

Expand All @@ -57,10 +60,6 @@ export const onOnlineGameStatusUpdate = functions.database.instance(INSTANCE_ID)
await moveGameFromRTDBToFirestore(gameId, db, rtdb);
logger.log(`Game ${gameId} moved from RTDB to Firestore`);
}
return end();
}
return end();

}
return end();
});
19 changes: 9 additions & 10 deletions packages/functions/src/load-balancing/selectBestRTDBInstance.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import * as functions from 'firebase-functions';
import * as admin from "firebase-admin";
import axios from 'axios';
import FieldValue = admin.firestore.FieldValue;
import {checkAuth} from "../utils/auth";
import {runTransactionWithRetry} from "../utils/db";
import {FirebaseCollection, RTDBInstance, Game, RTDBPaths} from '@pipeline/common';
import {getRTDBInstanceName, PROJECT_ID} from "../utils/rtdb";
import {end, RTDB_LOCATION} from "../utils/general";
import {FirebaseCollection, Game, RTDBPaths} from '@pipeline/common';
import {RTDB_LOCATION} from "../utils/general";
const db = admin.firestore();
const logger = functions.logger;

const getNextRTDBInstanceNum = async (): Promise<number> => {
/*const getNextRTDBInstanceNum = async (): Promise<number> => {
const res = await axios.get(`https://firebasedatabase.googleapis.com/v1beta/projects/${PROJECT_ID}/locations/-/instances?pageSize=100`, {
headers: {
'Authorization': `Bearer `,
Expand Down Expand Up @@ -41,6 +38,8 @@ const createNewRTDBInstance = async () => {
return newRTDBInstanceName;
}
*/


export const selectBestRTDBInstance = functions.region(
'europe-west1'
Expand All @@ -52,21 +51,21 @@ export const selectBestRTDBInstance = functions.region(

if (req.method !== "GET") {
res.status(405).send("Method not allowed");
return end();
return;
}

const gameId = req.query.gameId as string;
if (!gameId) {
res.status(400).send("Missing required parameter");
return end();
return;
}

const decodedToken = await checkAuth(req, res);

if (!decodedToken) {
logger.log('User is not authenticated');
res.status(403).send();
return end();
return;
}


Expand Down Expand Up @@ -112,6 +111,6 @@ export const selectBestRTDBInstance = functions.region(
res.status(500).send("Unknown error");
}

return end();
return;

});
20 changes: 17 additions & 3 deletions packages/functions/src/load-balancing/syncStatusJob.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import * as functions from 'firebase-functions';
import * as admin from "firebase-admin";
import {FirebaseCollection, RTDBInstance, RTDBPaths, Status} from "@pipeline/common";
import {PROJECT_ID} from "../utils/rtdb";
import {FirebaseCollection, RTDBPaths, Status} from "@pipeline/common";
import Timestamp = admin.firestore.Timestamp;
import {end, RTDB_LOCATION} from "../utils/general";
import {RTDB_LOCATION} from "../utils/general";
import {moveGameFromRTDBToFirestore} from "./moveGameFromRTDBToFirestore";
import * as _ from 'lodash';

Expand Down Expand Up @@ -71,3 +70,18 @@ const syncStatusJob = async () => {
}
}
};

export const scheduledSyncStatusJob = functions.region(
'europe-west1'
).runWith({
memory: '2GB',
timeoutSeconds: 540,
}).pubsub.schedule(`every 30 minutes`)
.timeZone('Europe/Rome')
.onRun(async () => {
try {
await syncStatusJob();
} catch (e) {
logger.error(e);
}
});
3 changes: 2 additions & 1 deletion packages/functions/src/utils/db.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as admin from 'firebase-admin';
import {Transaction} from '@google-cloud/firestore';

type Transaction = admin.firestore.Transaction;

const wait = (ms: number) => { return new Promise(resolve => setTimeout(resolve, ms))};

Expand Down
6 changes: 0 additions & 6 deletions packages/functions/src/utils/general.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
export const RTDB_THRESHOLD = 100; // TODO compute carefully
export const RTDB_LOCATION = 'europe-west1';

export const end = () => {
return new Promise<void>(resolve => {
resolve();
});
};

0 comments on commit c9e8133

Please sign in to comment.