현재는 클라이언트와 서버의 연동을 확인하기 위해 작업한 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);
}
}