Skip to content

Commit

Permalink
Merge pull request #303 from boostcampwm2023/BE-feature/prevent-cycle
Browse files Browse the repository at this point in the history
트리 순환 막기
  • Loading branch information
tnpfldyd authored Dec 14, 2023
2 parents c51c54c + aeed977 commit d0da543
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 0 deletions.
15 changes: 15 additions & 0 deletions nestjs-BE/server/src/crdt/crdt-tree.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,18 @@ it('crdt tree 역직렬화', () => {

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

it('crdt tree 순환', () => {
const tree = new CrdtTree<string>('1');

const op1 = tree.generateOperationAdd('a', 'root', 'hello');
const op2 = tree.generateOperationAdd('b', 'root', 'hi');
const op3 = tree.generateOperationAdd('c', 'a', 'good');
const op4 = tree.generateOperationAdd('d', 'b', 'bad');
const op5 = tree.generateOperationMove('a', 'b');
const op6 = tree.generateOperationMove('b', 'a');

tree.applyOperations([op1, op2, op3, op4, op5, op6]);

expect(tree.tree.get('b').parentId).toEqual('root');
});
4 changes: 4 additions & 0 deletions nestjs-BE/server/src/crdt/operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ export class OperationMove<T> extends Operation<T> {
const node = tree.get(this.id);
const oldParentId = node.parentId;

if (tree.isAncestor(this.parentId, this.id)) {
return { operation: this, oldParentId };
}

tree.removeNode(this.id);
tree.attachNode(this.id, this.parentId);
return { operation: this, oldParentId };
Expand Down
19 changes: 19 additions & 0 deletions nestjs-BE/server/src/crdt/tree.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Tree } from './tree';

it('isAncestor', () => {
const tree = new Tree<string>();

tree.addNode('a', 'root', 'test');
tree.addNode('b', 'a', 'test');
tree.addNode('c', 'b', 'test');
tree.addNode('d', 'a', 'test');
tree.addNode('e', 'b', 'test');

expect(tree.isAncestor('c', 'a')).toBeTruthy();
expect(tree.isAncestor('c', 'root')).toBeTruthy();
expect(tree.isAncestor('d', 'root')).toBeTruthy();
expect(tree.isAncestor('d', 'a')).toBeTruthy();
expect(tree.isAncestor('c', 'e')).toBeFalsy();
expect(tree.isAncestor('e', 'c')).toBeFalsy();
expect(tree.isAncestor('c', 'd')).toBeFalsy();
});
10 changes: 10 additions & 0 deletions nestjs-BE/server/src/crdt/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class Tree<T> {

const targetIndex = parentNode.children.indexOf(targetId);
if (targetIndex !== -1) parentNode.children.splice(targetIndex, 1);
targetNode.parentId = '0';

return this.nodes.get(targetId);
}
Expand All @@ -56,6 +57,15 @@ export class Tree<T> {
return { nodes: Array.from(this.nodes.values()) };
}

isAncestor(targetId: string, ancestorId: string) {
let curNode = this.nodes.get(targetId);
while (curNode) {
if (curNode.parentId === ancestorId) return true;
curNode = this.nodes.get(curNode.parentId);
}
return false;
}

static parse<T>(json: string) {
const { nodes } = JSON.parse(json);
const tree = new Tree<T>();
Expand Down

0 comments on commit d0da543

Please sign in to comment.