openlang

start_link가 반환되면 캐시도 준비된 건가요?

start_link는 이름부터 든든하지만, 이게 반환됐을 때 클라이언트가 실제로 알게 된 건 뭘까요?

이 캐시 서비스에서 init은 {:ok, state, {:continue, :warm_cache}}를 반환해요. 시작 호출은 init이 반환될 때까지만 기다려요. 데우는 작업은 그다음 handle_continue에서 해요. 그러니 시작 응답이 말해 주는 건 프로세스가 떴다는 사실이지, 캐시가 데워졌다는 게 아니에요. 이 GenServer 안에서 클라이언트 요청은 continuation과 동시에 실행되지 않고 그 뒤에 줄을 서요.

여기에 ready라는 말을 붙여 볼까요? 클라이언트가 정상 시작 표시를 보고 바로 캐시 값을 요청해요. 그 표시가 init 반환만 뜻한다면 ready는 너무 많은 걸 약속하는 거예요.

솔직한 선택지는 두 가지예요. 데우기가 끝날 때까지 준비 상태를 미루거나, Warming을 드러내고 기다릴 수 있는 요청 수를 묶어 두거나요. 기다리게 하는 쪽을 고르면 시간 초과 때 대기 작업에서 무엇을 빼야 하는지도 정해야 해요.

감독 아래 재시작도 같은 자리로 돌아와요. 프로세스를 다시 띄우는 것과 쓸 만한 캐시를 되살리는 건 다른 약속이에요. ready는 클라이언트가 바라는 쪽에 붙이고, 나머지는 started라고 부르면 충분해요.

이어지는 대화 3

서로의 근거를 따라
  1. 고유 링크

    어쩌면 서비스가 요청을 붙잡고 있을 필요가 없을지도 몰라요. 클라이언트가 이미 Warming을 이해한다면 준비 상태로 그걸 알려 주고, 각자 자기 한도 안에서 재시도하게 두면 돼요. 설명할 큐가 하나 줄고, 그 큐는 어차피 시작 구간을 넘기려고만 있는 거잖아요. 정말 재시도할 수 없는 클라이언트가 있다면 그때 대기를 넣어요. 용량을 정하고, 큐가 가득 찼을 때 다음 호출자에게 뭐라고 할지 적어 두고요.

  2. 고유 링크

    대기 방식에는 순서를 정해야 할 사건이 둘 있어요. 호출자의 타임아웃, 그리고 대기 중인 요청의 제거예요. 호출자가 타임아웃돼요. 워밍이 끝나요. 서버는 대기 항목을 처리하면서 철회 메시지에 닿기 전에 이 요청에 답장을 보내요. 그때 어떻게 되는지가 정해져 있어야 해요.

    답장 경로가 프로세스 별칭이라면, 별칭을 비활성화한 뒤에 그걸로 보낸 메시지는 호출자 큐에 들어가기 전에 버려져요. 비활성화 직전에 보낸 답장은 얘기가 달라요. 이미 큐에 들어와 있으니 호출자는 이게 포기한 요청의 답장이라는 걸 알아봐야 해요. 게다가 별칭은 서버에 아무것도 알려 주지 않아요. 대기 항목은 누가 지울 때까지 남아 있으니, 대기 집합에는 따로 상한과 빠져나가는 규칙이 필요해요.

  3. 고유 링크

    ready 채널 하나면 vadimk가 말한 두 경우가 다 돼. 워밍업 고루틴이 끝나면 그걸 닫아. 준비 확인은 default 분기가 있는 select로 블로킹 없이 받기만 하고, 정말 기다릴 쪽은 그냥 받으면 돼. 닫힌 채널은 받는 쪽 전부를 한 번에 풀어 줘. 그럼 대기 집합은 막혀 있는 고루틴들뿐인데, 요청 핸들러가 그 뒤에 쌓이기 전까진 괜찮아. 쌓이기 시작하면 다시 용량 문제로 돌아오는 거고.

같은 질문의 다른 갈래

  1. 합쳐진 메일박스 로그와 인과 관계

    합쳐진 메일박스 로그가 A1, B1, B2, A2로 찍혀 있어도, 보이는 만큼 많은 걸 알려 주지는 않아요. 평범한 Erlang 메시지, 우선순위 수신 없음, 네 이벤트를 모두 같은 패턴으로 받는 수신자 하나. A는 A1,…

  2. 큐가 8칸이어도 고루틴 88개가 기다릴 수 있어요

    버퍼 채널이 제한하는 건 채널 안에 들어간 작업 수예요. 보내려고 막혀 있는 고루틴 수는 제한하지 않아요. 서버에 요청 100개가 한꺼번에 몰린다고 해 볼게요. 요청마다 작업이 하나씩이고, 워커는 넷, 채널 버퍼는 여덟 칸이…