openlang

fetch 하나가 실패할 때의 asyncio.TaskGroup

언어별 동시성 비교는 보통 문법에서 시작하죠. 저는 뭔가 실패했을 때 이 계산에 무엇이 필요한지부터 보고 싶어요.

작은 Python 애플리케이션이 측정값과 가중치를 동시에 가져와서 하나의 점수로 합쳐요. 한쪽 가져오기가 예외를 던졌는데 다른 쪽은 아직 돌고 있어요.

첫 번째 단계예요. 가져오기 하나가 실패하면 계산 전체를 쓸 수 없게 되나요? 그렇다면 asyncio.TaskGroup이 맞아요. 멤버 하나가 CancelledError가 아닌 예외로 실패하면 그룹은 나머지 멤버를 취소하고, 종료를 마치기 전에 태스크들을 기다려요. 놓치기 쉬운 점이 하나 있어요. 코루틴 함수를 호출하기만 해서는 아무것도 예약되지 않으니, 가져오기를 그룹 안의 태스크로 만들어야 해요.

두 번째 단계는 다른 결정이에요. 두 태스크가 정상적으로 반환했는데 가중치가 쓸 만하지 않아요. 수집은 끝났어요. 이제 어떤 값이 왔는지 살펴봐요. 입력을 거부할지, 다시 요청할지, 부분 결과를 낼지는 TaskGroup이 정해 주지 않아요.

세 번째 단계는 호출자 쪽 취소예요. 가져오기의 정리 코드는 CancelledError를 그대로 전파해야 해요. 삼켜 버리면 그룹의 취소 동작이 흐트러질 수 있어요.

이 애플리케이션이라면 답은 TaskGroup이에요. 어느 쪽이 실패하든 합친 요청은 끝나야 하고, 스코프는 멤버들을 기다려야 하니까요. 반환된 데이터 검증은 그다음, 계산 전에 해요. 다른 언어와 비교할 때 지켜야 할 구체적인 기준이 바로 이거예요.

이어지는 대화 4

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

    두 번째 지점에서 작은 실험을 해 봤어요. 측정값은 그대로 두고, 가중치 조회가 예외 대신 []를 돌려주게 바꿔요. TaskGroup 입장에서는 둘 다 정상 반환이에요. 취소도 없고 전파되는 것도 없으니, 결합 단계가 빈 리스트로 무엇을 하든 그게 결과가 돼요.

    점수가 가중 평균이라면 여기서부터 재밌어져요. 파이썬에서는 빈 가중치 합으로 나누면 ZeroDivisionError가 나요. 줄리아에서는 빈 Float64 벡터로 같은 계산을 하면 조용히 NaN이 나오고요.

    이번엔 측정값도 비워 볼까요? 빈 컬렉션 두 개는 정말로 할 일이 없는 정상 계산일 수도 있고, 꼭 필요한 입력이 소리 없이 빠진 것일 수도 있어요. 태스크 그룹은 이 둘을 구별하지 못해요. 그러니 입력마다 비어 있다는 게 무슨 뜻인지 먼저 정하고, 어떤 부적합한 결과를 실패로 올릴지는 그다음에 고르는 게 순서 같아요.

  2. 고유 링크

    조회는 두 개뿐이에요. 작업 수가 이미 정해져 있으니 여기에 워커 풀을 두면 형식만 늘어요.

    따라가 볼 건 아직 돌고 있는 조회예요. 옆 태스크가 예외를 내면 그룹이 이 조회를 취소하고, 그다음에도 기다려요. 취소는 요청일 뿐이에요. 요청이 닿는 순간 조회는 소켓을 읽는 중일 수도, 정리 블록 안에 있을 수도 있어요. 태스크가 실제로 끝나야 끝난 거예요. Go의 errgroup.WithContext도 모양이 같아요. 첫 오류에서 컨텍스트가 취소되고, Wait는 그래도 모든 고루틴이 돌아올 때까지 막혀 있어요.

    그래서 제가 보는 요구 사항은 한 줄이에요. 멤버가 하나라도 돌고 있으면 결합된 요청은 스코프를 떠나지 않아요. 이미 도착한 측정값을 쓰고 싶다면, 그룹이 실패를 알린 뒤에도 써도 되는지 적어 두세요. 지금은 그런 말이 어디에도 없어요.

  3. 고유 링크

    단어는 같아도 제어를 넘기는 방식이 달라요. Lua 5.4에서 coroutine.create로 만든 코루틴은 아직 한 줄도 실행하지 않은 상태예요. 호스트가 resume을 불러요. 코루틴은 yield할 때까지 돌아요. 그리고 누가 다시 재개할 때까지 거기서 기다려요.

    다음에는 누가 재개하나요? 호스트가 짠 코드예요. 형제 코루틴을 기다려 주거나 대신 취소해 주는 장치는 없어요. 그러니 각 언어의 기능을 이 계산에서 TaskGroup이 하는 일, 그러니까 멤버를 기다리고 실패하면 취소하는 일과 맞대어 보세요. 같은 단어가 그 성질까지 옮겨 준다고 보면 안 돼요.

같은 질문의 다른 갈래

  1. 설정 언어를 바꾼다고 드리프트가 고쳐지지는 않는다

    HCL 파일을 범용 언어로 갈아타자는 주장은 보통 반복문과 함수를 내세운다. 일리가 있을 때도 있다. 그런데 그 주장에 늘 따라붙는 불만이 드리프트이고, 드리프트는 언어 문제가 아니다. HCL은 구조화된 설정 문법이다. 블록…

    답글 4hcl