Files
gridpilot.gg/tests/integration/database/concurrency/concurrency.integration.test.ts
Marc Mintel a0f41f242f
Some checks failed
CI / lint-typecheck (pull_request) Failing after 4m51s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped
integration tests
2026-01-23 00:46:34 +01:00

107 lines
3.2 KiB
TypeScript

import { describe, it, expect, beforeEach } from 'vitest';
import { DatabaseTestContext, DriverData } from '../DatabaseTestContext';
describe('Database Constraints - Concurrent Operations', () => {
let context: DatabaseTestContext;
beforeEach(() => {
context = DatabaseTestContext.create();
});
it('should handle concurrent team creation attempts safely', async () => {
// Given: Multiple drivers exist
const drivers: DriverData[] = await Promise.all(
Array(5).fill(null).map((_, i) => {
const driver = {
id: `driver-${i}`,
iracingId: `iracing-${i}`,
name: `Test Driver ${i}`,
country: 'US',
joinedAt: new Date(),
};
return context.driverRepository.create(driver);
})
);
// When: Multiple concurrent attempts to create teams with same name
// We use a small delay to ensure they don't all get the same timestamp
// if the implementation uses Date.now() for IDs
const concurrentRequests = drivers.map(async (driver, i) => {
await new Promise(resolve => setTimeout(resolve, i * 10));
return context.createTeamUseCase.execute({
name: 'Concurrent Team',
tag: 'CT', // Same tag for all to trigger duplicate error
description: 'Concurrent creation',
ownerId: driver.id,
leagues: [],
});
});
const results = await Promise.all(concurrentRequests);
// Then: Exactly one should succeed, others should fail
const successes = results.filter(r => r.isOk());
const failures = results.filter(r => r.isErr());
// Note: In-memory implementation is synchronous, so concurrent requests
// actually run sequentially in this test environment.
expect(successes.length).toBe(1);
expect(failures.length).toBe(4);
// All failures should be duplicate errors
failures.forEach(result => {
if (result.isErr()) {
expect(result.error.code).toBe('DUPLICATE_TEAM');
}
});
});
it('should handle concurrent join requests safely', async () => {
// Given: A driver and team exist
const driver: DriverData = {
id: 'driver-123',
iracingId: '12345',
name: 'Test Driver',
country: 'US',
joinedAt: new Date(),
};
await context.driverRepository.create(driver);
const team = {
id: 'team-123',
name: 'Test Team',
tag: 'TT',
description: 'A test team',
ownerId: 'other-driver',
leagues: [],
isRecruiting: false,
createdAt: new Date(),
};
await context.teamRepository.create(team);
// When: Multiple concurrent join attempts
const concurrentJoins = Array(3).fill(null).map(() =>
context.joinTeamUseCase.execute({
teamId: team.id,
driverId: driver.id,
})
);
const results = await Promise.all(concurrentJoins);
// Then: Exactly one should succeed
const successes = results.filter(r => r.isOk());
const failures = results.filter(r => r.isErr());
expect(successes.length).toBe(1);
expect(failures.length).toBe(2);
// All failures should be already member errors
failures.forEach(result => {
if (result.isErr()) {
expect(result.error.code).toBe('ALREADY_MEMBER');
}
});
});
});