Skip to content

Commit

Permalink
feat: isHolding 필드를 통한 업데이트 쿼리 디바운싱
Browse files Browse the repository at this point in the history
- 데모때 테스트 해보고 더 지켜봐야 할 것 같습니다

Co-authored-by: Summer Min <summersummerwhy@users.noreply.github.com>
Co-authored-by: ez <ezcolin2@users.noreply.github.com>
  • Loading branch information
3 people committed Nov 21, 2024
1 parent f9c27d4 commit 3a4cda3
Showing 1 changed file with 28 additions and 25 deletions.
53 changes: 28 additions & 25 deletions apps/backend/src/yjs/yjs.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,12 @@ import { NodeCacheService } from '../node-cache/node-cache.service';
import {
yXmlFragmentToProsemirrorJSON,
prosemirrorJSONToYXmlFragment,
prosemirrorJSONToYDoc,
yDocToProsemirrorJSON,
} from 'y-prosemirror';
import { novelEditorSchema } from './yjs.schema';
import { Schema } from 'prosemirror-model';
import { EdgeService } from '../edge/edge.service';
import { Node } from 'src/node/node.entity';
import { Edge } from 'src/edge/edge.entity';
import { YMapEdge } from './yjs.type';
import { YMapNode } from './yjs.type';

// Y.Doc에는 name 컬럼이 없어서 생성했습니다.
class CustomDoc extends Y.Doc {
Expand All @@ -49,8 +45,10 @@ export class YjsService
private readonly edgeService: EdgeService,
private readonly nodeCacheService: NodeCacheService,
) {}

@WebSocketServer()
server: Server;

insertProseMirrorDataToXmlFragment(xmlFragment: Y.XmlFragment, data: any[]) {
// XML Fragment 초기화
xmlFragment.delete(0, xmlFragment.length);
Expand All @@ -72,6 +70,7 @@ export class YjsService
xmlFragment.push([yNode]);
});
}

afterInit() {
if (!this.server) {
this.logger.error('서버 초기화 안됨..!');
Expand Down Expand Up @@ -131,45 +130,47 @@ export class YjsService
this.initializeYEdgeMap(edges, edgesMap);

// node의 변경 사항을 감지한다.
nodesMap.observe(() => {
nodesMap.observe(async () => {
const nodes = Object.values(doc.getMap('nodes').toJSON());

// 모든 노드에 대해 검사한다.
nodes.forEach((node: YMapNode) => {
const { title, id } = node.data;
for await (const node of nodes) {
const { title, id } = node.data; // TODO: 이모지 추가
const { x, y } = node.position;
// 만약 캐쉬에 노드가 존재하지 않다면 갱신 후 캐쉬에 노드를 넣는다.
if (!this.nodeCacheService.has(id)) {
this.nodeService.updateNode(id, { title, x, y });
this.nodeCacheService.set(id, title);
return;
const isHolding = node.isHolding;
const updateCondition =
!(await this.nodeCacheService.has(id)) ||
!(await this.nodeCacheService.hasSameTitle(id, title)) ||
!(await this.nodeCacheService.isHoldingStatusChanged(
id,
isHolding,
));

if (updateCondition) {
await this.nodeService.updateNode(id, { title, x, y });
await this.nodeCacheService.set(id, title);
}

// 만약 캐쉬에 노드가 존재하고 title이 다르다면 갱신한다.
if (!this.nodeCacheService.hasSameTitle(id, title)) {
this.nodeService.updateNode(id, { title, x, y });
this.nodeCacheService.set(id, title);
return;
}
// 만약 캐쉬에 노드가 존재하고 title이 동일하다면 패스한다.
});
}
});

// edge의 변경 사항을 감지한다.
edgesMap.observe(() => {
const edges = Object.values(doc.getMap('edges').toJSON());
edges.forEach(async (edge: YMapEdge) => {
edgesMap.observe(async () => {
const edges: YMapEdge[] = Object.values(doc.getMap('edges').toJSON());

for await (const edge of edges) {
const findEdge = await this.edgeService.findEdgeByFromNodeAndToNode(
parseInt(edge.source),
parseInt(edge.target),
);

// 연결된 노드가 없을 때만 edge 생성
if (!findEdge) {
await this.edgeService.createEdge({
fromNode: parseInt(edge.source),
toNode: parseInt(edge.target),
});
}
});
}
});
});
}
Expand All @@ -193,6 +194,7 @@ export class YjsService
},
selected: false, // 기본적으로 선택되지 않음
dragging: true,
isHolding: false,
});
});
}
Expand All @@ -212,6 +214,7 @@ export class YjsService
});
});
}

// yXmlFragment에 content를 넣어준다.
initializePageContent(content: Object, yXmlFragment: Y.XmlFragment) {
prosemirrorJSONToYXmlFragment(novelEditorSchema, content, yXmlFragment);
Expand Down

0 comments on commit 3a4cda3

Please sign in to comment.