Frontend → API 서버
API서버 → 채점 서버
removeOnComplete
와 removeOnFail
을 true로 설정해준다.await this.scoringQueue.add(
{
data: newSubmission.id,
},
{
jobId: newSubmission.id,
removeOnComplete: true,
removeOnFail: true,
},
);
채점 서버는 큐에 데이터가 들어오면(publish) 하나를 받는다(subscribe). 이후 채점 중이지 않은 도커 컨테이너 하나를 할당하여 비동기로 채점을 시작한다.
// 비동기 채점 promise
const promise = new Promise(async (resolve) => {
await this.scoringService.createSubmission(job.data.data, containerIndex);
this.isReadyContainer.push(containerIndex);
resolve(null);
}).then(() => {
return job.data.data;
}) as MyPromise;
promise.submissionId = job.data.data;
// 배열에 저장
this.promises.push(promise);
이후 남은 컨테이너가 없으면 ( === promise배열의 길이가 총 도커 컨테이너 개수와 같다면) 현재 진행중인 채점 중 하나의 채점이 종료될 때 까지 await로 대기한다.
Promise.race
로 채점이 먼저 끝나는 도커 컨테이너의 id를 받아 promises 배열에서 해당 컨테이너를 빼내고 채점 요청을 대기할 수 있도록 만든다.if (this.promises.length === 3) {
const idx = await Promise.race(this.promises);
this.promises = this.promises.filter((val) => val.submissionId !== idx);
}
채점 서버는 API 서버로부터 요청을 받는 게 아니기 때문에 위 작업만 수행하면 된다.
채점 서버 → API 서버
위와 동일한 구조에서 기존의 채점 서버와 동일한 사양의 채점 서버를 한 대 더 늘렸다.
⇒ 총 6대의 도커 컨테이너에서 채점 진행
채점 서버가 한 대 증설된 것 이외에는 위와 동일하다.