Skip to content

Commit

Permalink
Merge pull request #194 from boostcampwm-2024/be-feature-#188
Browse files Browse the repository at this point in the history
DB 데이터 저장 구현
  • Loading branch information
ezcolin2 authored Nov 19, 2024
2 parents e1ffb27 + a630937 commit 428419b
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 20 deletions.
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,8 @@ lerna-debug.log*

# IDE - VSCode
.vscode/*
apps/backend/db.sqlite
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
db.sqlite
Binary file removed apps/backend/db
Binary file not shown.
2 changes: 2 additions & 0 deletions apps/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"lib0": "^0.2.98",
"node-ts-cache": "^4.4.0",
"node-ts-cache-storage-memory": "^4.4.0",
"path": "^0.12.7",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
Expand Down
9 changes: 9 additions & 0 deletions apps/backend/src/node-cache/node-cache.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module, Global } from '@nestjs/common';
import { NodeCacheService } from './node-cache.service';

@Global()
@Module({
providers: [NodeCacheService],
exports: [NodeCacheService],
})
export class NodeCacheModule {}
33 changes: 33 additions & 0 deletions apps/backend/src/node-cache/node-cache.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Injectable } from '@nestjs/common';
import { CacheContainer } from 'node-ts-cache';
import { MemoryStorage } from 'node-ts-cache-storage-memory';

@Injectable()
export class NodeCacheService {
private cache: CacheContainer;
private ttlTime: number;

constructor() {
this.ttlTime = 10;
this.cache = new CacheContainer(new MemoryStorage());
}

async set(nodeId: number, title: string): Promise<void> {
const config = { ttl: this.ttlTime };
await this.cache.setItem(nodeId.toString(), title, config);
}

async get(nodeId: number): Promise<String | undefined> {
return await this.cache.getItem<String>(nodeId.toString());
}

async has(nodeId: number): Promise<boolean> {
const item = await this.cache.getItem(nodeId.toString());
return item !== undefined;
}

async hasSameTitle(nodeId: number, title: string): Promise<boolean> {
const savedTitle = await this.get(nodeId);
return !!savedTitle && savedTitle === title;
}
}
17 changes: 9 additions & 8 deletions apps/backend/src/page/page.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,18 @@ export class PageService {
) {}

async createPage(dto: CreatePageDto): Promise<Page> {
const { title, content, x, y } = dto;
const { title, x, y } = dto;

// 페이지부터 생성한다.
const page = await this.pageRepository.save({ title, content });
// 노드부터 생성한다.
const node = await this.nodeRepository.save({ title, x, y });

// 노드를 생성한다.
const node = await this.nodeRepository.save({ id: page.id, x, y });
// 페이지를 생성한다.
const page = await this.pageRepository.save({ title, content: {} });

// 노드와 페이지를 서로 연결하여 저장한다.
page.node = node;
return await this.pageRepository.save(page);
// 페이지와 노드를 서로 연결하여 저장한다.
node.page = page;
await this.nodeRepository.save(node);
return page;
}

async createLinkedPage(title: string, nodeId: number): Promise<Page> {
Expand Down
3 changes: 3 additions & 0 deletions apps/backend/src/yjs/yjs.module.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { Module } from '@nestjs/common';
import { YjsService } from './yjs.service';
import { NodeModule } from 'src/node/node.module';
import { NodeCacheModule } from 'src/node-cache/node-cache.module';

@Module({
imports: [NodeModule, NodeCacheModule],
providers: [YjsService],
})
export class YjsModule {}
44 changes: 33 additions & 11 deletions apps/backend/src/yjs/yjs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { Logger } from '@nestjs/common';
import { Server } from 'socket.io';
import { YSocketIO } from 'y-socket.io/dist/server';
import * as Y from 'yjs';
import { NodeService } from '../node/node.service';
import { NodeCacheService } from '../node-cache/node-cache.service';

@WebSocketGateway(1234)
export class YjsService
Expand All @@ -17,6 +19,10 @@ export class YjsService
private logger = new Logger('YjsGateway');
private ysocketio: YSocketIO;

constructor(
private readonly nodeService: NodeService,
private readonly nodeCacheService: NodeCacheService,
) {}
@WebSocketServer()
server: Server;

Expand All @@ -32,20 +38,36 @@ export class YjsService

this.ysocketio.initialize();

this.ysocketio.on('document-update', (doc: Y.Doc) => {
// console.log(doc.get("content").doc.share.get("content"));
// console.log(doc.share.get('default'));
});

this.ysocketio.on('document-loaded', (doc: Y.Doc) => {
this.logger.log(`Document loaded: ${doc.guid}`);
doc.on('update', () => {
const nodes = Object.values(doc.getMap('nodes').toJSON());

// 모든 노드에 대해 검사한다.
nodes.forEach((node) => {
const { title, id } = node.data;
const { x, y } = node.position;
// 만약 캐쉬에 노드가 존재하지 않다면 갱신 후 캐쉬에 노드를 넣는다.
if (!this.nodeCacheService.has(id)) {
console.log(id);
this.nodeService.updateNode(id, { title, x, y });
this.nodeCacheService.set(id, title);
return;
}

const titleMap = doc.getMap('title');
titleMap.observe(() => {
console.log(titleMap.toString());
// 만약 캐쉬에 노드가 존재하고 title이 다르다면 갱신한다.
if (!this.nodeCacheService.hasSameTitle(id, title)) {
this.nodeService.updateNode(id, { title, x, y });
this.nodeCacheService.set(id, title);
return;
}
// 만약 캐쉬에 노드가 존재하고 title이 동일하다면 패스한다.
});
});
// const toggleMap = doc.getMap('toggleMap');
// toggleMap.observe(() => {
// const toggleState = toggleMap.get('toggle') || false;
// this.logger.log('🐰 토글 상태 변경', {
// toggleState,
// });
// });
});
}

Expand Down
54 changes: 54 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3045,6 +3045,11 @@ bl@^4.0.3, bl@^4.1.0:
inherits "^2.0.4"
readable-stream "^3.4.0"

[email protected]:
version "3.7.2"
resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f"
integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==

[email protected]:
version "1.20.3"
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
Expand Down Expand Up @@ -3750,6 +3755,11 @@ delegates@^1.0.0:
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
integrity sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==

denque@^1.5.0:
version "1.5.1"
resolved "https://registry.yarnpkg.com/denque/-/denque-1.5.1.tgz#07f670e29c9a78f8faecb2566a1e2c11929c5cbf"
integrity sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==

[email protected]:
version "2.0.0"
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
Expand Down Expand Up @@ -6604,6 +6614,23 @@ node-releases@^2.0.18:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f"
integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==

node-ts-cache-storage-memory@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/node-ts-cache-storage-memory/-/node-ts-cache-storage-memory-4.4.0.tgz#d87da36bef0145c4d5a988191ffff6b9789c394e"
integrity sha512-eG8tFF4C1/RBmx52cS/dEu63l+Cn+Z6mz16nuTJwNyvtvDHWjsKKM3hg77PA7ddgf2ztaCyen8ZMQnLy191S4g==
dependencies:
debug "^4.3.2"
node-ts-cache "^4.4.0"

node-ts-cache@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/node-ts-cache/-/node-ts-cache-4.4.0.tgz#ce10368537751d198565d15d1352bab5cc649252"
integrity sha512-ZULcxpzyFfgpOd33PHjwhPz4fkWSfyrwa9sq1j4jyOm+PaBpQDIzB3m5HRiSKdgEBtQhP3g6hX44dnMjnoHiPA==
dependencies:
bluebird "3.7.2"
debug "^4.3.2"
redis "^3.1.2"

nopt@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/nopt/-/nopt-5.0.0.tgz#530942bb58a512fccafe53fe210f13a25355dc88"
Expand Down Expand Up @@ -7494,6 +7521,33 @@ readdirp@~3.6.0:
dependencies:
picomatch "^2.2.1"

redis-commands@^1.7.0:
version "1.7.0"
resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89"
integrity sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==

redis-errors@^1.0.0, redis-errors@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad"
integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==

redis-parser@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4"
integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==
dependencies:
redis-errors "^1.0.0"

redis@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/redis/-/redis-3.1.2.tgz#766851117e80653d23e0ed536254677ab647638c"
integrity sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==
dependencies:
denque "^1.5.0"
redis-commands "^1.7.0"
redis-errors "^1.2.0"
redis-parser "^3.0.0"

reflect-metadata@^0.1.13:
version "0.1.14"
resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.14.tgz#24cf721fe60677146bb77eeb0e1f9dece3d65859"
Expand Down

0 comments on commit 428419b

Please sign in to comment.