Superlifter sub field resolver exception hang fix #2
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
문제
Handle thrown exception and deliver lacinia result appropriately #1 이후 superlifter 리졸버에서 exception이 난 경우 (
리졸버 함수에서 with-superlifter에 넘긴 promise(promesa)
가 reject됨) prom/catch로 잡아 lacinia-promise(ResolverResultPromise)로 error를 deliver함으로써 핸들링할 수 있었습니다.라시니아에서 리졸빙할 때 object를 리졸빙한 결과를 deliver받고, callback function으로 하위 필드를 연쇄로 리졸빙합니다.
superlifter 리졸버에서 exception이 나지 않은 경우
리졸버 함수에서 with-superlifter에 넘긴 promise(promesa)
가 정상적으로 resolve되므로 prom/then을 거쳐 lacinia-promise에 error 없이 resolved-value가 deliver됩니다.이 때
하위 필드 리졸버
에서 에러가 나는 경우 2.에서 언급한 callback function에서 exception이 발생합니다. 이렇게 되면 기존 ->lacinia-promise
unwrap
두 함수를 거쳤을 때 prom/then에서 에러가 날 경우 prom/catch로 잡게 되고 이미 resolved-value를 한 번 deliver했던 lacinia-promise에 error를 deliver하려 시도합니다.이 때
lacinia-promise
에 두 번 deliver했기에 Exception이 발생하고 이 deliver 과정은promesa
안에서 했기 때문에 이 때 발생한 Exception은 promesa 안에 갇히게 되고 이는 결국 리졸버를 무한 대기 상태로 빠지게 만듭니다.해결 방안
근본적으로 차이가 있는
promesa
와lacinia-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하는 것을 방지합니다.성능 테스트
- 현 PR 버전 superlifter
- 테스트 쿼리
representativeWeight 필드를 리졸빙할 때 superlifter를 쓰는데 아무래도 deref를 하다보니 성능이 유의미하게 느려집니다..
deref이 아닌 다른 해결 방안을 찾아야 할 듯 합니다.