Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

서버에서 가격 계산 기능 추가 #191

Merged
merged 7 commits into from
Dec 4, 2024
12 changes: 8 additions & 4 deletions apps/server/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,24 @@ import { PrivateArchitectureModule } from 'src/private-architecture/private-arch
import { PrismaService } from 'src/prisma/prisma.service';
import { MyModule } from './my/my.module';
import { ScheduleModule } from '@nestjs/schedule';
import { NcloudResourcesService } from './ncloud-resources/ncloud-resources.service.js';
import { CloudsModule } from './clouds/clouds.module';
import { resourceUsage } from 'process';
import { NcloudResourcesService } from './ncloud-resource/ncloud-resource.service.js';
import { CloudModule } from './cloud/cloud.module';
import { RedisModule } from '@nestjs-modules/ioredis';

@Module({
imports: [
RedisModule.forRoot({
type: 'single',
url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`,
}),
ConfigModule.forRoot(),
AuthModule,
UserModule,
PublicArchitectureModule,
PrivateArchitectureModule,
MyModule,
ScheduleModule.forRoot(),
CloudsModule,
CloudModule,
],
controllers: [AppController],
providers: [AppService, PrismaService, NcloudResourcesService],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Test, TestingModule } from '@nestjs/testing';
import { CloudsController } from './clouds.controller';
import { CloudController } from './cloud.controller';

describe('CloudsController', () => {
let controller: CloudsController;
describe('CloudController', () => {
let controller: CloudController;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [CloudsController],
controllers: [CloudController],
}).compile();

controller = module.get<CloudsController>(CloudsController);
controller = module.get<CloudController>(CloudController);
});

it('should be defined', () => {
Expand Down
17 changes: 17 additions & 0 deletions apps/server/src/cloud/cloud.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Controller, Get } from '@nestjs/common';
import { CloudService } from './cloud.service';

@Controller('cloud')
export class CloudController {
constructor(private readonly service: CloudService) {}

@Get('/prices')
getCloudResorucePrices() {
return this.service.findCloudResourcePrices();
}

// @Get('/test')
// getTestPrices() {
// return this.service.calculatePrice();
// }
}
12 changes: 12 additions & 0 deletions apps/server/src/cloud/cloud.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Module } from '@nestjs/common';
import { CloudController } from './cloud.controller';
import { CloudService } from './cloud.service';
import { PrismaModule } from 'src/prisma/prisma.module';

@Module({
imports: [PrismaModule],
controllers: [CloudController],
providers: [CloudService],
exports: [CloudService],
})
export class CloudModule {}
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Test, TestingModule } from '@nestjs/testing';
import { CloudsService } from './clouds.service';
import { CloudService } from './cloud.service';

describe('CloudsService', () => {
let service: CloudsService;
describe('CloudService', () => {
let service: CloudService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [CloudsService],
providers: [CloudService],
}).compile();

service = module.get<CloudsService>(CloudsService);
service = module.get<CloudService>(CloudService);
});

it('should be defined', () => {
Expand Down
65 changes: 65 additions & 0 deletions apps/server/src/cloud/cloud.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { InjectRedis } from '@nestjs-modules/ioredis';
import { Injectable, NotFoundException } from '@nestjs/common';
import Redis from 'ioredis';
import { PrismaService } from 'src/prisma/prisma.service';

@Injectable()
export class CloudService {
constructor(
private readonly prisma: PrismaService,
@InjectRedis() private readonly redis: Redis,
) {}

async findCloudResourcePrices() {
return Object.fromEntries(await this.getCloudResourcesMap());
}

async calculatePrice(nodes: Record<string, any>) {
if (nodes && !Object.keys(nodes).length) throw new NotFoundException();
const cloudResourcesPriceMap = await this.getCloudResourcesMap();
const nodeValues = Object.values(nodes);
const totalMonthPrice = nodeValues.reduce(
(price, nodeValue): number => {
if (nodeValue.properties['server_spec_code']) {
if (
!cloudResourcesPriceMap.has(
nodeValue.properties['server_spec_code'],
)
)
throw new NotFoundException();
price += cloudResourcesPriceMap.get(
nodeValue.properties['server_spec_code'],
).monthCost as number;
return price;
}
return price;
},
0,
);
return { totalMonthPrice };
}

private async getCloudResourcesMap() {
const cachePrices = JSON.parse(await this.redis.get('cloudResource'));
const prices =
cachePrices ||
(await this.prisma.ncloudServerResource.findMany({
select: {
serverSpecCode: true,
productName: true,
hourCost: true,
monthCost: true,
},
}));
const priceMap = new Map<string, Record<string, number | string>>();
prices.map((price) => {
const { productName, hourCost, monthCost } = price;
priceMap.set(price.serverSpecCode, {
productName,
hourCost,
monthCost,
});
});
return priceMap;
}
}
4 changes: 0 additions & 4 deletions apps/server/src/clouds/clouds.controller.ts

This file was deleted.

9 changes: 0 additions & 9 deletions apps/server/src/clouds/clouds.module.ts

This file was deleted.

4 changes: 0 additions & 4 deletions apps/server/src/clouds/clouds.service.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Test, TestingModule } from '@nestjs/testing';
import { NcloudResourcesService } from './ncloud-resources.service';
import { NcloudResourcesService } from './ncloud-resource.service';

describe('NcloudResourcesService', () => {
let service: NcloudResourcesService;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { Ncloud, PriceApi, ApiKeyCredentials } from '@cloud-canvas/ncloud-sdk';
import { InjectRedis } from '@nestjs-modules/ioredis';
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import Redis from 'ioredis';
import { PrismaService } from 'src/prisma/prisma.service';
import { writeFile } from 'fs/promises';

@Injectable()
export class NcloudResourcesService {
constructor(private readonly prisma: PrismaService) {}
constructor(
private readonly prisma: PrismaService,
@InjectRedis() private readonly redis: Redis,
) {}

@Cron(CronExpression.EVERY_DAY_AT_3AM, {
name: 'Insert Ncloud Resource Cron Job',
Expand Down Expand Up @@ -93,6 +97,10 @@ export class NcloudResourcesService {
await tx.ncloudServerResource.createMany({
data: flattenedResources,
});
await this.redis.set(
'cloudResource',
JSON.stringify(flattenedResources),
);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
import { PrivateArchitectureService } from './private-architecture.service';
import { PrivateArchitectureController } from './private-architecture.controller';
import { PrismaModule } from 'src/prisma/prisma.module';
import { CloudModule } from 'src/cloud/cloud.module';

@Module({
imports: [PrismaModule],
imports: [PrismaModule, CloudModule],
controllers: [PrivateArchitectureController],
providers: [PrivateArchitectureService],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,27 @@ import { RemoveArchitectureDto } from './dto/remove-architecture.dto';
import { RemoveVersionDto } from './dto/remove-version.dto';
import { SaveArchitectureDto } from './dto/save-architecture.dto';
import { SaveVersionDto } from './dto/save-version.dto';
import { CloudService } from 'src/cloud/cloud.service';

@Injectable()
export class PrivateArchitectureService {
constructor(private readonly prisma: PrismaService) {}
constructor(
private readonly prisma: PrismaService,
private readonly cloud: CloudService,
) {}

saveArchitecture({
async saveArchitecture({
title,
userId: authorId,
architecture,
cost,
}: SaveArchitectureDto) {
const cost = await this.cloud.calculatePrice(architecture?.nodes);
return this.prisma.privateArchitecture.create({
data: {
title,
authorId,
architecture,
cost,
cost: cost.totalMonthPrice,
},
});
}
Expand Down Expand Up @@ -53,9 +57,9 @@ export class PrivateArchitectureService {
userId: authorId,
title,
architecture,
cost,
}: ModifyArchitectureDto) {
const isAuthor = await this.isArchitectureAuthor(id, authorId);
const cost = await this.cloud.calculatePrice(architecture?.nodes);
if (!isAuthor) throw new ForbiddenException();
return this.prisma.privateArchitecture.update({
where: {
Expand All @@ -65,7 +69,7 @@ export class PrivateArchitectureService {
data: {
title,
architecture,
cost,
cost: cost.totalMonthPrice,
},
});
}
Expand Down Expand Up @@ -108,16 +112,16 @@ export class PrivateArchitectureService {
userId: authorId,
title,
architecture,
cost,
}: SaveVersionDto) {
const isAuthor = await this.isArchitectureAuthor(id, authorId);
const cost = await this.cloud.calculatePrice(architecture?.nodes);
if (!isAuthor) throw new ForbiddenException();
return this.prisma.version.create({
data: {
privateArchitectureId: id,
title,
architecture,
cost,
cost: cost.totalMonthPrice,
},
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { Module } from '@nestjs/common';
import { PublicArchitectureService } from './public-architecture.service';
import { PublicArchitectureController } from './public-architecture.controller';
import { PrismaModule } from 'src/prisma/prisma.module';
import { CloudModule } from 'src/cloud/cloud.module';

@Module({
imports: [PrismaModule],
imports: [PrismaModule, CloudModule],
controllers: [PublicArchitectureController],
providers: [PublicArchitectureService],
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@ import { RemoveArchitectureDto } from './dto/remove-architecture.dto';
import { UnstarDto } from './dto/unstar.dto';
import { StarDto } from './dto/star.dto';
import { ImportDto } from './dto/import.dto';
import { CloudService } from 'src/cloud/cloud.service';

@Injectable()
export class PublicArchitectureService {
constructor(private readonly prisma: PrismaService) {}
constructor(
private readonly prisma: PrismaService,
private readonly cloud: CloudService,
) {}

async findArchitectures(queryParams: FindArchitecturesDto) {
const [data, total] = await this.prisma.$transaction([
Expand Down Expand Up @@ -55,18 +59,18 @@ export class PublicArchitectureService {
return { data, total };
}

saveArchitecture({
async saveArchitecture({
title,
architecture,
cost,
tags,
userId: authorId,
}: SaveArchitectureDto) {
const cost = await this.cloud.calculatePrice(architecture?.nodes);
return this.prisma.publicArchitecture.create({
data: {
title,
architecture,
cost,
cost: cost.totalMonthPrice,
authorId,
tags: {
create: tags.map((name) => ({
Expand Down
3 changes: 2 additions & 1 deletion apps/server/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
"noFallthroughCasesInSwitch": false
"noFallthroughCasesInSwitch": false,
"resolveJsonModule": true
}
}
Loading
Loading