Skip to content

Commit

Permalink
Merge pull request #376 from boostcampwm2023/BE-feature/crdt
Browse files Browse the repository at this point in the history
์ œ๋„ค๋ฆญ ํƒ€์ž… ์ œ๊ฑฐ
  • Loading branch information
Conut-1 authored Feb 1, 2025
2 parents c3e5a4c + e050cc3 commit 183940f
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 119 deletions.
8 changes: 4 additions & 4 deletions nestjs-BE/server/src/board-trees/board-trees.gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ export class BoardTreesGateway implements OnGatewayConnection {
const { boardId, operation: serializedOperation } = payloadObject;

const operationTypeMap = {
add: OperationAdd.parse<string>,
delete: OperationDelete.parse<string>,
move: OperationMove.parse<string>,
update: OperationUpdate.parse<string>,
add: OperationAdd.parse,
delete: OperationDelete.parse,
move: OperationMove.parse,
update: OperationUpdate.parse,
};

const operation =
Expand Down
8 changes: 4 additions & 4 deletions nestjs-BE/server/src/board-trees/board-trees.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export class BoardTreesService {
@InjectModel(BoardTree.name) private boardTreeModel: Model<BoardTree>,
) {}

private boardTrees = new Map<string, CrdtTree<string>>();
private boardTrees = new Map<string, CrdtTree>();

async create(boardId: string, tree: string) {
const createdTree = new this.boardTreeModel({
Expand All @@ -33,16 +33,16 @@ export class BoardTreesService {
async initBoardTree(boardId: string, boardName: string) {
const existingTree = await this.findByBoardId(boardId);
if (existingTree) {
this.boardTrees.set(boardId, CrdtTree.parse<string>(existingTree.tree));
this.boardTrees.set(boardId, CrdtTree.parse(existingTree.tree));
} else {
const newTree = new CrdtTree<string>(boardId);
const newTree = new CrdtTree(boardId);
newTree.tree.get('root').description = boardName;
this.create(boardId, JSON.stringify(newTree));
this.boardTrees.set(boardId, newTree);
}
}

applyOperation(boardId: string, operation: Operation<string>) {
applyOperation(boardId: string, operation: Operation) {
const boardTree = this.boardTrees.get(boardId);
boardTree.applyOperation(operation);
}
Expand Down
12 changes: 6 additions & 6 deletions nestjs-BE/server/src/crdt/crdt-tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { CrdtTree } from './crdt-tree';
import { Node } from './node';

it('crdt tree ๋™๊ธฐํ™”', () => {
const tree1 = new CrdtTree<string>('1');
const tree2 = new CrdtTree<string>('2');
const tree1 = new CrdtTree('1');
const tree2 = new CrdtTree('2');

const op_1_1 = tree1.generateOperationAdd('a', 'root', 'hello');
const op_1_2 = tree1.generateOperationAdd('b', 'root', 'hi');
Expand Down Expand Up @@ -45,7 +45,7 @@ it('crdt tree ๋™๊ธฐํ™”', () => {
});

it('crdt tree ์—ญ์ง๋ ฌํ™”', () => {
const tree = new CrdtTree<string>('1');
const tree = new CrdtTree('1');

const op1 = tree.generateOperationAdd('a', 'root', 'hello');
const op2 = tree.generateOperationAdd('b', 'root', 'hi');
Expand All @@ -56,13 +56,13 @@ it('crdt tree ์—ญ์ง๋ ฌํ™”', () => {

expect(JSON.stringify(tree));

const parsedTree = CrdtTree.parse<string>(JSON.stringify(tree));
const parsedTree = CrdtTree.parse(JSON.stringify(tree));

expect(JSON.stringify(tree)).toEqual(JSON.stringify(parsedTree));
});

it('crdt tree ์ˆœํ™˜', () => {
const tree = new CrdtTree<string>('1');
const tree = new CrdtTree('1');

const op1 = tree.generateOperationAdd('a', 'root', 'hello');
const op2 = tree.generateOperationAdd('b', 'root', 'hi');
Expand All @@ -72,5 +72,5 @@ it('crdt tree ์ˆœํ™˜', () => {
const op6 = tree.generateOperationMove('b', 'a');

tree.applyOperations([op1, op2, op3, op4, op5, op6]);
expect((tree.tree.get('b') as Node<string>).parentId).toEqual('root');
expect((tree.tree.get('b') as Node).parentId).toEqual('root');
});
56 changes: 28 additions & 28 deletions nestjs-BE/server/src/crdt/crdt-tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,75 +14,75 @@ import {
import { Tree } from './tree';
import { Node } from './node';

export class CrdtTree<T> {
operationLogs: OperationLog<T>[] = [];
export class CrdtTree {
operationLogs: OperationLog[] = [];
clock: Clock;
tree = new Tree<T>();
tree = new Tree();

constructor(id: string) {
this.clock = new Clock(id);
}

get(id: string): Node<T> | undefined {
get(id: string): Node | undefined {
return this.tree.get(id);
}

addLog(log: OperationLog<T>) {
addLog(log: OperationLog) {
this.operationLogs.push(log);
}

generateOperationAdd(
targetId: string,
parentId: string,
description: T,
): OperationAdd<T> {
description: string,
): OperationAdd {
this.clock.increment();
const clock = this.clock.copy();
const input: OperationAddInput<T> = {
const input: OperationAddInput = {
id: targetId,
parentId,
description,
clock,
};
return new OperationAdd<T>(input);
return new OperationAdd(input);
}

generateOperationDelete(targetId: string): OperationDelete<T> {
generateOperationDelete(targetId: string): OperationDelete {
this.clock.increment();
const clock = this.clock.copy();
const input: OperationInput = {
id: targetId,
clock,
};
return new OperationDelete<T>(input);
return new OperationDelete(input);
}

generateOperationMove(targetId: string, parentId: string): OperationMove<T> {
generateOperationMove(targetId: string, parentId: string): OperationMove {
this.clock.increment();
const clock = this.clock.copy();
const input: OperationMoveInput = {
id: targetId,
parentId,
clock,
};
return new OperationMove<T>(input);
return new OperationMove(input);
}

generateOperationUpdate(
targetId: string,
description: T,
): OperationUpdate<T> {
description: string,
): OperationUpdate {
this.clock.increment();
const clock = this.clock.copy();
const input: OperationUpdateInput<T> = {
const input: OperationUpdateInput = {
id: targetId,
description,
clock,
};
return new OperationUpdate<T>(input);
return new OperationUpdate(input);
}

applyOperation(operation: Operation<T>) {
applyOperation(operation: Operation) {
this.clock = this.clock.merge(operation.clock);

if (this.operationLogs.length === 0) {
Expand All @@ -94,7 +94,7 @@ export class CrdtTree<T> {
const lastOperation =
this.operationLogs[this.operationLogs.length - 1].operation;
if (operation.clock.compare(lastOperation.clock) === COMPARE.LESS) {
const prevLog = this.operationLogs.pop() as OperationLog<T>;
const prevLog = this.operationLogs.pop() as OperationLog;
prevLog.operation.undoOperation(this.tree, prevLog);
this.applyOperation(operation);
const redoLog = prevLog.operation.redoOperation(this.tree, prevLog);
Expand All @@ -105,25 +105,25 @@ export class CrdtTree<T> {
}
}

applyOperations(operations: Operation<T>[]) {
applyOperations(operations: Operation[]) {
for (const operation of operations) this.applyOperation(operation);
}

static parse<T>(json: string) {
static parse(json: string) {
const parsedJson = JSON.parse(json);
const crdtTree = new CrdtTree<T>('0');
const crdtTree = new CrdtTree('0');
crdtTree.clock = Clock.parse(JSON.stringify(parsedJson.clock));
crdtTree.tree = Tree.parse<T>(JSON.stringify(parsedJson.tree));
crdtTree.tree = Tree.parse(JSON.stringify(parsedJson.tree));

const operationTypeMap = {
add: OperationAdd.parse<T>,
delete: OperationDelete.parse<T>,
move: OperationMove.parse<T>,
update: OperationUpdate.parse<T>,
add: OperationAdd.parse,
delete: OperationDelete.parse,
move: OperationMove.parse,
update: OperationUpdate.parse,
};

const parsedOperationLogs = parsedJson.operationLogs.map(
(operationLog: OperationLog<T>) => {
(operationLog: OperationLog) => {
const operationType = operationLog.operation.operationType;
operationLog.operation = operationTypeMap[operationType](
operationLog.operation,
Expand Down
4 changes: 2 additions & 2 deletions nestjs-BE/server/src/crdt/node.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Node } from './node';

it('node ์—ญ์ง๋ ฌํ™”', () => {
const node = new Node<string>('1', 'root', 'hello');
const parsedNode = Node.parse<string>(JSON.stringify(node));
const node = new Node('1', 'root', 'hello');
const parsedNode = Node.parse(JSON.stringify(node));

expect(JSON.stringify(node)).toEqual(JSON.stringify(parsedNode));
});
10 changes: 5 additions & 5 deletions nestjs-BE/server/src/crdt/node.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
export class Node<T> {
export class Node {
targetId: string;
parentId: string;
description: T | null;
description?: string;
children = new Array<string>();

constructor(
targetId: string,
parentId: string = '0',
description: T | null = null,
description: string = null,
) {
this.targetId = targetId;
this.parentId = parentId;
this.description = description;
}

static parse<T>(json: string) {
static parse(json: string) {
const parsedJson = JSON.parse(json);
const node = new Node<T>(
const node = new Node(
parsedJson.targetId,
parsedJson.parentId,
parsedJson.description,
Expand Down
Loading

0 comments on commit 183940f

Please sign in to comment.