Skip to content

Commit d8ec80d

Browse files
authored
Feat/#327-K: CRDT 에러 핸들러 추가 (#328)
* feat: 클라이언트 CRDT 에러 핸들러 추가 * feat: 동작 실패시 로깅 대신 에러 throw * fix: try-catch 제거 * fix: try 블럭 필요한 부분만 적용 * refactor: initializedRef 네이밍 구체화
1 parent 79d764b commit d8ec80d

File tree

4 files changed

+84
-25
lines changed

4 files changed

+84
-25
lines changed

@wabinar/crdt/linked-list.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,8 @@ export default class LinkedList {
171171

172172
return prevIndex + 1;
173173
} catch (e) {
174-
console.log(`insertById 실패 ^^\n${e}`);
175-
176-
return null;
174+
// console.log(`insertById 실패 ^^\n${e}`);
175+
throw e;
177176
}
178177
}
179178

@@ -197,9 +196,8 @@ export default class LinkedList {
197196

198197
return targetIndex;
199198
} catch (e) {
200-
console.log(`deleteById 실패 ^^\n${e}`);
201-
202-
return null;
199+
// console.log(`deleteById 실패 ^^\n${e}`);
200+
throw e;
203201
}
204202
}
205203

client/src/components/Block/TextBlock.tsx

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ function TextBlock({
3333
}: BlockProps) {
3434
const { momSocket: socket } = useSocketContext();
3535

36+
const initBlock = () => {
37+
socket.emit(BLOCK_EVENT.INIT_TEXT, id);
38+
};
39+
3640
const {
3741
syncCRDT,
3842
readCRDT,
@@ -89,7 +93,14 @@ function TextBlock({
8993
};
9094

9195
const onInsert = (op: RemoteInsertOperation) => {
92-
const prevIndex = remoteInsertCRDT(op);
96+
let prevIndex;
97+
98+
try {
99+
prevIndex = remoteInsertCRDT(op);
100+
} catch {
101+
initBlock();
102+
return;
103+
}
93104

94105
if (!blockRef.current) return;
95106

@@ -101,7 +112,14 @@ function TextBlock({
101112
};
102113

103114
const onDelete = (op: RemoteDeleteOperation) => {
104-
const targetIndex = remoteDeleteCRDT(op);
115+
let targetIndex;
116+
117+
try {
118+
targetIndex = remoteDeleteCRDT(op);
119+
} catch {
120+
initBlock();
121+
return;
122+
}
105123

106124
if (!blockRef.current) return;
107125

@@ -114,7 +132,7 @@ function TextBlock({
114132

115133
// crdt의 초기화와 소켓을 통해 전달받는 리모트 연산 처리
116134
useEffect(() => {
117-
socket.emit(BLOCK_EVENT.INIT_TEXT, id);
135+
initBlock();
118136

119137
ee.on(`${BLOCK_EVENT.INIT_TEXT}-${id}`, onInitialize);
120138
ee.on(`${BLOCK_EVENT.UPDATE_TEXT}-${id}`, onInitialize);
@@ -168,14 +186,29 @@ function TextBlock({
168186
if (event.isComposing) return; // 한글 입력 무시
169187

170188
if (event.inputType === 'deleteContentBackward') {
171-
const remoteDeletion = localDeleteCRDT(offsetRef.current);
189+
let remoteDeletion;
190+
191+
try {
192+
remoteDeletion = localDeleteCRDT(offsetRef.current);
193+
} catch {
194+
initBlock();
195+
return;
196+
}
197+
172198
socket.emit(BLOCK_EVENT.DELETE_TEXT, id, remoteDeletion);
173199
return;
174200
}
175201

176202
const letter = event.data as string;
177203
const previousLetterIndex = offsetRef.current - 2;
178-
const remoteInsertion = localInsertCRDT(previousLetterIndex, letter);
204+
205+
let remoteInsertion;
206+
207+
try {
208+
remoteInsertion = localInsertCRDT(previousLetterIndex, letter);
209+
} catch {
210+
initBlock();
211+
}
179212

180213
socket.emit(BLOCK_EVENT.INSERT_TEXT, id, remoteInsertion);
181214
};

client/src/components/Mom/index.tsx

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ function Mom() {
1515
const { selectedMom } = useSelectedMom();
1616
const { momSocket: socket } = useSocketContext();
1717

18+
const initMom = () => {
19+
if (!selectedMom) return;
20+
socket.emit(MOM_EVENT.INIT, selectedMom._id);
21+
};
22+
1823
const {
1924
syncCRDT,
2025
spreadCRDT,
@@ -82,11 +87,18 @@ function Mom() {
8287

8388
const blockId = uuid();
8489

85-
const remoteInsertion = localInsertCRDT(index, blockId);
90+
let remoteInsertion;
91+
92+
try {
93+
remoteInsertion = localInsertCRDT(index, blockId);
94+
} catch {
95+
initMom();
96+
}
8697

8798
updateBlockFocus(index + 1);
8899

89100
socket.emit(MOM_EVENT.INSERT_BLOCK, blockId, remoteInsertion);
101+
90102
return;
91103
}
92104

@@ -99,7 +111,13 @@ function Mom() {
99111

100112
if (index === 0) return;
101113

102-
const remoteDeletion = localDeleteCRDT(index);
114+
let remoteDeletion;
115+
116+
try {
117+
remoteDeletion = localDeleteCRDT(index);
118+
} catch {
119+
initMom();
120+
}
103121

104122
updateBlockFocus(index - 1);
105123

@@ -115,9 +133,7 @@ function Mom() {
115133
};
116134

117135
useEffect(() => {
118-
if (!selectedMom) return;
119-
120-
socket.emit(MOM_EVENT.INIT, selectedMom._id);
136+
initMom();
121137

122138
socket.on(MOM_EVENT.INIT, (crdt) => {
123139
syncCRDT(crdt);
@@ -135,14 +151,24 @@ function Mom() {
135151
});
136152

137153
socket.on(MOM_EVENT.INSERT_BLOCK, (op) => {
138-
remoteInsertCRDT(op);
154+
try {
155+
remoteInsertCRDT(op);
156+
} catch {
157+
initMom();
158+
return;
159+
}
139160

140161
updateBlockFocus(undefined);
141162
setBlocks(spreadCRDT());
142163
});
143164

144165
socket.on(MOM_EVENT.DELETE_BLOCK, (op) => {
145-
remoteDeleteCRDT(op);
166+
try {
167+
remoteDeleteCRDT(op);
168+
} catch {
169+
initMom();
170+
return;
171+
}
146172

147173
updateBlockFocus(undefined);
148174
setBlocks(spreadCRDT());

client/src/hooks/useCRDT.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,17 @@ export function useCRDT() {
2626

2727
const crdtRef = useRef<CRDT>(new CRDT(clientId, new LinkedList()));
2828

29-
const initializedRef = useRef<boolean>(false);
30-
const operationSet: RemoteOperation[] = [];
29+
const isCRDTInitializedRef = useRef<boolean>(false);
30+
let operationSet: RemoteOperation[] = [];
3131

3232
const syncCRDT = (structure: unknown) => {
3333
crdtRef.current = new CRDT(
3434
clientId,
3535
new LinkedList(structure as LinkedList),
3636
);
3737

38-
initializedRef.current = true;
38+
isCRDTInitializedRef.current = true;
39+
3940
operationSet.forEach(({ type, op }) => {
4041
switch (type) {
4142
case OPERATION_TYPE.INSERT:
@@ -48,15 +49,16 @@ export function useCRDT() {
4849
break;
4950
}
5051
});
52+
operationSet = [];
5153
};
5254

5355
const readCRDT = (): string => {
54-
if (!initializedRef.current) return '';
56+
if (!isCRDTInitializedRef.current) return '';
5557
return crdtRef.current.read();
5658
};
5759

5860
const spreadCRDT = (): string[] => {
59-
if (!initializedRef.current) return [];
61+
if (!isCRDTInitializedRef.current) return [];
6062
return crdtRef.current.spread();
6163
};
6264

@@ -73,7 +75,7 @@ export function useCRDT() {
7375
};
7476

7577
const remoteInsertCRDT = (op: RemoteInsertOperation) => {
76-
if (!initializedRef.current) {
78+
if (!isCRDTInitializedRef.current) {
7779
operationSet.push({ type: OPERATION_TYPE.INSERT, op });
7880
return null;
7981
}
@@ -84,7 +86,7 @@ export function useCRDT() {
8486
};
8587

8688
const remoteDeleteCRDT = (op: RemoteDeleteOperation) => {
87-
if (!initializedRef.current) {
89+
if (!isCRDTInitializedRef.current) {
8890
operationSet.push({ type: OPERATION_TYPE.DELETE, op });
8991
return null;
9092
}

0 commit comments

Comments
 (0)