Skip to content

Commit

Permalink
Merge pull request #153 from boostcampwm-2024/feature/ncloud-price
Browse files Browse the repository at this point in the history
Ncloud 서버 리소스 가격 조회 배치 기능 구현
  • Loading branch information
SeoGeonhyuk authored Nov 28, 2024
2 parents fe84d74 + cad29ec commit e4a2bd8
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 50 deletions.
137 changes: 137 additions & 0 deletions apps/server/prisma/migrations/20241128085427_/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
-- CreateTable
CREATE TABLE `import` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`public_architecture_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),

PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `ncloud_server_resource` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`server_resource_type_id` INTEGER NOT NULL,
`server_spec_code` CHAR(50) NOT NULL,
`hour_cost` DOUBLE NOT NULL,
`month_cost` DOUBLE NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`updated_at` TIMESTAMP(0) NULL,

PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `ncloud_server_resource_type` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`type` CHAR(50) NOT NULL,

PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `private_architecture` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`title` CHAR(50) NOT NULL,
`author_id` INTEGER NOT NULL,
`architecture` JSON NOT NULL,
`cost` DOUBLE NOT NULL DEFAULT 0,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`updated_at` TIMESTAMP(0) NULL,

PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `public_architecture_tag` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`public_architecture_id` INTEGER NOT NULL,
`tag_id` INTEGER NOT NULL,

UNIQUE INDEX `public_architecture_tag_public_architecture_id_tag_id_key`(`public_architecture_id`, `tag_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `public_architecture` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`title` CHAR(50) NOT NULL,
`author_id` INTEGER NOT NULL,
`architecture` JSON NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`cost` DOUBLE NOT NULL DEFAULT 0,

PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `star` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`public_architecture_id` INTEGER NOT NULL,
`user_id` INTEGER NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),

UNIQUE INDEX `star_public_architecture_id_user_id_key`(`public_architecture_id`, `user_id`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `tag` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(15) NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),

UNIQUE INDEX `tag_name_key`(`name`),
PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `user` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`name` VARCHAR(30) NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),

PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- CreateTable
CREATE TABLE `version` (
`id` INTEGER NOT NULL AUTO_INCREMENT,
`private_architecture_id` INTEGER NOT NULL,
`title` CHAR(50) NOT NULL,
`created_at` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
`architecture` JSON NOT NULL,
`cost` DOUBLE NOT NULL DEFAULT 0,

PRIMARY KEY (`id`)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- AddForeignKey
ALTER TABLE `import` ADD CONSTRAINT `import_public_architecture_id_fkey` FOREIGN KEY (`public_architecture_id`) REFERENCES `public_architecture`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `import` ADD CONSTRAINT `import_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `ncloud_server_resource` ADD CONSTRAINT `ncloud_server_resource_server_resource_type_id_fkey` FOREIGN KEY (`server_resource_type_id`) REFERENCES `ncloud_server_resource_type`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `private_architecture` ADD CONSTRAINT `private_architecture_author_id_fkey` FOREIGN KEY (`author_id`) REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `public_architecture_tag` ADD CONSTRAINT `public_architecture_tag_public_architecture_id_fkey` FOREIGN KEY (`public_architecture_id`) REFERENCES `public_architecture`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `public_architecture_tag` ADD CONSTRAINT `public_architecture_tag_tag_id_fkey` FOREIGN KEY (`tag_id`) REFERENCES `tag`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `public_architecture` ADD CONSTRAINT `public_architecture_author_id_fkey` FOREIGN KEY (`author_id`) REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `star` ADD CONSTRAINT `star_public_architecture_id_fkey` FOREIGN KEY (`public_architecture_id`) REFERENCES `public_architecture`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `star` ADD CONSTRAINT `star_user_id_fkey` FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;

-- AddForeignKey
ALTER TABLE `version` ADD CONSTRAINT `version_private_architecture_id_fkey` FOREIGN KEY (`private_architecture_id`) REFERENCES `private_architecture`(`id`) ON DELETE RESTRICT ON UPDATE CASCADE;
3 changes: 3 additions & 0 deletions apps/server/prisma/migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "mysql"
2 changes: 1 addition & 1 deletion apps/server/prisma/schema/ncloud-server-resoruce.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ model NcloudServerResource {
serverResourceTypeId Int @map("server_resource_type_id")
serverSpecCode String @map("server_spec_code") @db.Char(50)
hourCost Float @map("hour_cost")
timeCost Float @map("month_cost")
monthCost Float @map("month_cost")
createdAt DateTime @default(now()) @map("created_at") @db.Timestamp(0)
updatedAt DateTime? @updatedAt @map("updated_at") @db.Timestamp(0)
Expand Down
48 changes: 0 additions & 48 deletions apps/server/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,9 @@ import helmet from 'helmet';
import * as cookieParser from 'cookie-parser';
import { PrismaExceptionFilter } from './filters/prisma-exception.filter';
import { ConfigService } from '@nestjs/config';
import { ApiKeyCredentials, Ncloud, PriceApi } from '@cloud-canvas/ncloud-sdk';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
const ncloud = new Ncloud();
const priceApi = new PriceApi(ncloud.keys() as ApiKeyCredentials);
const result1 = await priceApi.getProductCategoryList({});
console.log(result1.productCategoryList);

// VPC
// const result = await priceApi.getProductList({
// regionCode: 'KR',
// productCategoryCode: 'NETWORKING'
// });
// result.productList.forEach((product) => {
// if(product.productCode === 'VPC.V001' || product.productCode === 'SPNET00000000015')
// console.log(product);
// })

// SERVER
// const result = await priceApi.getProductList({
// regionCode: 'KR',
// productCategoryCode: 'COMPUTE',
// });
// result.productList.forEach((product) => {
// if(product.productItemKind.codeName === 'Server' && product.serverProductCode){
// console.log(product);
// }
// })

// SERVER PRICE
const result = await priceApi.getProductPriceList({
regionCode: 'KR',
payCurrencyCode: 'KRW',
productCategoryCode: 'COMPUTE',
});
result.productPriceList.forEach((product) => {
if (
product.productItemKind.code === 'SVR' &&
product.serverProductCode &&
product.serverProductCode.endsWith('50')
) {
console.log(product.productType.codeName);
console.log(product.serverProductCode);
console.log('월');
console.log(product.priceList[0].price);
console.log('시간');
console.log(product.priceList[1].price);
console.log('gksk');
}
});

swaggerConfig(app);

Expand Down
101 changes: 100 additions & 1 deletion apps/server/src/ncloud-resources/ncloud-resources.service.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,103 @@
import { Ncloud, PriceApi, ApiKeyCredentials } from '@cloud-canvas/ncloud-sdk';
import { Injectable } from '@nestjs/common';
import { Cron, CronExpression } from '@nestjs/schedule';
import { PrismaService } from 'src/prisma/prisma.service';

@Injectable()
export class NcloudResourcesService {}
export class NcloudResourcesService {
constructor(private readonly prisma: PrismaService) {}

@Cron(CronExpression.EVERY_DAY_AT_3AM, {
name: 'Insert Ncloud Resource Cron Job',
})
async insertNcloudResource() {
const ncloud = new Ncloud();
const priceApi = new PriceApi(ncloud.keys() as ApiKeyCredentials);
const result = await priceApi.getProductPriceList({
regionCode: 'KR',
payCurrencyCode: 'KRW',
productCategoryCode: 'COMPUTE',
});
const ncloudServerResourceMap: Map<
string,
Record<string, number | string>[]
> = new Map();
result.productPriceList.forEach((product) => {
if (
product.productItemKind.code === 'SVR' &&
product.serverProductCode &&
product.serverProductCode.endsWith('50')
) {
if (!ncloudServerResourceMap.has(product.productType.codeName))
ncloudServerResourceMap.set(
product.productType.codeName,
[],
);
const {
serverProductCode,
priceList: [{ price: monthPrice }, { price: hourPrice }],
}: {
serverProductCode: string;
priceList: { price: number }[];
} = product;
ncloudServerResourceMap.get(product.productType.codeName).push({
serverProductCode: serverProductCode.toLowerCase(),
monthPrice,
hourPrice,
});
}
});
await this.prisma.$transaction(async (tx) => {
await tx.ncloudServerResource.deleteMany({});
await tx.ncloudServerResourceType.deleteMany({});

const ncloudServerResourceTypes = [
...ncloudServerResourceMap.keys(),
].map((key) => ({ type: key }));

await tx.ncloudServerResourceType.createMany({
data: ncloudServerResourceTypes,
});

const ncloudServerResources = await Promise.all(
[...ncloudServerResourceMap.values()].map(
async (ncloudServerResourceList, index) => {
const serverResourceTypeId =
await tx.ncloudServerResourceType.findFirst({
select: { id: true },
where: {
type: ncloudServerResourceTypes[index].type,
},
});

return ncloudServerResourceList.map(
(ncloudServerResource) => ({
serverResourceTypeId: serverResourceTypeId?.id,
serverSpecCode:
ncloudServerResource.serverProductCode as string,
hourCost: parseFloat(
'' + ncloudServerResource.hourPrice,
),
monthCost: parseFloat(
'' + ncloudServerResource.monthPrice,
),
}),
);
},
),
);

const flattenedResources = ncloudServerResources.flat();

await tx.ncloudServerResource.createMany({
data: flattenedResources,
});
console.log(await tx.ncloudServerResourceType.findMany({}));
console.log(await tx.ncloudServerResource.findMany({}));
});
}

async onApplicationBootstrap() {
await this.insertNcloudResource();
}
}

0 comments on commit e4a2bd8

Please sign in to comment.