Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Superlifter sub field resolver exception hang fix #2

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

duddlf23
Copy link

@duddlf23 duddlf23 commented Aug 12, 2022

문제

  1. Handle thrown exception and deliver lacinia result appropriately #1 이후 superlifter 리졸버에서 exception이 난 경우 (리졸버 함수에서 with-superlifter에 넘긴 promise(promesa)가 reject됨) prom/catch로 잡아 lacinia-promise(ResolverResultPromise)로 error를 deliver함으로써 핸들링할 수 있었습니다.

  2. 라시니아에서 리졸빙할 때 object를 리졸빙한 결과를 deliver받고, callback function으로 하위 필드를 연쇄로 리졸빙합니다.

  3. superlifter 리졸버에서 exception이 나지 않은 경우 리졸버 함수에서 with-superlifter에 넘긴 promise(promesa)가 정상적으로 resolve되므로 prom/then을 거쳐 lacinia-promise에 error 없이 resolved-value가 deliver됩니다.

  4. 이 때 하위 필드 리졸버에서 에러가 나는 경우 2.에서 언급한 callback function에서 exception이 발생합니다. 이렇게 되면 기존 ->lacinia-promise unwrap 두 함수를 거쳤을 때 prom/then에서 에러가 날 경우 prom/catch로 잡게 되고 이미 resolved-value를 한 번 deliver했던 lacinia-promise에 error를 deliver하려 시도합니다.

  5. 이 때 lacinia-promise에 두 번 deliver했기에 Exception이 발생하고 이 deliver 과정은 promesa 안에서 했기 때문에 이 때 발생한 Exception은 promesa 안에 갇히게 되고 이는 결국 리졸버를 무한 대기 상태로 빠지게 만듭니다.

해결 방안

  • 근본적으로 차이가 있는 promesalacinia-promise(ResolverResultPromise) 둘을 함께 사용하다보니 lacinia-promise deliver 과정에서 발생한 Exception이 promesa 안에 갇히게 되는 등 호환성이 부족합니다.

  • ->lacinia-promise에서 deref을 해 promesa와 lacinia-promis의 레이어를 완전히 분리합니다. 이 때 promesa를 이용한 async가 깨지게 되는데 with-superlifter를 사용하는 리졸버 레벨에서만 sync로 동작하고 여전히 하위 필드 리졸빙이나 wrap-resolver-result 같은 나머지 동작들은 lacinia-promise 안에서 async로 동작합니다. - 성능 테스트가 필요합니다.

  • unwrap 함수를 prom/handle로 리팩토링해 then이나 catch 중 하나만 실행하게 만들어 lacinia-promise에 두 번 deliver하는 것을 방지합니다.

성능 테스트

  • 기존 superlifter

image

- 현 PR 버전 superlifter

image

- 테스트 쿼리
{
  products(first: 50, orderBy: [{statusPriority: ASC}, {price: ASC_NULLS_LAST}, {updatedAt: DESC}], type:[MATCHING]) {
    edges {
      node {
        status
        number
        displayName
        category {
          id
        }
        __typename
        ... on MatchingProduct {
          pricePerKg
          representativeWeight
        }
      }
      cursor
    }
  }
}

representativeWeight 필드를 리졸빙할 때 superlifter를 쓰는데 아무래도 deref를 하다보니 성능이 유의미하게 느려집니다..

deref이 아닌 다른 해결 방안을 찾아야 할 듯 합니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant