Skip to content

Commit

Permalink
feat(discord): notify when no game servers are available (#2811)
Browse files Browse the repository at this point in the history
  • Loading branch information
garrappachc authored Mar 29, 2024
1 parent e8dc7f8 commit e0b666d
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/events/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,10 @@ export class Events {
newValue: unknown;
}>();

readonly errorNoFreeGameServerAvailable = new Subject<{
gameId: GameId;
}>();

constructor() {
for (const eventName in this) {
const prop = this[eventName];
Expand Down
25 changes: 25 additions & 0 deletions src/games/services/game-server-assigner.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { PlayersService } from '@/players/services/players.service';
// eslint-disable-next-line jest/no-mocks-import
import { PlayersService as MockedPlayersService } from '@/players/services/__mocks__/players.service';
import { Player, playerSchema } from '@/players/models/player';
import { NoFreeGameServerAvailableError } from '@/game-servers/errors/no-free-game-server-available.error';

jest.mock('./games.service');
jest.mock('@/game-servers/services/game-servers.service');
Expand Down Expand Up @@ -174,6 +175,30 @@ describe('GameServerAssignerService', () => {
).rejects.toThrow(CannotAssignGameServerError);
});
});

describe('when no free gameservers are available', () => {
let emitted: boolean;

beforeEach(() => {
gameServersService.assignGameServer.mockRejectedValue(
new NoFreeGameServerAvailableError(),
);
events.errorNoFreeGameServerAvailable.subscribe(() => {
emitted = true;
});
emitted = false;
});

it('should emit event', async () => {
try {
await service.assignGameServer(game._id);
} catch (error) {
// empty
}

expect(emitted).toBe(true);
});
});
});

describe('#handleOrphanedGames()', () => {
Expand Down
6 changes: 6 additions & 0 deletions src/games/services/game-server-assigner.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { Game } from '../models/game';
import { GamesService } from './games.service';
import { PlayerId } from '@/players/types/player-id';
import { PlayersService } from '@/players/services/players.service';
import { NoFreeGameServerAvailableError } from '@/game-servers/errors/no-free-game-server-available.error';

@Injectable()
export class GameServerAssignerService implements OnModuleInit {
Expand Down Expand Up @@ -90,6 +91,11 @@ export class GameServerAssignerService implements OnModuleInit {
return game;
} catch (error) {
assertIsError(error);

if (error instanceof NoFreeGameServerAvailableError) {
this.events.errorNoFreeGameServerAvailable.next({ gameId });
}

throw new CannotAssignGameServerError(game, error.message);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { EmbedBuilder } from 'discord.js';

interface NoFreeGameServersAvailableOptions {
game: {
number: string;
url: string;
};
client: {
name: string;
iconUrl: string;
};
}

export const noFreeGameServersAvailable = (
options: NoFreeGameServersAvailableOptions,
): EmbedBuilder => {
return new EmbedBuilder()
.setTitle('No free game servers available')
.setColor('#ff0000')
.setDescription(
`Game number: **[${options.game.number}](${options.game.url})**`,
)
.setFooter({
text: options.client.name,
iconURL: options.client.iconUrl,
})
.setTimestamp();
};
21 changes: 21 additions & 0 deletions src/plugins/discord/services/admin-notifications.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,4 +440,25 @@ describe('AdminNotificationsService', () => {
});
}));
});

describe('when no free game servers are available', () => {
let game: Game;
beforeEach(async () => {
game = await gamesService._createOne();
});

it('should send a notification to admins channel', () =>
new Promise<void>((resolve) => {
sentMessages.subscribe((message) => {
expect(message.embeds[0].toJSON().title).toEqual(
'No free game servers available',
);
resolve();
});

events.errorNoFreeGameServerAvailable.next({
gameId: game._id,
});
}));
});
});
19 changes: 19 additions & 0 deletions src/plugins/discord/services/admin-notifications.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { GamesService } from '@/games/services/games.service';
import { substituteRequested } from '../notifications/substitute-requested';
import { version } from '../../../../package.json';
import { DISCORD_CLIENT } from '../discord-client.token';
import { noFreeGameServersAvailable } from '../notifications/no-free-game-servers-available';

@Injectable()
export class AdminNotificationsService implements OnModuleInit {
Expand Down Expand Up @@ -380,6 +381,24 @@ export class AdminNotificationsService implements OnModuleInit {
),
)
.subscribe((embed) => this.notifications.next(embed));

this.events.errorNoFreeGameServerAvailable
.pipe(
concatMap(({ gameId }) => from(this.gamesService.getById(gameId))),
map((game) =>
noFreeGameServersAvailable({
game: {
number: `${game.number}`,
url: `${this.environment.clientUrl}/game/${game.id}`,
},
client: {
name: new URL(this.environment.clientUrl).hostname,
iconUrl: `${this.environment.clientUrl}/${iconUrlPath}`,
},
}),
),
)
.subscribe((embed) => this.notifications.next(embed));
}

private async getAdminChannels() {
Expand Down

0 comments on commit e0b666d

Please sign in to comment.