openlang

늦게 온 call 응답을 두고 엇갈리는 Erlang 문서와 Elixir 문서

타임아웃 난 call을 두고 두 문서가 서로 다른 얘기를 해요. gen_server 레퍼런스는 OTP 24부터 call이 프로세스 별칭을 거치기 때문에 타임아웃 뒤에 도착한 답장은 받지 않는다고 해요. Elixir 문서의 GenServer.call/3 페이지는 아직도 종료를 잡은 뒤 늦게 온 두 원소 튜플은 버리라고 하고요. 둘 다 같은 VM, 같은 gen 모듈 위에 있어요. 저는 Elixir 문단이 남은 흔적이라고 읽어요. 어느 쪽이든 서버는 일을 해 버렸고, 두 페이지 다 그 얘기를 앞에 두지 않아요.

이어지는 대화 3

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

    저는 문서끼리 어긋나는 걸 좋아해요. 고치자고 말하기가 제일 쉬운 종류거든요. 그래도 Elixir 문단의 절반은 남기고 싶어요. 쓰레기 튜플을 버리라는 조언은 현재 OTP의 GenServer.call에는 낡은 얘기예요. 정말 쓸모 있는 건 그 앞 문장, 호출자는 종료되는데 서버는 여전히 일하고 있을 수 있다는 부분이에요. 별칭이 생겨도 그건 전혀 안 바뀌어요.

    그래서 문서용 규칙은 두 갈래예요. call 자체에 대한 쓰레기 메시지 조언은 빼요. 서버가 어쨌든 일을 끝낸다는 부분은 남기고, 아마 더 늘려야 해요. {:ok, 1}을 보여 주는 doctest는 그걸 절대 알려 주지 않으니까요.

  2. 고유 링크

    저는 잡는 쪽을 더 들여다보겠어요. 타임아웃 종료를 잡는 코드는 대개 재시도하려고 그래요. 첫 요청은 아직 서버 큐에 있거나 이미 실행 중이라서, 재시도는 같은 작업을 한 번 더 돌려요. 별칭은 첫 답장을 감출 뿐이고, 첫 효과는 어차피 일어났어요.

    읽기만 하는 작업이면 괜찮아요. 쓰는 작업이면 재시도에 서버가 확인할 수 있는 요청 식별자가 있어야 하고, 아니면 호출자가 재시도하지 말고 종료를 그냥 받아들여야 해요.

  3. 고유 링크

    현재 OTP에서는 Erlang 쪽 설명이 맞아요. 서버가 call이 허용하는 시간보다 오래 자고 나서 답해요. 호출자는 GenServer.call을 catch :exit, _로 감싸고 그다음 flush()를 불러요. 아무것도 없어요. 늦은 답장은 끝내 안 나타나요.

    비용이 드는 건 patchkit 님이 신경 쓰는 순서예요. 첫 번째를 잡자마자 두 번째 call을 보내면, 서버는 첫 요청을 끝까지 처리하고 나서 두 번째를 처리하고 부수 효과도 둘 다 일어나요.

같은 질문의 다른 갈래

  1. swap! 함수 안의 println

    swap! 문서에는 함수가 여러 번 호출될 수 있으니 부수 효과가 없어야 한다고 적혀 있다. 그런데 실제 코드에는 그 안에서 로그를 찍는 경우가 여전히 있다. 아톰의 값은 어떤 경우에도 맞다. 커밋되는 시도는 하나뿐이기 때문…

  2. Isolate.run이 Loader를 통째로 데려갔어요

    큰 JSON 디코딩을 Isolate.run으로 메인 isolate 밖에 빼 봤는데, 빨라지기는커녕 보낼 수 없는 객체라는 오류가 났어요. 디코딩 자체는 문제가 없었고 클로저가 문제였어요. _decode가 인스턴스 메서드라서…

    답글 2dart
  3. 컨텍스트 취소 뒤 결과 전송에서 멈춘 워커들

    단순한 건데 생각보다 오래 붙잡고 있었어요. 워커 여덟 개짜리 풀이 jobs에서 작업을 읽고, 버퍼 없는 results에 결과를 써요. 소비자는 results를 루프로 읽다가 첫 에러가 나면 ctx.Done()으로 돌아가요.…

    답글 8go