Files
gridpilot.gg/adapters/racing/persistence/inmemory/InMemoryLeagueMembershipRepository.ts
2025-12-15 18:49:10 +01:00

179 lines
7.1 KiB
TypeScript

/**
* Infrastructure Adapter: InMemoryLeagueMembershipRepository
*
* In-memory implementation of ILeagueMembershipRepository.
* Stores memberships and join requests in maps keyed by league.
*/
import type {
LeagueMembership,
JoinRequest,
} from '@gridpilot/racing/domain/entities/LeagueMembership';
import type { ILeagueMembershipRepository } from '@gridpilot/racing/domain/repositories/ILeagueMembershipRepository';
import type { ILogger } from '@gridpilot/shared/logging/ILogger';
export class InMemoryLeagueMembershipRepository implements ILeagueMembershipRepository {
private membershipsByLeague: Map<string, LeagueMembership[]>;
private joinRequestsByLeague: Map<string, JoinRequest[]>;
private readonly logger: ILogger;
constructor(logger: ILogger, seedMemberships?: LeagueMembership[], seedJoinRequests?: JoinRequest[]) {
this.logger = logger;
this.logger.info('InMemoryLeagueMembershipRepository initialized.');
this.membershipsByLeague = new Map();
this.joinRequestsByLeague = new Map();
if (seedMemberships) {
seedMemberships.forEach((membership) => {
const list = this.membershipsByLeague.get(membership.leagueId) ?? [];
list.push(membership);
this.membershipsByLeague.set(membership.leagueId, list);
this.logger.debug(`Seeded membership for league ${membership.leagueId}, driver ${membership.driverId}.`);
});
}
if (seedJoinRequests) {
seedJoinRequests.forEach((request) => {
const list = this.joinRequestsByLeague.get(request.leagueId) ?? [];
list.push(request);
this.joinRequestsByLeague.set(request.leagueId, list);
this.logger.debug(`Seeded join request for league ${request.leagueId}, driver ${request.driverId}.`);
});
}
}
async getMembership(leagueId: string, driverId: string): Promise<LeagueMembership | null> {
this.logger.debug(`Getting membership for league: ${leagueId}, driver: ${driverId}`);
try {
const list = this.membershipsByLeague.get(leagueId);
if (!list) {
this.logger.warn(`No membership list found for league: ${leagueId}.`);
return null;
}
const membership = list.find((m) => m.driverId === driverId) ?? null;
if (membership) {
this.logger.info(`Found membership for league: ${leagueId}, driver: ${driverId}.`);
} else {
this.logger.warn(`Membership not found for league: ${leagueId}, driver: ${driverId}.`);
}
return membership;
} catch (error) {
this.logger.error(`Error getting membership for league ${leagueId}, driver ${driverId}:`, error);
throw error;
}
}
async getLeagueMembers(leagueId: string): Promise<LeagueMembership[]> {
this.logger.debug(`Getting league members for league: ${leagueId}`);
try {
const members = [...(this.membershipsByLeague.get(leagueId) ?? [])];
this.logger.info(`Found ${members.length} members for league: ${leagueId}.`);
return members;
} catch (error) {
this.logger.error(`Error getting league members for league ${leagueId}:`, error);
throw error;
}
}
async getJoinRequests(leagueId: string): Promise<JoinRequest[]> {
this.logger.debug(`Getting join requests for league: ${leagueId}`);
try {
const requests = [...(this.joinRequestsByLeague.get(leagueId) ?? [])];
this.logger.info(`Found ${requests.length} join requests for league: ${leagueId}.`);
return requests;
} catch (error) {
this.logger.error(`Error getting join requests for league ${leagueId}:`, error);
throw error;
}
}
async saveMembership(membership: LeagueMembership): Promise<LeagueMembership> {
this.logger.debug(`Saving membership for league: ${membership.leagueId}, driver: ${membership.driverId}`);
try {
const list = this.membershipsByLeague.get(membership.leagueId) ?? [];
const existingIndex = list.findIndex(
(m) => m.leagueId === membership.leagueId && m.driverId === membership.driverId,
);
if (existingIndex >= 0) {
list[existingIndex] = membership;
this.logger.info(`Updated existing membership for league: ${membership.leagueId}, driver: ${membership.driverId}.`);
} else {
list.push(membership);
this.logger.info(`Created new membership for league: ${membership.leagueId}, driver: ${membership.driverId}.`);
}
this.membershipsByLeague.set(membership.leagueId, list);
return membership;
} catch (error) {
this.logger.error(`Error saving membership for league ${membership.leagueId}, driver ${membership.driverId}:`, error);
throw error;
}
}
async removeMembership(leagueId: string, driverId: string): Promise<void> {
this.logger.debug(`Removing membership for league: ${leagueId}, driver: ${driverId}`);
try {
const list = this.membershipsByLeague.get(leagueId);
if (!list) {
this.logger.warn(`No membership list found for league: ${leagueId}. Cannot remove.`);
return;
}
const next = list.filter((m) => m.driverId !== driverId);
if (next.length < list.length) {
this.membershipsByLeague.set(leagueId, next);
this.logger.info(`Removed membership for league: ${leagueId}, driver: ${driverId}.`);
} else {
this.logger.warn(`Membership not found for league: ${leagueId}, driver: ${driverId}. Cannot remove.`);
}
} catch (error) {
this.logger.error(`Error removing membership for league ${leagueId}, driver ${driverId}:`, error);
throw error;
}
}
async saveJoinRequest(request: JoinRequest): Promise<JoinRequest> {
this.logger.debug(`Saving join request for league: ${request.leagueId}, driver: ${request.driverId}, id: ${request.id}`);
try {
const list = this.joinRequestsByLeague.get(request.leagueId) ?? [];
const existingIndex = list.findIndex((r) => r.id === request.id);
if (existingIndex >= 0) {
list[existingIndex] = request;
this.logger.info(`Updated existing join request: ${request.id}.`);
} else {
list.push(request);
this.logger.info(`Created new join request: ${request.id}.`);
}
this.joinRequestsByLeague.set(request.leagueId, list);
return request;
} catch (error) {
this.logger.error(`Error saving join request ${request.id}:`, error);
throw error;
}
}
async removeJoinRequest(requestId: string): Promise<void> {
this.logger.debug(`Removing join request with ID: ${requestId}`);
try {
let removed = false;
for (const [leagueId, requests] of this.joinRequestsByLeague.entries()) {
const next = requests.filter((r) => r.id !== requestId);
if (next.length !== requests.length) {
this.joinRequestsByLeague.set(leagueId, next);
removed = true;
this.logger.info(`Removed join request ${requestId} from league ${leagueId}.`);
break;
}
}
if (!removed) {
this.logger.warn(`Join request with ID ${requestId} not found for removal.`);
}
} catch (error) {
this.logger.error(`Error removing join request ${requestId}:`, error);
throw error;
}
}
}