Skip to content

Commit

Permalink
Merge pull request #1856 from gettakaro/fix-issue-with-stale-server-c…
Browse files Browse the repository at this point in the history
…onnection-info
  • Loading branch information
niekcandaele authored Jan 4, 2025
2 parents 0815107 + 959e32c commit fdf6473
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 141 deletions.
23 changes: 22 additions & 1 deletion packages/app-api/src/lib/socketServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { Server, Socket } from 'socket.io';
import { IncomingMessage, Server as HttpServer, ServerResponse } from 'http';
import { config } from '../config.js';
import { ctx, errors, logger } from '@takaro/util';
import { EventPayload, EventTypes } from '@takaro/modules';
import { EventPayload, EventTypes, HookEvents } from '@takaro/modules';
import { instrument } from '@socket.io/admin-ui';
import { AuthenticatedRequest, AuthService } from '../service/AuthService.js';
import { NextFunction, Response } from 'express';
import { createAdapter } from '@socket.io/redis-adapter';
import { Redis } from '@takaro/db';
import { EventOutputDTO } from '../service/EventService.js';
import { GameServerService } from '../service/GameServerService.js';

interface ServerToClientEvents {
gameEvent: (gameserverId: string, type: EventTypes, data: EventPayload) => void;
Expand All @@ -22,6 +23,7 @@ interface ClientToServerEvents {

interface InterServerEvents {
ping: () => void;
event: (event: EventOutputDTO) => void;
}

interface SocketData {
Expand Down Expand Up @@ -76,6 +78,22 @@ class SocketServer {
});
});

this.io.on('event', (event: EventOutputDTO) => {
const eventsToRefreshServerCache: EventTypes[] = [
HookEvents.GAMESERVER_CREATED,
HookEvents.GAMESERVER_DELETED,
HookEvents.GAMESERVER_UPDATED,
];

if (eventsToRefreshServerCache.includes(event.eventName)) {
this.log.info(
`Received event from other node that indicates we need to refresh cache for gameserver ${event.gameserverId}`,
);
const gameserverService = new GameServerService(event.domain);
gameserverService.refreshGameInstance(event.gameserverId);
}
});

this.log.info('Socket server started');
}

Expand All @@ -92,6 +110,9 @@ class SocketServer {
data: Parameters<ServerToClientEvents[keyof ServerToClientEvents]> = [],
) {
this.io.to(domainId).emit(event, ...data);
if (event === 'event') {
this.io.serverSideEmit(event, data as unknown as EventOutputDTO);
}
}

private async routerMiddleware(
Expand Down
37 changes: 34 additions & 3 deletions packages/app-api/src/service/GameServerService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ import {
EventChatMessage,
TakaroEventModuleInstalled,
TakaroEventModuleUninstalled,
TakaroEventGameserverCreated,
TakaroEventGameserverUpdated,
TakaroEventGameserverDeleted,
ChatChannel,
} from '@takaro/modules';
import { ITakaroQuery } from '@takaro/db';
Expand Down Expand Up @@ -156,6 +159,10 @@ export class GameServerService extends TakaroService<
return new GameServerRepo(this.domainId);
}

public refreshGameInstance(id: string) {
gameClassCache.delete(id);
}

find(filters: ITakaroQuery<GameServerOutputDTO>): Promise<PaginatedOutput<GameServerOutputDTO>> {
return this.repo.find(filters);
}
Expand All @@ -168,6 +175,14 @@ export class GameServerService extends TakaroService<
const isReachable = await this.testReachability(undefined, JSON.parse(item.connectionInfo), item.type);
const createdServer = await this.repo.create(item);

const eventsService = new EventService(this.domainId);
await eventsService.create(
new EventCreateDTO({
eventName: EVENT_TYPES.GAMESERVER_CREATED,
gameserverId: createdServer.id,
meta: new TakaroEventGameserverCreated(),
}),
);
await queueService.queues.connector.queue.add({
domainId: this.domainId,
gameServerId: createdServer.id,
Expand All @@ -192,7 +207,7 @@ export class GameServerService extends TakaroService<
});
await Promise.all(installedModules.map((mod) => this.uninstallModule(id, mod.moduleId)));

gameClassCache.delete(id);
this.refreshGameInstance(id);

const gateway = new Pushgateway(config.get('metrics.pushgatewayUrl'), {});
gateway.delete({ jobName: 'worker', groupings: { gameserver: id } });
Expand All @@ -204,6 +219,14 @@ export class GameServerService extends TakaroService<
time: new Date().toISOString(),
});
await this.repo.delete(id);
const eventsService = new EventService(this.domainId);
await eventsService.create(
new EventCreateDTO({
eventName: EVENT_TYPES.GAMESERVER_DELETED,
gameserverId: id,
meta: new TakaroEventGameserverDeleted(),
}),
);
await queueService.queues.system.queue.add(
{
domainId: this.domainId,
Expand All @@ -216,7 +239,15 @@ export class GameServerService extends TakaroService<

async update(id: string, item: GameServerUpdateDTO): Promise<GameServerOutputDTO> {
const updatedServer = await this.repo.update(id, item);
gameClassCache.delete(id);
this.refreshGameInstance(id);
const eventsService = new EventService(this.domainId);
await eventsService.create(
new EventCreateDTO({
eventName: EVENT_TYPES.GAMESERVER_UPDATED,
gameserverId: id,
meta: new TakaroEventGameserverUpdated(),
}),
);
await queueService.queues.connector.queue.add({
domainId: this.domainId,
gameServerId: id,
Expand Down Expand Up @@ -252,7 +283,7 @@ export class GameServerService extends TakaroService<

// When a user is trying to fix their connection info, it's important we don't cache stale/wrong connection info
if (!reachability.connectable) {
gameClassCache.delete(id);
this.refreshGameInstance(id);
}

return reachability;
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.10.0
7.8.0
Loading

0 comments on commit fdf6473

Please sign in to comment.