95 lines
3.6 KiB
TypeScript
95 lines
3.6 KiB
TypeScript
import type { Logger } from '@core/shared/application';
|
|
import type { EnsureInitialData } from '../../../../../adapters/bootstrap/EnsureInitialData';
|
|
import { SeedRacingData, type RacingSeedDependencies } from '../../../../../adapters/bootstrap/SeedRacingData';
|
|
import { Inject, Module, OnModuleInit } from '@nestjs/common';
|
|
import { getApiPersistence, getEnableBootstrap, getForceReseed } from '../../env';
|
|
import { RacingPersistenceModule } from '../../persistence/racing/RacingPersistenceModule';
|
|
import { SocialPersistenceModule } from '../../persistence/social/SocialPersistenceModule';
|
|
import { AchievementPersistenceModule } from '../../persistence/achievement/AchievementPersistenceModule';
|
|
import { IdentityPersistenceModule } from '../../persistence/identity/IdentityPersistenceModule';
|
|
import { BootstrapProviders, ENSURE_INITIAL_DATA_TOKEN } from './BootstrapProviders';
|
|
|
|
@Module({
|
|
imports: [RacingPersistenceModule, SocialPersistenceModule, AchievementPersistenceModule, IdentityPersistenceModule],
|
|
providers: BootstrapProviders,
|
|
})
|
|
export class BootstrapModule implements OnModuleInit {
|
|
constructor(
|
|
@Inject(ENSURE_INITIAL_DATA_TOKEN) private readonly ensureInitialData: EnsureInitialData,
|
|
@Inject('Logger') private readonly logger: Logger,
|
|
@Inject('RacingSeedDependencies') private readonly seedDeps: RacingSeedDependencies,
|
|
) {}
|
|
|
|
async onModuleInit() {
|
|
console.log('[Bootstrap] Initializing application data...');
|
|
try {
|
|
if (!getEnableBootstrap()) {
|
|
this.logger.info('[Bootstrap] Bootstrap disabled via GRIDPILOT_API_BOOTSTRAP; skipping initialization');
|
|
return;
|
|
}
|
|
|
|
await this.ensureInitialData.execute();
|
|
|
|
if (await this.shouldSeedRacingData()) {
|
|
await new SeedRacingData(this.logger, this.seedDeps).execute();
|
|
}
|
|
|
|
console.log('[Bootstrap] Application data initialized successfully');
|
|
} catch (error) {
|
|
console.error('[Bootstrap] Failed to initialize application data:', error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
private async shouldSeedRacingData(): Promise<boolean> {
|
|
const persistence = getApiPersistence();
|
|
|
|
if (persistence === 'inmemory') return true;
|
|
if (persistence !== 'postgres') return false;
|
|
if (process.env.NODE_ENV === 'production') return false;
|
|
|
|
// Check for force reseed flag
|
|
const forceReseed = getForceReseed();
|
|
if (forceReseed) {
|
|
this.logger.info('[Bootstrap] Force reseed enabled via GRIDPILOT_API_FORCE_RESEED');
|
|
return true;
|
|
}
|
|
|
|
// Check if database is empty
|
|
const isEmpty = await this.isRacingDatabaseEmpty();
|
|
if (!isEmpty) {
|
|
// Database has data, check if it needs reseeding
|
|
return await this.needsReseed();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private async isRacingDatabaseEmpty(): Promise<boolean> {
|
|
const count = await this.seedDeps.leagueRepository.countAll?.();
|
|
if (typeof count === 'number') return count === 0;
|
|
|
|
const leagues = await this.seedDeps.leagueRepository.findAll();
|
|
return leagues.length === 0;
|
|
}
|
|
|
|
private async needsReseed(): Promise<boolean> {
|
|
// Check if driver count is less than expected (150)
|
|
// This indicates old seed data that needs updating
|
|
try {
|
|
const drivers = await this.seedDeps.driverRepository.findAll();
|
|
const driverCount = drivers.length;
|
|
|
|
// If we have fewer than 150 drivers, we need to reseed
|
|
if (driverCount < 150) {
|
|
this.logger.info(`[Bootstrap] Found ${driverCount} drivers (expected 150), triggering reseed`);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
} catch (error) {
|
|
this.logger.warn('[Bootstrap] Error checking driver count for reseed:', error);
|
|
return false;
|
|
}
|
|
}
|
|
} |