Files
gridpilot.gg/adapters/racing/persistence/inmemory/InMemoryTeamMembershipRepository.ts
2025-12-16 13:13:03 +01:00

233 lines
9.4 KiB
TypeScript

/**
* Infrastructure Adapter: InMemoryTeamMembershipRepository
*
* In-memory implementation of ITeamMembershipRepository.
* Stores memberships and join requests in Map structures.
*/
import type {
TeamMembership,
TeamJoinRequest,
} from '@core/racing/domain/types/TeamMembership';
import type { ITeamMembershipRepository } from '@core/racing/domain/repositories/ITeamMembershipRepository';
import type { Logger } from '@core/shared/application';
export class InMemoryTeamMembershipRepository implements ITeamMembershipRepository {
private membershipsByTeam: Map<string, TeamMembership[]>;
private joinRequestsByTeam: Map<string, TeamJoinRequest[]>;
private readonly logger: Logger;
constructor(logger: Logger, seedMemberships?: TeamMembership[], seedJoinRequests?: TeamJoinRequest[]) {
this.logger = logger;
this.logger.info('InMemoryTeamMembershipRepository initialized.');
this.membershipsByTeam = new Map();
this.joinRequestsByTeam = new Map();
if (seedMemberships) {
seedMemberships.forEach((membership) => {
const list = this.membershipsByTeam.get(membership.teamId) ?? [];
list.push(membership);
this.membershipsByTeam.set(membership.teamId, list);
this.logger.debug(`Seeded membership for team ${membership.teamId}, driver ${membership.driverId}.`);
});
}
if (seedJoinRequests) {
seedJoinRequests.forEach((request) => {
const list = this.joinRequestsByTeam.get(request.teamId) ?? [];
list.push(request);
this.joinRequestsByTeam.set(request.teamId, list);
this.logger.debug(`Seeded join request for team ${request.teamId}, driver ${request.driverId}.`);
});
}
}
private getMembershipList(teamId: string): TeamMembership[] {
let list = this.membershipsByTeam.get(teamId);
if (!list) {
list = [];
this.membershipsByTeam.set(teamId, list);
this.logger.debug(`Created new membership list for team: ${teamId}`);
}
return list;
}
private getJoinRequestList(teamId: string): TeamJoinRequest[] {
let list = this.joinRequestsByTeam.get(teamId);
if (!list) {
list = [];
this.joinRequestsByTeam.set(teamId, list);
this.logger.debug(`Created new join request list for team: ${teamId}`);
}
return list;
}
async getMembership(teamId: string, driverId: string): Promise<TeamMembership | null> {
this.logger.debug(`[getMembership] Entry - teamId: ${teamId}, driverId: ${driverId}`);
try {
const list = this.membershipsByTeam.get(teamId);
if (!list) {
this.logger.warn(`[getMembership] No membership list found for team: ${teamId}. Returning null.`);
return null;
}
const membership = list.find((m) => m.driverId === driverId) ?? null;
if (membership) {
this.logger.info(`[getMembership] Success - found membership for team: ${teamId}, driver: ${driverId}.`);
} else {
this.logger.info(`[getMembership] Not found - membership for team: ${teamId}, driver: ${driverId}.`);
}
return membership;
} catch (error) {
this.logger.error(`[getMembership] Error getting membership for team ${teamId}, driver ${driverId}:`, error);
throw error;
}
}
async getActiveMembershipForDriver(driverId: string): Promise<TeamMembership | null> {
this.logger.debug(`[getActiveMembershipForDriver] Entry - driverId: ${driverId}`);
try {
for (const list of this.membershipsByTeam.values()) {
const membership = list.find(
(m) => m.driverId === driverId && m.status === 'active',
);
if (membership) {
this.logger.info(`[getActiveMembershipForDriver] Success - found active membership for driver: ${driverId}, team: ${membership.teamId}.`);
return membership;
}
}
this.logger.info(`[getActiveMembershipForDriver] Not found - no active membership for driver: ${driverId}.`);
return null;
} catch (error) {
this.logger.error(`[getActiveMembershipForDriver] Error getting active membership for driver ${driverId}:`, error);
throw error;
}
}
async getTeamMembers(teamId: string): Promise<TeamMembership[]> {
this.logger.debug(`[getTeamMembers] Entry - teamId: ${teamId}`);
try {
const members = [...(this.membershipsByTeam.get(teamId) ?? [])];
this.logger.info(`[getTeamMembers] Success - found ${members.length} members for team: ${teamId}.`);
return members;
} catch (error) {
this.logger.error(`[getTeamMembers] Error getting team members for team ${teamId}:`, error);
throw error;
}
}
async countByTeamId(teamId: string): Promise<number> {
this.logger.debug(`[countByTeamId] Entry - teamId: ${teamId}`);
try {
const list = this.membershipsByTeam.get(teamId) ?? [];
const count = list.filter((m) => m.status === 'active').length;
this.logger.info(`[countByTeamId] Success - counted ${count} active members for team: ${teamId}.`);
return count;
} catch (error) {
this.logger.error(`[countByTeamId] Error counting members for team ${teamId}:`, error);
throw error;
}
}
async saveMembership(membership: TeamMembership): Promise<TeamMembership> {
this.logger.debug(`[saveMembership] Entry - teamId: ${membership.teamId}, driverId: ${membership.driverId}`);
try {
const list = this.getMembershipList(membership.teamId);
const existingIndex = list.findIndex(
(m) => m.teamId === membership.teamId && m.driverId === membership.driverId,
);
if (existingIndex >= 0) {
list[existingIndex] = membership;
this.logger.info(`[saveMembership] Success - updated existing membership for team: ${membership.teamId}, driver: ${membership.driverId}.`);
} else {
list.push(membership);
this.logger.info(`[saveMembership] Success - created new membership for team: ${membership.teamId}, driver: ${membership.driverId}.`);
}
this.membershipsByTeam.set(membership.teamId, list);
return membership;
} catch (error) {
this.logger.error(`[saveMembership] Error saving membership for team ${membership.teamId}, driver ${membership.driverId}:`, error);
throw error;
}
}
async removeMembership(teamId: string, driverId: string): Promise<void> {
this.logger.debug(`[removeMembership] Entry - teamId: ${teamId}, driverId: ${driverId}`);
try {
const list = this.membershipsByTeam.get(teamId);
if (!list) {
this.logger.warn(`[removeMembership] No membership list found for team: ${teamId}. Cannot remove.`);
return;
}
const index = list.findIndex((m) => m.driverId === driverId);
if (index >= 0) {
list.splice(index, 1);
this.membershipsByTeam.set(teamId, list);
this.logger.info(`[removeMembership] Success - removed membership for team: ${teamId}, driver: ${driverId}.`);
} else {
this.logger.info(`[removeMembership] Not found - membership for team: ${teamId}, driver: ${driverId}. Cannot remove.`);
}
} catch (error) {
this.logger.error(`[removeMembership] Error removing membership for team ${teamId}, driver ${driverId}:`, error);
throw error;
}
}
async getJoinRequests(teamId: string): Promise<TeamJoinRequest[]> {
this.logger.debug(`[getJoinRequests] Entry - teamId: ${teamId}`);
try {
const requests = [...(this.joinRequestsByTeam.get(teamId) ?? [])];
this.logger.info(`[getJoinRequests] Success - found ${requests.length} join requests for team: ${teamId}.`);
return requests;
} catch (error) {
this.logger.error(`[getJoinRequests] Error getting join requests for team ${teamId}:`, error);
throw error;
}
}
async saveJoinRequest(request: TeamJoinRequest): Promise<TeamJoinRequest> {
this.logger.debug(`[saveJoinRequest] Entry - teamId: ${request.teamId}, driverId: ${request.driverId}, id: ${request.id}`);
try {
const list = this.getJoinRequestList(request.teamId);
const existingIndex = list.findIndex((r) => r.id === request.id);
if (existingIndex >= 0) {
list[existingIndex] = request;
this.logger.info(`[saveJoinRequest] Success - updated existing join request: ${request.id}.`);
} else {
list.push(request);
this.logger.info(`[saveJoinRequest] Success - created new join request: ${request.id}.`);
}
this.joinRequestsByTeam.set(request.teamId, list);
return request;
} catch (error) {
this.logger.error(`[saveJoinRequest] Error saving join request ${request.id}:`, error);
throw error;
}
}
async removeJoinRequest(requestId: string): Promise<void> {
this.logger.debug(`[removeJoinRequest] Entry - requestId: ${requestId}`);
try {
let removed = false;
for (const [teamId, list] of this.joinRequestsByTeam.entries()) {
const index = list.findIndex((r) => r.id === requestId);
if (index >= 0) {
list.splice(index, 1);
this.joinRequestsByTeam.set(teamId, list);
removed = true;
this.logger.info(`[removeJoinRequest] Success - removed join request ${requestId} from team ${teamId}.`);
break;
}
}
if (!removed) {
this.logger.warn(`[removeJoinRequest] Not found - join request with ID ${requestId} not found for removal.`);
}
} catch (error) {
this.logger.error(`[removeJoinRequest] Error removing join request ${requestId}:`, error);
throw error;
}
}
}