From 341334843f022f17ca2d4c27fc8348f4b76a4007 Mon Sep 17 00:00:00 2001 From: HKLeeeee Date: Tue, 12 Dec 2023 19:24:19 +0900 Subject: [PATCH 1/9] =?UTF-8?q?fix:=20[BE]=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=EC=8B=9C=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backEnd/api/src/auth/auth.controller.ts | 6 ++-- .../common/transaction/transaction.service.ts | 32 +++++++++++-------- backEnd/api/src/users/users.service.ts | 12 ++++++- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/backEnd/api/src/auth/auth.controller.ts b/backEnd/api/src/auth/auth.controller.ts index 758d7ce..3e05f52 100644 --- a/backEnd/api/src/auth/auth.controller.ts +++ b/backEnd/api/src/auth/auth.controller.ts @@ -52,8 +52,7 @@ export class AuthController { const user: UserDto = await this.googleService.getUserInfo(id_token); let findUser = await this.userService.findUser(user); if (findUser === null) { - await this.userService.addUser(user, 'google'); - findUser = await this.userService.findUser(user); + findUser = await this.userService.getUserAfterAddUser(user, 'google'); } const returnTo: string = await this.authService.login(findUser, res, req); return res.redirect(returnTo); @@ -84,8 +83,7 @@ export class AuthController { const user: UserDto = await this.githubService.getUserInfo(accessToken); let findUser = await this.userService.findUser(user); if (findUser === null) { - await this.userService.addUser(user, 'github'); - findUser = await this.userService.findUser(user); + findUser = await this.userService.getUserAfterAddUser(user, 'github'); } const returnTo: string = await this.authService.login(findUser, res, req); diff --git a/backEnd/api/src/common/transaction/transaction.service.ts b/backEnd/api/src/common/transaction/transaction.service.ts index 1f40328..ee14f59 100644 --- a/backEnd/api/src/common/transaction/transaction.service.ts +++ b/backEnd/api/src/common/transaction/transaction.service.ts @@ -58,20 +58,24 @@ export class TransactionService implements OnModuleInit { return async function (...args: any[]) { const qr = await dataSource.createQueryRunner(); - await queryRunnerLocalStorage.run({ qr }, async function () { - try { - await qr.startTransaction(); - const result = await originalMethod.apply(instance, args); - await qr.commitTransaction(); - return result; - } catch (e) { - await qr.rollbackTransaction(); - this.logger.error(e); - throw new TransactionRollback(); - } finally { - await qr.release(); - } - }); + const result = await queryRunnerLocalStorage.run( + { qr }, + async function () { + try { + await qr.startTransaction(); + const result = await originalMethod.apply(instance, args); + await qr.commitTransaction(); + return result; + } catch (e) { + await qr.rollbackTransaction(); + this.logger.error(e); + throw new TransactionRollback(); + } finally { + await qr.release(); + } + }, + ); + return result; }; } diff --git a/backEnd/api/src/users/users.service.ts b/backEnd/api/src/users/users.service.ts index 1478318..db17606 100644 --- a/backEnd/api/src/users/users.service.ts +++ b/backEnd/api/src/users/users.service.ts @@ -15,13 +15,23 @@ export class UsersService { private usersRepository: Repository, ) {} @Transactional('typeorm') - async addUser(userDTO: UserDto, oauth: OAUTH) { + async getUserAfterAddUser( + userDTO: UserDto, + oauth: OAUTH, + ): Promise { const user = new UserEntity(); user.name = userDTO.name; user.authServiceID = userDTO.authServiceID; user.oauth = oauth; const repository = getLocalStorageRepository(UserEntity); await repository.save(user); + + const find = await repository.findOne({ + where: { + authServiceID: userDTO.authServiceID, + }, + }); + return find as UserEntity; } async findUser(userDTO: UserDto): Promise { From a778db4c9262a459d02d60e146cfef010fa3ec4d Mon Sep 17 00:00:00 2001 From: d0422 Date: Wed, 13 Dec 2023 17:01:10 +0900 Subject: [PATCH 2/9] =?UTF-8?q?feat:=20[FE]=20=EC=86=8C=EC=BC=93=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0=EB=B0=A9=EC=8B=9D=20=EB=B3=80=EA=B2=BD=20cre?= =?UTF-8?q?ateSocket=EC=9D=84=20=ED=86=B5=ED=95=B4=20room,=20chat=EC=97=90?= =?UTF-8?q?=20=EB=8C=80=ED=95=9C=20=EC=86=8C=EC=BC=93=20=EC=97=B0=EA=B2=B0?= =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontEnd/src/apis/getSocketURL.ts | 11 +++++-- .../src/components/room/ChattingSection.tsx | 30 +++++++++++-------- frontEnd/src/hooks/useRTCConnection.ts | 29 ++++++++++-------- frontEnd/src/utils/createSocket.ts | 12 ++++++++ 4 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 frontEnd/src/utils/createSocket.ts diff --git a/frontEnd/src/apis/getSocketURL.ts b/frontEnd/src/apis/getSocketURL.ts index d2fa136..b5d9395 100644 --- a/frontEnd/src/apis/getSocketURL.ts +++ b/frontEnd/src/apis/getSocketURL.ts @@ -1,8 +1,15 @@ import axios from 'axios'; import { VITE_SOCKET_URL } from '@/constants/env'; -export default async function getSocketURL(roomName: string) { - const result = await axios.post(VITE_SOCKET_URL, { roomName }); +type SocketType = 'signalling' | 'chatting'; + +export const SOCKET_TYPE: Record = { + SIGNAL: 'signalling', + CHAT: 'chatting', +}; + +export default async function getSocketURL(type: SocketType, roomName: string) { + const result = await axios.post(`${VITE_SOCKET_URL}/${type}`, { roomName }); return result.data.result.url; } diff --git a/frontEnd/src/components/room/ChattingSection.tsx b/frontEnd/src/components/room/ChattingSection.tsx index 348f0a6..5da5a96 100644 --- a/frontEnd/src/components/room/ChattingSection.tsx +++ b/frontEnd/src/components/room/ChattingSection.tsx @@ -1,7 +1,6 @@ import { useParams } from 'react-router-dom'; import { memo, useEffect, useState } from 'react'; -import { Socket, io } from 'socket.io-client/debug'; -import { VITE_CHAT_URL } from '@/constants/env'; +import { Socket } from 'socket.io-client/debug'; import { ErrorData, ErrorResponse, MessageData } from '@/types/chatting'; import ChattingMessage from './chatting/ChattingMessage'; import useLastMessageViewingState from '@/hooks/useLastMessageViewingState'; @@ -12,6 +11,8 @@ import Section from '../common/SectionWrapper'; import { CHATTING_ERROR_STATUS_CODE, CHATTING_ERROR_TEXT } from '@/constants/chattingErrorResponse'; import ChattingErrorToast from '../common/ChattingErrorToast'; import useScroll from '@/hooks/useScroll'; +import getSocketURL, { SOCKET_TYPE } from '@/apis/getSocketURL'; +import createSocket from '@/utils/createSocket'; function ChattingSection() { const [socket, setSocket] = useState(null); @@ -51,20 +52,23 @@ function ChattingSection() { if (statusCode === AI_ERROR_CODE) setErrorData(AI_ERROR_TEXT); }; - useEffect(() => { - setSocket(() => { - const newSocket = io(VITE_CHAT_URL, { - transports: ['websocket'], - }); + const socketConnect = async () => { + const socketURL = await getSocketURL(SOCKET_TYPE.CHAT, roomId as string); + const socketCallbacks = { + [CHATTING_SOCKET_RECIEVE_EVNET.NEW_MESSAGE]: handleRecieveMessage, + exception: handleChattingSocketError, + }; + + const newSocket = createSocket(socketURL, socketCallbacks); - newSocket.on(CHATTING_SOCKET_RECIEVE_EVNET.NEW_MESSAGE, handleRecieveMessage); - newSocket.on('exception', handleChattingSocketError); - newSocket.connect(); + newSocket.connect(); + newSocket.emit(CHATTING_SOCKET_EMIT_EVNET.JOIN_ROOM, { room: roomId }); - newSocket.emit(CHATTING_SOCKET_EMIT_EVNET.JOIN_ROOM, { room: roomId }); + setSocket(newSocket); + }; - return newSocket; - }); + useEffect(() => { + socketConnect(); }, []); useEffect(() => { diff --git a/frontEnd/src/hooks/useRTCConnection.ts b/frontEnd/src/hooks/useRTCConnection.ts index 7e5c9f1..3e2ec49 100644 --- a/frontEnd/src/hooks/useRTCConnection.ts +++ b/frontEnd/src/hooks/useRTCConnection.ts @@ -1,9 +1,10 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ import { useState, useEffect } from 'react'; -import { Socket, io } from 'socket.io-client/debug'; +import { Socket } from 'socket.io-client/debug'; +import createSocket from '@utils/createSocket'; import { RTC_SOCKET_EMIT_EVENT, RTC_SOCKET_RECEIVE_EVENT } from '@/constants/rtcSocketEvents'; import { VITE_STUN_URL, VITE_TURN_CREDENTIAL, VITE_TURN_URL, VITE_TURN_USERNAME } from '@/constants/env'; -import getSocketURL from '@/apis/getSocketURL'; +import getSocketURL, { SOCKET_TYPE } from '@/apis/getSocketURL'; import useDataChannels from '@/stores/useDataChannels'; import useRoomConfigData from '@/stores/useRoomConfigData'; @@ -22,17 +23,19 @@ const useRTCConnection = (roomId: string, localStream: MediaStream) => { const { addCodeDataChannel, removeCodeDataChannel, addLanguageChannel, removeLanguageChannel } = useDataChannels(); const socketConnect = async () => { - const socketURL = await getSocketURL(roomId); - - socket = io(socketURL); - socket.on(RTC_SOCKET_RECEIVE_EVENT.ALL_USERS, onAllUser); - socket.on(RTC_SOCKET_RECEIVE_EVENT.OFFER, onOffer); - socket.on(RTC_SOCKET_RECEIVE_EVENT.ANSWER, onAnswer); - socket.on(RTC_SOCKET_RECEIVE_EVENT.CANDIDATE, onCandidate); - socket.on(RTC_SOCKET_RECEIVE_EVENT.USER_EXIT, onUserExit); - - socket.on('exception', throwConnectionError); - socket.on('error', throwSignalError); + const socketURL = await getSocketURL(SOCKET_TYPE.SIGNAL, roomId); + + const socketCallbacks = { + [RTC_SOCKET_RECEIVE_EVENT.ALL_USERS]: onAllUser, + [RTC_SOCKET_RECEIVE_EVENT.OFFER]: onOffer, + [RTC_SOCKET_RECEIVE_EVENT.ANSWER]: onAnswer, + [RTC_SOCKET_RECEIVE_EVENT.CANDIDATE]: onCandidate, + [RTC_SOCKET_RECEIVE_EVENT.USER_EXIT]: onUserExit, + exception: throwConnectionError, + error: throwSignalError, + }; + + socket = createSocket(socketURL, socketCallbacks); socket.connect(); diff --git a/frontEnd/src/utils/createSocket.ts b/frontEnd/src/utils/createSocket.ts new file mode 100644 index 0000000..73a8d62 --- /dev/null +++ b/frontEnd/src/utils/createSocket.ts @@ -0,0 +1,12 @@ +import { io } from 'socket.io-client/debug'; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type SocketCallback = Record; + +export default function createSocket(socketURL: string, socketCallback: SocketCallback) { + const socket = io(socketURL, { transports: ['websocket'] }); + Object.entries(socketCallback).forEach(([event, callback]) => { + socket.on(event, callback); + }); + + return socket; +} From 02feb8489a0b79f63091daed573ddf86742479dc Mon Sep 17 00:00:00 2001 From: d0422 Date: Wed, 13 Dec 2023 17:07:31 +0900 Subject: [PATCH 3/9] =?UTF-8?q?refactor:=20[FE]=20crdt=20yjs=20interface?= =?UTF-8?q?=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=A3=BC=EC=9E=85=EC=9D=84=20?= =?UTF-8?q?=ED=86=B5=ED=95=9C=20=EA=B2=B0=ED=95=A9=EB=8F=84=20=EB=82=AE?= =?UTF-8?q?=EC=B6=94=EA=B8=B0=20crdt=20yjs=20interface=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=ED=86=B5?= =?UTF-8?q?=ED=95=9C=20=EA=B2=B0=ED=95=A9=EB=8F=84=20=EB=82=AE=EC=B6=94?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/room/EditorSection.tsx | 13 +++-- .../src/components/room/editor/Editor.tsx | 11 ++-- .../src/components/room/editor/InputArea.tsx | 5 +- .../src/components/room/editor/LoadButton.tsx | 9 ++-- .../components/room/modal/CodeListModal.tsx | 9 ++-- frontEnd/src/contexts/crdt.tsx | 6 +-- frontEnd/src/services/crdt.ts | 51 +++++++++++++++++++ 7 files changed, 75 insertions(+), 29 deletions(-) create mode 100644 frontEnd/src/services/crdt.ts diff --git a/frontEnd/src/components/room/EditorSection.tsx b/frontEnd/src/components/room/EditorSection.tsx index cf78065..14b77bd 100644 --- a/frontEnd/src/components/room/EditorSection.tsx +++ b/frontEnd/src/components/room/EditorSection.tsx @@ -1,6 +1,5 @@ import { useContext, useEffect, useState } from 'react'; import { Socket, io } from 'socket.io-client/debug'; -import * as Y from 'yjs'; import { EDITOR_DEFAULT_LANGUAGE, EDITOR_LANGUAGE_TYPES } from '@/constants/editor'; import OutputArea from './editor/OutputArea'; import LoadButton from './editor/LoadButton'; @@ -46,15 +45,15 @@ export default function EditorSection({ defaultCode }: EditorSectionProps) { }, []); const handleRecieveCodeMessage = (event: MessageEvent) => { - const relPos = Y.createRelativePositionFromTypeIndex(crdt.getText('sharedText'), cursorPosition); + const relPos = crdt.getRelativePosition(cursorPosition); const update = new Uint8Array(event.data); - Y.applyUpdate(crdt, update); + crdt.update(update); - const updatedText = crdt.getText('sharedText').toString(); + const updatedText = crdt.toString(); setPlainCode(updatedText); - const pos = Y.createAbsolutePositionFromRelativePosition(relPos, crdt); + const pos = crdt.getAbsolutePosition(relPos); if (pos) setCursorPosition(pos.index); }; @@ -63,8 +62,8 @@ export default function EditorSection({ defaultCode }: EditorSectionProps) { }; const clearEditor = () => { - crdt.getText('sharedText').delete(0, crdt.getText('sharedText').toString().length); - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + crdt.delete(0, crdt.toString().length); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); }; const handleClear = () => { diff --git a/frontEnd/src/components/room/editor/Editor.tsx b/frontEnd/src/components/room/editor/Editor.tsx index e1c8be6..8a91750 100644 --- a/frontEnd/src/components/room/editor/Editor.tsx +++ b/frontEnd/src/components/room/editor/Editor.tsx @@ -1,5 +1,4 @@ import { useContext } from 'react'; -import * as Y from 'yjs'; import InputArea from './InputArea'; import LineNumber from './LineNumber'; import { EDITOR_TAB_SIZE } from '@/constants/editor'; @@ -38,13 +37,13 @@ export default function Editor({ plainCode, languageInfo, setPlainCode, cursorPo if (isOneLetter && isKorean) return; - crdt.getText('sharedText').insert(newCursor - Math.abs(changedLength), addedText); + crdt.insert(newCursor - Math.abs(changedLength), addedText); } else { const removedLength = Math.abs(changedLength); - crdt.getText('sharedText').delete(newCursor, removedLength); + crdt.delete(newCursor, removedLength); } - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); }; const handleClick = (event: React.MouseEvent) => { @@ -58,8 +57,8 @@ export default function Editor({ plainCode, languageInfo, setPlainCode, cursorPo if (event.key === 'Tab') { event.preventDefault(); - crdt.getText('sharedText').insert(selectionStart, ' '); - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + crdt.insert(selectionStart, ' '); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); setCursorPosition((prev) => prev + EDITOR_TAB_SIZE); setPlainCode((prev) => `${prev.slice(0, selectionStart)} ${prev.slice(selectionStart)}`); diff --git a/frontEnd/src/components/room/editor/InputArea.tsx b/frontEnd/src/components/room/editor/InputArea.tsx index 457e4e6..37fdb33 100644 --- a/frontEnd/src/components/room/editor/InputArea.tsx +++ b/frontEnd/src/components/room/editor/InputArea.tsx @@ -1,5 +1,4 @@ import { useEffect, useRef, useState, useContext } from 'react'; -import * as Y from 'yjs'; import dompurify from 'dompurify'; import highlightCode from '@/utils/highlightCode'; import { LanguageInfo } from '@/types/editor'; @@ -44,8 +43,8 @@ export default function InputArea({ plainCode, cursorPosition, handleChange, han }, [languageInfo]); const handleCompositionEnd = (event: React.CompositionEvent) => { - crdt.getText('sharedText').insert(cursorPosition - 1, event.data); - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + crdt.insert(cursorPosition - 1, event.data); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); }; return ( diff --git a/frontEnd/src/components/room/editor/LoadButton.tsx b/frontEnd/src/components/room/editor/LoadButton.tsx index 70156be..82f23be 100644 --- a/frontEnd/src/components/room/editor/LoadButton.tsx +++ b/frontEnd/src/components/room/editor/LoadButton.tsx @@ -1,6 +1,5 @@ import { useState, useEffect, useContext } from 'react'; import { useQuery } from '@tanstack/react-query'; -import * as Y from 'yjs'; import getUserCodes from '@/apis/getUserCodes'; import useModal from '@/hooks/useModal'; import { uploadLocalFile } from '@/utils/file'; @@ -66,11 +65,11 @@ export default function LoadButton({ plainCode, setPlainCode, setLanguageName, s setPlainCode(code); setLanguageName(languageName); - crdt.getText('sharedText').delete(0, crdt.getText('sharedText').toString().length); - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + crdt.delete(0, crdt.toString().length); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); - crdt.getText('sharedText').insert(0, code); - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + crdt.insert(0, code); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); }); }; diff --git a/frontEnd/src/components/room/modal/CodeListModal.tsx b/frontEnd/src/components/room/modal/CodeListModal.tsx index 4392aab..2aa80b2 100644 --- a/frontEnd/src/components/room/modal/CodeListModal.tsx +++ b/frontEnd/src/components/room/modal/CodeListModal.tsx @@ -1,5 +1,4 @@ import { useState, useContext } from 'react'; -import * as Y from 'yjs'; import { useQuery } from '@tanstack/react-query'; import { LoadCodeData } from '@/types/loadCodeData'; import CodeFileButton from './codeList/CodeFileButton'; @@ -47,11 +46,11 @@ export default function CodeListModal({ show({ warningString: '작업중이던 내용이 모두 지워집니다.', callback: () => { - crdt.getText('sharedText').delete(0, crdt.getText('sharedText').toString().length); - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + crdt.delete(0, crdt.toString().length); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); - crdt.getText('sharedText').insert(0, result.content); - sendMessageDataChannels(codeDataChannel, Y.encodeStateAsUpdate(crdt)); + crdt.insert(0, result.content); + sendMessageDataChannels(codeDataChannel, crdt.encodeData()); setPlainCode(result.content); setModifyId(result.id); diff --git a/frontEnd/src/contexts/crdt.tsx b/frontEnd/src/contexts/crdt.tsx index 95b4857..d8feacd 100644 --- a/frontEnd/src/contexts/crdt.tsx +++ b/frontEnd/src/contexts/crdt.tsx @@ -1,9 +1,9 @@ import React from 'react'; -import * as Y from 'yjs'; +import YjsCRDT, { CRDT } from '@/services/crdt'; -const crdt = new Y.Doc(); +const crdt = new YjsCRDT(); -export const CRDTContext = React.createContext(crdt); +export const CRDTContext = React.createContext(crdt); interface CRDTProviderProps { children: React.ReactNode; diff --git a/frontEnd/src/services/crdt.ts b/frontEnd/src/services/crdt.ts new file mode 100644 index 0000000..5bf7da7 --- /dev/null +++ b/frontEnd/src/services/crdt.ts @@ -0,0 +1,51 @@ +import * as Y from 'yjs'; + +const TEXT_DATA = 'sharedText'; + +interface RelativePositon extends Y.RelativePosition {} +interface AbsolutePosition extends Y.AbsolutePosition {} + +export interface CRDT { + encodeData: () => Uint8Array; + insert: (start: number, data: string) => void; + delete: (start: number, removeLength: number) => void; + update: (update: Uint8Array) => void; + getRelativePosition: (position: number) => RelativePositon; + getAbsolutePosition: (relativePositioni: RelativePositon) => AbsolutePosition | null; +} + +export default class YjsCRDT implements CRDT { + context: Y.Doc; + + constructor() { + this.context = new Y.Doc(); + } + + encodeData() { + return Y.encodeStateAsUpdate(this.context); + } + + insert(start: number, data: string) { + this.context.getText(TEXT_DATA).insert(start, data); + } + + delete(start: number, removeLength: number) { + this.context.getText(TEXT_DATA).delete(start, removeLength); + } + + update(update: Uint8Array) { + Y.applyUpdate(this.context, update); + } + + toString() { + return this.context.getText(TEXT_DATA).toString(); + } + + getRelativePosition(position: number): RelativePositon { + return Y.createRelativePositionFromTypeIndex(this.context.getText(TEXT_DATA), position); + } + + getAbsolutePosition(relativePosition: RelativePositon): AbsolutePosition | null { + return Y.createAbsolutePositionFromRelativePosition(relativePosition, this.context); + } +} From cd51668568ce5801b94849855cf010ddd573f704 Mon Sep 17 00:00:00 2001 From: HKLeeeee Date: Tue, 12 Dec 2023 19:55:47 +0900 Subject: [PATCH 4/9] =?UTF-8?q?fix:=20[BE]=20=ED=8A=B8=EB=9E=9C=EC=9E=AD?= =?UTF-8?q?=EC=85=98=20=EB=A7=A4=EB=8B=88=EC=A0=80=20logger=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backEnd/api/src/auth/auth.controller.ts | 6 ++++++ backEnd/api/src/common/transaction/transaction.service.ts | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/backEnd/api/src/auth/auth.controller.ts b/backEnd/api/src/auth/auth.controller.ts index 3e05f52..735a892 100644 --- a/backEnd/api/src/auth/auth.controller.ts +++ b/backEnd/api/src/auth/auth.controller.ts @@ -51,9 +51,12 @@ export class AuthController { const id_token: string = await this.googleService.getIDToken(code); const user: UserDto = await this.googleService.getUserInfo(id_token); let findUser = await this.userService.findUser(user); + this.logger.error(JSON.stringify(findUser)); if (findUser === null) { findUser = await this.userService.getUserAfterAddUser(user, 'google'); } + this.logger.error(JSON.stringify(findUser)); + const returnTo: string = await this.authService.login(findUser, res, req); return res.redirect(returnTo); } @@ -82,9 +85,12 @@ export class AuthController { const accessToken = await this.githubService.getGithubAccessToken(code); const user: UserDto = await this.githubService.getUserInfo(accessToken); let findUser = await this.userService.findUser(user); + this.logger.error(JSON.stringify(findUser)); if (findUser === null) { findUser = await this.userService.getUserAfterAddUser(user, 'github'); } + this.logger.error(JSON.stringify(findUser)); + const returnTo: string = await this.authService.login(findUser, res, req); return res.redirect(returnTo); diff --git a/backEnd/api/src/common/transaction/transaction.service.ts b/backEnd/api/src/common/transaction/transaction.service.ts index ee14f59..ea9c284 100644 --- a/backEnd/api/src/common/transaction/transaction.service.ts +++ b/backEnd/api/src/common/transaction/transaction.service.ts @@ -68,7 +68,6 @@ export class TransactionService implements OnModuleInit { return result; } catch (e) { await qr.rollbackTransaction(); - this.logger.error(e); throw new TransactionRollback(); } finally { await qr.release(); From 7cac05d4798850a65a9c583f16254793ebf6306f Mon Sep 17 00:00:00 2001 From: HKLeeeee Date: Wed, 13 Dec 2023 13:29:43 +0900 Subject: [PATCH 5/9] =?UTF-8?q?chore:=20[BE]=20=EA=B8=B0=EC=88=A0=EC=A0=81?= =?UTF-8?q?=20=EB=8F=84=EC=A0=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 30b7633..b6d74fd 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@

동료들과 함께 소통하며 알고리즘 학습을 할 수 있는 플랫폼

🗝️ KeyWords
#WebRTC #Socket #CRDT + +
@@ -94,8 +96,6 @@ Pub/Sub을 활용해 다중 서버 환경에서도 채팅을 할 수 있습니 - 429 Error 및 InMemory 용량부족 해결 과정 (16만건 처리에 걸리는 시간 64% 감소) - [도커 이미지 최적화](https://energetic-palm-634.notion.site/f35c15bc99a842a18ce095fa6bf1c806?v=efbb8ec67beb43b89792200fc1f3c9a1&pvs=4) - 도커 이미지 사이즈 85% 감소시킨 이야기 -- [서버에서 OAuth 처리하여 자원 보호하기](https://energetic-palm-634.notion.site/69f2e78273884a65b52c370debb83073?v=2b272ead31924af59732edbda24cef84&pvs=4) - - OAuth2.0을 도입하고 안전하게 자원을 관리하는 이야기 # 🔎 개발기 개발하면서 공부한 내용들과 고민 과정, 이유, 해결 방법을 기록했습니다. @@ -112,8 +112,8 @@ Pub/Sub을 활용해 다중 서버 환경에서도 채팅을 할 수 있습니 - [Transaction 관심사 분리하기](https://energetic-palm-634.notion.site/AsyncLocalStorage-Transaction-34f42523c0ec43f4b633eb7944c0b29d?pvs=4) - [SSL Termination을 통해 안전하게 HTTP 통신하기](https://energetic-palm-634.notion.site/SSL-Termination-HTTP-70c76949740f4452a2899fa1e617628a?pvs=4) - [Blue-Green으로 무중단 배포하기](https://energetic-palm-634.notion.site/57396ff1e3174251ba2c7487ab070a53?pvs=4) -- [Clove X 도입하기](https://www.notion.so/Clova-Studio-d990f41d3e814b708906e64fd4707a24?pvs=4) - +- [Clove X 도입하기](https://energetic-palm-634.notion.site/Clova-Studio-d990f41d3e814b708906e64fd4707a24?pvs=4) +- [서버에서 OAuth 처리하여 자원 보호하기](https://energetic-palm-634.notion.site/OAuth-2-0-2bc01496ac9c4ed6b0118642c887828d?pvs=4) [👉 더 많은 기술정리 보러가기](https://www.notion.so/f4562ec49e0245d2b6ef203588c031ea?v=fbfeb754b1a4471e8ffc174a45c64346&pvs=4) From bb19a3ae3504e710dd5e21f3392598d5701fd39a Mon Sep 17 00:00:00 2001 From: HKLeeeee Date: Thu, 14 Dec 2023 00:39:45 +0900 Subject: [PATCH 6/9] =?UTF-8?q?fix:=20[BE]=20Kill=20Code=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SIGINT 시그널로 종료했을 때 코드(130)으로 응답하는 경우도 존재함 --- backEnd/running/src/codes/codes.service.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/backEnd/running/src/codes/codes.service.ts b/backEnd/running/src/codes/codes.service.ts index b981028..a5cb7d1 100644 --- a/backEnd/running/src/codes/codes.service.ts +++ b/backEnd/running/src/codes/codes.service.ts @@ -25,7 +25,8 @@ export class CodesService { process.env.NODE_ENV === 'dev' ? path.join(__dirname, '..', 'tmp') : '/algoitni'; - private killSignal: NodeJS.Signals = 'SIGINT'; + private readonly killSignal: NodeJS.Signals = 'SIGINT'; + private readonly killCode: number = 130; private readonly timeOut = 5000; constructor() { if (!fs.existsSync(this.tempDir)) { @@ -40,7 +41,6 @@ export class CodesService { try { fs.writeFileSync(filePath, code); const { stdout, stderr } = await this.runCommand(filePaths, language); - this.logger.debug(`${stdout}, ${stderr}`); if (stderr) { throw new RunningException(stderr.trim()); } @@ -62,7 +62,6 @@ export class CodesService { language: supportLang, ): Promise { const commands = languageCommand(language, filePaths); - this.logger.debug(JSON.stringify(commands)); let command; if (commands.length > 1) { @@ -99,10 +98,11 @@ export class CodesService { this.logger.log(`child process exited with code ${code}, ${signal}`); clearTimeout(timer); const out = Buffer.concat(stdout).toString(); - const err = - signal === this.killSignal - ? Messages.TIMEOUT - : Buffer.concat(stderr).toString(); + let err = Buffer.concat(stderr).toString(); + this.logger.log(this.isTimeout(code, signal)); + if (this.isTimeout(code, signal)) { + err = Messages.TIMEOUT; + } resolve({ stdout: out, stderr: err }); }); } catch (e) { @@ -164,4 +164,8 @@ export class CodesService { path.join(this.tempDir, `${uuid}${distExtension}`), ]; } + + isTimeout(code: number, signal: NodeJS.Signals) { + return code === this.killCode || signal === this.killSignal; + } } From 10a41fc0dfc1bf628dfa6508f62a9e4f6ebf85f8 Mon Sep 17 00:00:00 2001 From: HKLeeeee Date: Thu, 14 Dec 2023 12:30:50 +0900 Subject: [PATCH 7/9] =?UTF-8?q?chore:=20README.md=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b6d74fd..326c488 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,7 @@

동료들과 함께 소통하며 알고리즘 학습을 할 수 있는 플랫폼

🗝️ KeyWords
-#WebRTC #Socket #CRDT - - +

#WebRTC #Socket #CRDT


@@ -126,8 +124,11 @@ Pub/Sub을 활용해 다중 서버 환경에서도 채팅을 할 수 있습니 | **Front-End** | **Front-End** | **Back-End** | **Back-End** | | [@HBSPS](https://github.com/HBSPS) | [@d0422](https://github.com/d0422) | [@HKLeeeee](https://github.com/HKLeeeee) | [@Gseungmin](https://github.com/Gseungmin) | +![AlgoITNi](https://github.com/boostcampwm2023/web05-AlgoITNi/assets/84272873/db73a539-bb3f-4cf0-af23-81e23adc6b17) + ## 우리가 일하는 방식 + - [그라운드 룰](https://energetic-palm-634.notion.site/1f2cbea527e341c7ad1c8fd84ed5104d?pvs=4) - [깃 컨벤션](https://energetic-palm-634.notion.site/Git-Convention-8563596644404eb49148a940773d2be8?pvs=4) - [게더타운 규칙](https://energetic-palm-634.notion.site/b3b67313c1f748e7b58abf99466b000b?pvs=4) From 8a8aea22355ad86f1882e3c0afa4f95f10b67ef3 Mon Sep 17 00:00:00 2001 From: HKLeeeee Date: Thu, 14 Dec 2023 12:40:59 +0900 Subject: [PATCH 8/9] =?UTF-8?q?refactor:=20[BE]=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EB=A1=9C=EA=B7=B8=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backEnd/running/src/codes/codes.service.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backEnd/running/src/codes/codes.service.ts b/backEnd/running/src/codes/codes.service.ts index a5cb7d1..5afa818 100644 --- a/backEnd/running/src/codes/codes.service.ts +++ b/backEnd/running/src/codes/codes.service.ts @@ -99,7 +99,6 @@ export class CodesService { clearTimeout(timer); const out = Buffer.concat(stdout).toString(); let err = Buffer.concat(stderr).toString(); - this.logger.log(this.isTimeout(code, signal)); if (this.isTimeout(code, signal)) { err = Messages.TIMEOUT; } From 37d3a4e13b035f9429a42efaa43db1f0a1d67fc0 Mon Sep 17 00:00:00 2001 From: Ji Seungmin Date: Thu, 14 Dec 2023 14:58:20 +0900 Subject: [PATCH 9/9] =?UTF-8?q?fix:=20[BE]=20AI=20=EC=B1=84=ED=8C=85?= =?UTF-8?q?=EC=8B=9C=20room=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=A0=95?= =?UTF-8?q?=EB=B3=B4=EB=8F=84=20pub?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backEnd/chat/src/chat/chat.gateway.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backEnd/chat/src/chat/chat.gateway.ts b/backEnd/chat/src/chat/chat.gateway.ts index 31af41e..8553ad5 100644 --- a/backEnd/chat/src/chat/chat.gateway.ts +++ b/backEnd/chat/src/chat/chat.gateway.ts @@ -120,7 +120,7 @@ export class ChatGateway implements OnGatewayConnection, OnGatewayDisconnect { try { await this.publisherClient.publish( SOCKET.REDIS_CHAT_CHANEL, - JSON.stringify({ using: true }), + JSON.stringify({ room: room, using: true }), ); const llmMessageDto: LLMMessageDto = await this.processAIResponse(