Skip to content

Commit

Permalink
Merge pull request #93 from Boost-Coder/feature/Batch-#92
Browse files Browse the repository at this point in the history
[#92] 매 00:00 분에 사용자 정보를 업데이트 하는 기능 구현
  • Loading branch information
namewhat99 authored Apr 22, 2024
2 parents 990c45a + 1e21503 commit c9c6a9b
Show file tree
Hide file tree
Showing 12 changed files with 160 additions and 12 deletions.
36 changes: 36 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@nestjs/jwt": "^10.2.0",
"@nestjs/passport": "^10.0.3",
"@nestjs/platform-express": "^10.0.0",
"@nestjs/schedule": "^4.0.2",
"@nestjs/swagger": "^7.3.1",
"@nestjs/typeorm": "^10.0.2",
"@types/passport-jwt": "^4.0.1",
Expand Down
14 changes: 14 additions & 0 deletions src/Entity/algorithm.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { User } from './user';

Expand Down Expand Up @@ -36,6 +38,18 @@ export class Algorithm {
@Column()
point: number;

@CreateDateColumn({
type: 'timestamp',
nullable: false,
})
createDate: Date;

@UpdateDateColumn({
type: 'timestamp',
nullable: true,
})
updateDate: Date;

@OneToOne(() => User, (user) => user.userId, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'user_id', referencedColumnName: 'userId' })
user: User;
Expand Down
14 changes: 14 additions & 0 deletions src/Entity/github.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { User } from './user';

Expand All @@ -27,6 +29,18 @@ export class Github {
@Column()
accessToken: string;

@CreateDateColumn({
type: 'timestamp',
nullable: false,
})
createDate: Date;

@UpdateDateColumn({
type: 'timestamp',
nullable: true,
})
updateDate: Date;

@OneToOne(() => User, (user) => user.userId, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'user_id', referencedColumnName: 'userId' })
user: User;
Expand Down
14 changes: 14 additions & 0 deletions src/Entity/grade.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { User } from './user';

Expand All @@ -24,6 +26,18 @@ export class Grade {
@Column()
point: number;

@CreateDateColumn({
type: 'timestamp',
nullable: false,
})
createDate: Date;

@UpdateDateColumn({
type: 'timestamp',
nullable: true,
})
updateDate: Date;

@OneToOne(() => User, (user) => user.userId, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'user_id', referencedColumnName: 'userId' })
user: User;
Expand Down
14 changes: 14 additions & 0 deletions src/Entity/totalPoint.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
OneToOne,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { User } from './user';

Expand All @@ -21,6 +23,18 @@ export class TotalPoint {
@Column()
point: number;

@CreateDateColumn({
type: 'timestamp',
nullable: false,
})
createDate: Date;

@UpdateDateColumn({
type: 'timestamp',
nullable: true,
})
updateDate: Date;

@OneToOne(() => User, (user) => user.userId, { onDelete: 'CASCADE' })
@JoinColumn({ name: 'user_id', referencedColumnName: 'userId' })
user: User;
Expand Down
4 changes: 4 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import { APP_FILTER, APP_INTERCEPTOR } from '@nestjs/core';
import { HttpExceptionFilter } from './utils/httpExceptionFilter';
import { addTransactionalDataSource } from 'typeorm-transactional';
import { DataSource } from 'typeorm';
import { BatchModule } from './batch/batch.module';
import { ScheduleModule } from '@nestjs/schedule';

@Module({
imports: [
Expand All @@ -30,9 +32,11 @@ import { DataSource } from 'typeorm';
isGlobal: true,
envFilePath: `${process.cwd()}/envs/${process.env.NODE_ENV}.env`,
}),
ScheduleModule.forRoot(),
AuthModule,
UserModule,
StatModule,
BatchModule,
],
controllers: [AppController],
providers: [
Expand Down
10 changes: 10 additions & 0 deletions src/batch/batch.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Module } from '@nestjs/common';
import { BatchService } from './batch.service';
import { UserModule } from '../user/user.module';
import { StatModule } from '../stat/stat.module';

@Module({
imports: [UserModule, StatModule],
providers: [BatchService],
})
export class BatchModule {}
32 changes: 32 additions & 0 deletions src/batch/batch.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Injectable, Logger } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
import { UserService } from '../user/user.service';
import { AlgorithmService } from '../stat/service/algorithm.service';
import { GithubService } from '../stat/service/github.service';
import { TotalService } from '../stat/service/total.service';
import { IsolationLevel, Transactional } from 'typeorm-transactional';

@Injectable()
export class BatchService {
private readonly logger = new Logger(BatchService.name);
constructor(
private userService: UserService,
private algorithmService: AlgorithmService,
private githubService: GithubService,
private totalService: TotalService,
) {}
@Cron('0 0 * * * *')
@Transactional({
isolationLevel: IsolationLevel.READ_COMMITTED,
})
async updateAllUserStat() {
this.logger.log(`모든 유저의 역량 업데이트 시작`);
const users = await this.userService.getUsers();
for (const user of users) {
await this.algorithmService.updateAlgorithm(user.userId);
await this.githubService.updateGithub(user.userId);
await this.totalService.updateTotal(user.userId);
}
this.logger.log(`모든 유저의 역량 업데이트 완료`);
}
}
8 changes: 5 additions & 3 deletions src/stat/service/algorithm.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class AlgorithmService {
async updateAlgorithm(userId: string) {
const algorithm = await this.algorithmRepository.findOneById(userId);
if (algorithm === null) {
throw new NotFoundError('Algorithm info not found');
return;
}
try {
const bojInfo = await this.getBOJInfo(algorithm.bojId);
Expand All @@ -68,9 +68,11 @@ export class AlgorithmService {
} catch (e) {
if (e instanceof BadRequestException) {
await this.removeAlgorithm(userId);
this.logger.log(`${userId} 님의 알고리즘 스탯이 초기화됨.`);
this.logger.warn(`${userId} 님의 알고리즘 스탯이 초기화됨.`);
} else {
throw e;
this.logger.error(
`${userId} 님의 알고리즘 스탯이 업데이트 되지 않음. ${e}`,
);
}
}
}
Expand Down
21 changes: 12 additions & 9 deletions src/stat/service/github.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,19 @@ export class GithubService {
await this.githubRepository.updateGithub(github);
}

public async updateGithubList() {
const userGithubList = await this.githubRepository.findAll();

for (let i = 0; i < userGithubList.length; i++) {
const userResource = await this.getUserResource(
userGithubList[i].accessToken,
public async updateGithub(userId: string) {
const github = await this.githubRepository.findOneById(userId);
if (github === null) {
return;
}
try {
const githubInfo = await this.getUserResource(github.accessToken);
github.point = this.calculateGithubPoint(githubInfo);
await this.githubRepository.updateGithub(github);
} catch (e) {
this.logger.error(
`${userId} 님의 알고리즘 스탯이 업데이트 되지 않음. ${e}`,
);

userGithubList[i].point = this.calculateGithubPoint(userResource);
await this.githubRepository.updateGithub(userGithubList[i]);
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/user/user.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import { Transactional } from 'typeorm-transactional';
export class UserService {
constructor(private userRepository: UserRepository) {}

async getUsers() {
return await this.userRepository.find();
}

async findUserByProviderId(providerId: string) {
const user = await this.userRepository.findOneByProviderId(providerId);
return user;
Expand Down

0 comments on commit c9c6a9b

Please sign in to comment.