NestJS- Seeder
Ref Docs
STAR
S 상황
- 기본 프리셋 전략의 값은 반드시 시드 데이터가 있어야 한다.
- Readonly 테이블과 비슷하다.
T 과제
- seed역할을 수행하는 모듈을 만들고
- createApplicationContext 을 이용해
- 시드서비스를 호출하자.
A 액션
- seeder 모듈 제작
- seeder 서비스 제작
- seed data 제작
- ssed Application 제작
R 결과
seed.ts
import { NestFactory } from '@nestjs/core';
import { SeederModule } from './seeder.module';
import { SeederService } from './seeder.service';
async function bootstrap() {
const appContext = await NestFactory.createApplicationContext(SeederModule);
const seederService = appContext.get(SeederService);
await seederService.seedBaseTradingStrategy();
}
bootstrap();
data.ts
import { StrategyName } from 'src/trading/constant/strategy-setting';
import { BaseTradingStrategy } from 'src/trading/entities';
export const preSet__BaseTradingStrategy_List: BaseTradingStrategy[] = [
{
trading_strategy_code: 0,
trading_strategy_name: StrategyName.None,
setting_json: {},
},
{
trading_strategy_code: 1,
trading_strategy_name: StrategyName.GoldenCross,
setting_json: {
GoldenCross: {
pfast: 5,
pslow: 10,
},
},
},
{
trading_strategy_code: 2,
trading_strategy_name: StrategyName.SMA,
setting_json: {
SMA: { SMA_A: 5 },
},
},
];
seeder.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import * as Chance from 'chance';
import { Logger } from '@nestjs/common';
import {
AccumulateProfitRateChart,
BacktestDetailInfo,
BacktestMontlyProfitRateChart,
BacktestQueue,
BacktestWinRatio,
History,
InvestProfitInfo,
} from 'src/backtest/entities';
import {
Category,
CategoryList,
Corporation,
DailyStock,
} from 'src/finance/entities';
import {
LookupMemberList,
MemberInfo,
OperationMemberList,
} from 'src/member/entities';
import {
Hash,
HashList,
MemberStrategy,
} from 'src/strategy/entities';
import {
BaseTradingStrategy,
SimpleBacktest,
Universal,
} from 'src/trading/entities';
import { UploadedObject } from 'src/upload/entities/uploaded-object.entity';
import { UserRole } from 'src/member/entities/member-info.entity';
import { InvestType } from 'src/strategy/entities/member-strategy.entity';
import { preSet__BaseTradingStrategy_List } from './pre-settings/data';
@Injectable()
export class SeederService {
private readonly logger = new Logger(SeederService.name);
constructor(
@InjectRepository(CategoryList)
private readonly CategoryList: Repository<CategoryList>,
@InjectRepository(Category)
private readonly Category: Repository<Category>,
@InjectRepository(Corporation)
private readonly Corporation: Repository<Corporation>,
@InjectRepository(DailyStock)
private readonly DailyStock: Repository<DailyStock>,
@InjectRepository(BaseTradingStrategy)
private readonly BaseTradingStrategy: Repository<BaseTradingStrategy>,
@InjectRepository(SimpleBacktest)
private readonly SimpleBacktest: Repository<SimpleBacktest>,
@InjectRepository(Universal)
private readonly Universal: Repository<Universal>,
@InjectRepository(Hash)
private readonly Hash: Repository<Hash>,
@InjectRepository(HashList)
private readonly HashList: Repository<HashList>,
@InjectRepository(MemberStrategy)
private readonly MemberStrategy: Repository<MemberStrategy>,
@InjectRepository(AccumulateProfitRateChart)
private readonly AccumulateProfitRateChart: Repository<AccumulateProfitRateChart>,
@InjectRepository(BacktestDetailInfo)
private readonly BacktestDetailInfo: Repository<BacktestDetailInfo>,
@InjectRepository(BacktestMontlyProfitRateChart)
private readonly BacktestMontlyProfitRateChart: Repository<BacktestMontlyProfitRateChart>,
@InjectRepository(BacktestQueue)
private readonly BacktestQueue: Repository<BacktestQueue>,
@InjectRepository(BacktestWinRatio)
private readonly BacktestWinRatio: Repository<BacktestWinRatio>,
@InjectRepository(History)
private readonly History: Repository<History>,
@InjectRepository(InvestProfitInfo)
private readonly InvestProfitInfo: Repository<InvestProfitInfo>,
@InjectRepository(LookupMemberList)
private readonly LookupMemberList: Repository<LookupMemberList>,
@InjectRepository(MemberInfo)
private readonly MemberInfo: Repository<MemberInfo>,
@InjectRepository(OperationMemberList)
private readonly OperationMemberList: Repository<OperationMemberList>,
@InjectRepository(UploadedObject)
private readonly UploadedObject: Repository<UploadedObject>,
) {}
async seedMemberInfo(n: number) {
try {
await Promise.all(
new Array(n).fill(0).map(async () => {
return this.MemberInfo.save(this.__createMemberInfo());
}),
);
this.logger.log(`✔ seedMemberInfo ${n} done`);
return true;
} catch (error) {
this.logger.error(`❌ seedMemberInfo fails`);
return false;
}
}
async seedBaseTradingStrategy() {
try {
const targets = await this.BaseTradingStrategy.find();
await Promise.all(
targets.map(async (t) =>
this.BaseTradingStrategy.delete(t.trading_strategy_code),
),
);
await Promise.all(
preSet__BaseTradingStrategy_List.map(async (t) =>
this.BaseTradingStrategy.save(this.BaseTradingStrategy.create(t)),
),
);
this.logger.verbose('✔ seedBaseTradingStrategy');
} catch (error) {
this.logger.error('❌ seedBaseTradingStrategy', error);
}
}
async seedScenario01() {
this.logger.verbose('✔ seedScenario01');
}
__createMemberInfo() {
const email = Chance().email();
return this.MemberInfo.create({
email_id: email,
password: email,
member_name: Chance().name(),
});
}
}
seeder.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import * as Joi from 'joi';
import {
AccumulateProfitRateChart,
BacktestDetailInfo,
BacktestMontlyProfitRateChart,
BacktestQueue,
BacktestWinRatio,
History,
InvestProfitInfo,
} from 'src/backtest/entities';
import {
Category,
CategoryList,
Corporation,
DailyStock,
} from 'src/finance/entities';
import {
LookupMemberList,
MemberInfo,
OperationMemberList,
} from 'src/member/entities';
import { Hash, HashList, MemberStrategy } from 'src/strategy/entities';
import {
BaseTradingStrategy,
SimpleBacktest,
Universal,
} from 'src/trading/entities';
import { UploadedObject } from 'src/upload/entities/uploaded-object.entity';
import { SeederService } from './seeder.service';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: process.env.NODE_ENV === 'dev' ? '.env.dev' : '.env.test',
ignoreEnvFile: process.env.NODE_ENV === 'prod',
validationSchema: Joi.object({
MAINTAINER: Joi.string().required(),
PORT: Joi.number().required(),
DATABASE_URL: Joi.string().required(),
DATABASE_rejectUnauthorized: Joi.string().required(),
}),
}),
TypeOrmModule.forRoot({
type: 'postgres',
url: process.env.DATABASE_URL,
...(process.env.DATABASE_rejectUnauthorized === 'false' && {
ssl: {
rejectUnauthorized: false,
},
}),
synchronize: false,
logging: false,
entities: [
...[
CategoryList,
Category,
Corporation,
DailyStock,
],
...[
BaseTradingStrategy,
SimpleBacktest,
Universal,
],
...[
Hash,
HashList,
MemberStrategy,
],
...[
AccumulateProfitRateChart,
BacktestDetailInfo,
BacktestMontlyProfitRateChart,
BacktestQueue,
BacktestWinRatio,
History,
InvestProfitInfo,
],
...[
LookupMemberList,
MemberInfo,
OperationMemberList,
],
...[
UploadedObject,
],
],
}),
TypeOrmModule.forFeature([
...[
CategoryList,
Category,
Corporation,
DailyStock,
],
...[
BaseTradingStrategy,
SimpleBacktest,
Universal,
],
...[
Hash,
HashList,
MemberStrategy,
],
...[
AccumulateProfitRateChart,
BacktestDetailInfo,
BacktestMontlyProfitRateChart,
BacktestQueue,
BacktestWinRatio,
History,
InvestProfitInfo,
],
...[
LookupMemberList,
MemberInfo,
OperationMemberList,
],
...[
UploadedObject,
],
]),
],
controllers: [],
providers: [SeederService],
exports: [SeederService],
})
export class SeederModule {}