Skip to content

Commit

Permalink
Merge pull request #118 from boostcampwm-2024/Feature/#117_CRDT_라이브러리_개선
Browse files Browse the repository at this point in the history
Feature/#117 crdt 라이브러리 개선
  • Loading branch information
hyonun321 authored Nov 14, 2024
2 parents 093f167 + fc49717 commit f2744c1
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 19 deletions.
39 changes: 23 additions & 16 deletions @noctaCrdt/Crdt.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import { LinkedList } from "./LinkedList";
import { NodeId, Node } from "./Node";
import { RemoteInsertOperation, RemoteDeleteOperation, SerializedProps } from "./Interfaces";
import {
RemoteInsertOperation,
RemoteDeleteOperation,
SerializedProps,
Block,
Char,
CRDT as CRDTClassProps,
} from "./Interfaces";

export class CRDT {
export class CRDT implements CRDTClassProps {
clock: number;
client: number;
textLinkedList: LinkedList;
LinkedList: LinkedList;

constructor(client: number) {
this.clock = 0; // 이 CRDT의 논리적 시간 설정
this.client = client;
this.textLinkedList = new LinkedList();
this.LinkedList = new LinkedList();
}

/**
Expand All @@ -21,7 +28,7 @@ export class CRDT {
*/
localInsert(index: number, value: string): RemoteInsertOperation {
const id = new NodeId((this.clock += 1), this.client);
const remoteInsertion = this.textLinkedList.insertAtIndex(index, value, id);
const remoteInsertion = this.LinkedList.insertAtIndex(index, value, id);
return { node: remoteInsertion.node };
}

Expand All @@ -32,12 +39,12 @@ export class CRDT {
*/
localDelete(index: number): RemoteDeleteOperation {
// 유효한 인덱스인지 확인
if (index < 0 || index >= this.textLinkedList.spread().length) {
if (index < 0 || index >= this.LinkedList.spread().length) {
throw new Error(`유효하지 않은 인덱스입니다: ${index}`);
}

// 삭제할 노드 찾기
const nodeToDelete = this.textLinkedList.findByIndex(index);
const nodeToDelete = this.LinkedList.findByIndex(index);
if (!nodeToDelete) {
throw new Error(`삭제할 노드를 찾을 수 없습니다. 인덱스: ${index}`);
}
Expand All @@ -49,7 +56,7 @@ export class CRDT {
};

// 로컬 삭제 수행
this.textLinkedList.deleteNode(nodeToDelete.id);
this.LinkedList.deleteNode(nodeToDelete.id);

// 클록 업데이트
this.clock += 1;
Expand All @@ -66,7 +73,7 @@ export class CRDT {
const newNode = new Node(operation.node.value, newNodeId);
newNode.next = operation.node.next;
newNode.prev = operation.node.prev;
this.textLinkedList.insertById(newNode);
this.LinkedList.insertById(newNode);
// 동기화 논리적 시간
if (this.clock <= newNode.id.clock) {
this.clock = newNode.id.clock + 1;
Expand All @@ -80,7 +87,7 @@ export class CRDT {
remoteDelete(operation: RemoteDeleteOperation): void {
const { targetId, clock } = operation;
if (targetId) {
this.textLinkedList.deleteNode(targetId);
this.LinkedList.deleteNode(targetId);
}
// 동기화 논리적 시간
if (this.clock <= clock) {
Expand All @@ -93,23 +100,23 @@ export class CRDT {
* @returns 현재 텍스트
*/
read(): string {
return this.textLinkedList.stringify();
return this.LinkedList.stringify();
}

/**
* 현재 텍스트를 배열로 반환합니다.
* @returns 현재 텍스트 배열
*/
spread(): string[] {
return this.textLinkedList.spread();
spread(): Block[] | Char[] {
return this.LinkedList.spread();
}

/**
* textLinkedList를 반환하는 getter 메서드
* @returns LinkedList 인스턴스
*/
public getTextLinkedList(): LinkedList {
return this.textLinkedList;
return this.LinkedList;
}

/**
Expand All @@ -121,8 +128,8 @@ export class CRDT {
clock: this.clock,
client: this.client,
textLinkedList: {
head: this.textLinkedList.head,
nodeMap: this.textLinkedList.nodeMap,
head: this.LinkedList.head,
nodeMap: this.LinkedList.nodeMap,
},
};
}
Expand Down
56 changes: 56 additions & 0 deletions @noctaCrdt/Interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { NodeId, Node } from "./Node";

export type ElementType = "p" | "h1" | "h2" | "h3" | "ul" | "ol" | "li" | "checkbox" | "blockquote";

export interface InsertOperation {
node: Node;
}
Expand Down Expand Up @@ -30,3 +32,57 @@ export interface SerializedProps {
nodeMap: { [key: string]: Node };
};
}

export interface WorkSpace {
id: string;
pageList: Page[];
authUser: object;
}

export interface Page {
id: string;
title: string;
icon: string; // 추후 수정
crdt: CRDT;
}

export interface CRDT {
clock: number;
client: number;
LinkedList: LinkedList;
localInsert(index: number, value: string): RemoteInsertOperation;
localDelete(index: number): RemoteDeleteOperation;
remoteInsert(operation: RemoteInsertOperation): void;
remoteDelete(operation: RemoteDeleteOperation): void;
read(): string;
spread(): Block[] | Char[];
}

export interface LinkedList {
head: NodeId | null;
nodeMap: { [key: string]: Block | Char };
}

export interface Block {
id: BlockId;
icon: string; // 추후 수정
type: ElementType;
animation: string;
crdt: CRDT;
indent: number;
next: NodeId;
prev: NodeId;
style: string[];
}

export interface Char {
id: NodeId;
value: string;
next: NodeId | null;
prev: NodeId | null;
}

export interface BlockId {
clock: number;
client: number;
}
6 changes: 3 additions & 3 deletions @noctaCrdt/LinkedList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,14 @@ export class LinkedList {
* 현재 리스트를 배열로 변환합니다.
* @returns 배열로 변환된 리스트
*/
spread(): string[] {
spread(): Node[] {
let currentNodeId = this.head;
const result: string[] = [];
const result: Node[] = [];

while (currentNodeId !== null) {
const currentNode = this.getNode(currentNodeId);
if (!currentNode) break;
result.push(currentNode.value);
result.push(currentNode);
currentNodeId = currentNode.next;
}

Expand Down
18 changes: 18 additions & 0 deletions @noctaCrdt/Page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Page as PageInterface } from "@noctaCrdt/Interfaces";
import { CRDT } from "./Crdt";

export class Page implements PageInterface {
id: string;
title: string;
icon: string;
crdt: CRDT;

constructor(editorCRDT: CRDT = new CRDT(0)) {
// 추후 수정
this.id = "id";
this.title = "title";
this.icon = "icon";
this.crdt = editorCRDT;
// 직렬화, 역직렬화 메서드 추가
}
}
15 changes: 15 additions & 0 deletions @noctaCrdt/WorkSpace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { WorkSpace as WorkSpaceInterface } from "./Interfaces";
import { Page } from "./Page";

export class WorkSpace implements WorkSpaceInterface {
id: string;
pageList: Page[];
authUser: object;

constructor(id: string, pageList: Page[]) {
this.id = id;
this.pageList = pageList;
this.authUser = new Map();
// 직렬화, 역직렬화 메서드 추가
}
}

0 comments on commit f2744c1

Please sign in to comment.