현재는 클라이언트와 서버의 연동을 확인하기 위해 작업한 CRDT 문서들을 서버에 인스턴스로 저장하고 있다
이제 우리는 워크스페이스와 페이지들을 MongoDB에 직접 저장해야 한다
데이터 문자열로 뽑는 방법
serialize()
메서드가 있다serialize()
한 결과를 JSON.stringify()
로 출력하면 된다console.log(JSON.stringify(workspace.serialize(), null, 2));
실제 출력값 (주의! 797줄임 (노션은 코드 블럭이 500줄이 넘어가면 syntax highlighting이 적용되지 않는다..))
@Injectable()
export class workSpaceService implements OnModuleInit {
private workspaces: Map<string, CRDTWorkSpace>;
private server: Server;
constructor(@InjectModel(Workspace.name) private workspaceModel: Model<WorkspaceDocument>) {}
// Socket.IO 서버 인스턴스 설정
setServer(server: Server) {
this.server = server;
}
async onModuleInit() {
this.workspaces = new Map();
// 게스트 워크스페이스 초기화
const guestWorkspace = new CRDTWorkSpace("guest", []);
this.workspaces.set("guest", guestWorkspace);
// 주기적으로 인메모리 DB 정리 작업 실행
setInterval(
() => {
this.cleanupWorkspaces();
},
process.env.NODE_ENV === "production" ? 1 * 60 * 60 * 1000 : 30 * 1000,
);
}
private async cleanupWorkspaces() {
try {
for (const [roomId, workspace] of this.workspaces.entries()) {
// guest workspace는 제외
if (roomId === "guest") continue;
// room의 연결된 클라이언트 수 확인
const room = this.server.sockets.adapter.rooms.get(roomId);
const clientCount = room ? room.size : 0;
if (clientCount === 0) {
// DB에 workspace 상태 저장
await this.updateWorkspaceInDB(roomId, workspace);
// Map에서 제거
this.workspaces.delete(roomId);
console.log(`Workspace ${roomId} has been saved to DB and removed from memory`);
}
}
console.log("Workspace cleanup completed, current workspaces: ", this.workspaces.keys());
} catch (error) {
console.error("Error during workspace cleanup: ", error);
}
}