Skip to content

Commit

Permalink
Add additional check if the game the game server references is running
Browse files Browse the repository at this point in the history
  • Loading branch information
NetroScript committed Nov 2, 2021
1 parent b82b557 commit 751ceab
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 9 deletions.
32 changes: 31 additions & 1 deletion src/game-servers/services/game-servers.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
MongooseModule,
} from '@nestjs/mongoose';
import { GamesService } from '@/games/services/games.service';
import { GameState } from '@/games/models/game-state';

jest.mock('@/games/services/games.service');

Expand Down Expand Up @@ -200,7 +201,14 @@ describe('GameServersService', () => {
describe('#findFreeGameServer()', () => {
describe('when the server is online but taken', () => {
beforeEach(async () => {
testGameServer.game = new ObjectId();
const game1 = await gameModel.create({
number: 2,
map: 'cp_badlands',
slots: [],
state: GameState.started
});

testGameServer.game = new ObjectId(game1.id);
testGameServer.isOnline = true;
await testGameServer.save();
});
Expand All @@ -212,6 +220,28 @@ describe('GameServersService', () => {
});
});

describe('when the server has a game, but that game ended', () => {
beforeEach(async () => {

const game2 = await gameModel.create({
number: 2,
map: 'cp_badlands',
slots: [],
state: GameState.ended
});

testGameServer.game = new ObjectId(game2.id);
testGameServer.isOnline = true;
await testGameServer.save();
});

it('should return this game server', async () => {
expect((await service.findFreeGameServer()).id).toEqual(
testGameServer.id,
);
});
});

describe('when the server is free but offline', () => {
beforeEach(async () => {
testGameServer.isOnline = false;
Expand Down
44 changes: 36 additions & 8 deletions src/game-servers/services/game-servers.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { InjectModel } from '@nestjs/mongoose';
import { Model, Error, Types } from 'mongoose';
import { GamesService } from '@/games/services/games.service';
import { filter } from 'rxjs/operators';
import { GameState } from '@/games/models/game-state';

interface HeartbeatParams {
name: string;
Expand Down Expand Up @@ -155,14 +156,41 @@ export class GameServersService implements OnModuleInit {
}

async findFreeGameServer(): Promise<GameServer> {
return plainToClass(
GameServer,
await this.gameServerModel
.findOne({ isOnline: true, game: { $exists: false } })
.orFail()
.lean()
.exec(),
);
let availableGameServer: GameServer = null;
// Fetch all game servers to determine which ones are free
const availableGameServers = await this.getAllGameServers();

// Iterate every server and confirm if the stored game is actually running
// We iterate from last to first to return the first available server of
// all available server instead of the last
for (let i = availableGameServers.length - 1; i > -1; i--) {
const gameServer = availableGameServers[i];
if (gameServer.game !== undefined) {
const game = await this.gamesService.getById(gameServer.game);

if (
game.state === GameState.ended ||
game.state === GameState.interrupted
) {
this.logger.debug(
`game server ${gameServer.id} (${gameServer.name}) had the wrong state of a game`,
);

// Release the gameserver since the game it has stored actually finished
await this.releaseServer(gameServer.id);

availableGameServer = gameServer;
}
} else {
availableGameServer = gameServer;
}
}

if (availableGameServer !== null) {
return availableGameServer;
} else {
throw new Error.DocumentNotFoundError("No free servers available.");
}
}

async assignFreeGameServer(gameId: string): Promise<GameServer> {
Expand Down

0 comments on commit 751ceab

Please sign in to comment.