Общий запуск наполнителей в Nest
Опорные данные лежат в нескольких таблицах, и каждый наполнитель знает только свою сущность. Запускать их вручную в разном порядке легко перепутать при каждом новом окружении.
Общий класс координации получает оба наполнителя через внедрение и вызывает их операции одну за другой. Модуль темы при старте обращается только к координатору, а порядок заполнения таблиц задаётся в одном месте.
Покажем на примере постов:
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
}
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Tag {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
}
Каждый наполнитель заполнит свою таблицу:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Post } from '../post.entity.js';
@Injectable()
export class PostSeeder {
postRepository: Repository<Post>;
constructor(
@InjectRepository(Post) postRepository: Repository<Post>,
) {
this.postRepository = postRepository;
}
async seed() {
await this.postRepository.save({
title: 'Seed post',
});
}
}
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Tag } from '../tag.entity.js';
@Injectable()
export class TagSeeder {
tagRepository: Repository<Tag>;
constructor(
@InjectRepository(Tag) tagRepository: Repository<Tag>,
) {
this.tagRepository = tagRepository;
}
async seed() {
await this.tagRepository.save({
name: 'news',
});
}
}
Координатор вызовет оба наполнителя подряд:
import { Injectable } from '@nestjs/common';
import { PostSeeder } from './post.seeder.js';
import { TagSeeder } from './tag.seeder.js';
@Injectable()
export class DatabaseSeeder {
postSeeder: PostSeeder;
tagSeeder: TagSeeder;
constructor(postSeeder: PostSeeder, tagSeeder: TagSeeder) {
this.postSeeder = postSeeder;
this.tagSeeder = tagSeeder;
}
async run() {
await this.postSeeder.seed();
await this.tagSeeder.seed();
}
}
Модуль темы при инициализации запустит координатор:
import { Module, OnModuleInit } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Post } from '../post.entity.js';
import { Tag } from '../tag.entity.js';
import { DatabaseSeeder } from './database.seeder.js';
import { PostSeeder } from './post.seeder.js';
import { TagSeeder } from './tag.seeder.js';
@Module({
imports: [TypeOrmModule.forFeature([Post, Tag])],
providers: [PostSeeder, TagSeeder, DatabaseSeeder],
})
export class PostsModule implements OnModuleInit {
databaseSeeder: DatabaseSeeder;
constructor(databaseSeeder: DatabaseSeeder) {
this.databaseSeeder = databaseSeeder;
}
onModuleInit() {
void this.databaseSeeder.run();
}
}
Корень поднимает канал к базе и импортирует модуль темы:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { PostsModule } from './posts/posts.module.js';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'postgres',
database: 'site',
autoLoadEntities: true,
synchronize: true,
}),
PostsModule,
],
})
export class AppModule {}
Сделайте координатор в
WorkersModule, который при
старте по очереди запускает два
наполнителя для разных таблиц,
список откройте через
WorkerService в
WorkerController и
подключите модуль к PostgreSQL
в корне.