Skip to content

Comments

INTERNAL: read while PIPE_ERROR received in the pipe operation#839

Merged
jhpark816 merged 1 commit intonaver:developfrom
oliviarla:pipeend
Jan 9, 2025
Merged

INTERNAL: read while PIPE_ERROR received in the pipe operation#839
jhpark816 merged 1 commit intonaver:developfrom
oliviarla:pipeend

Conversation

@oliviarla
Copy link
Collaborator

@oliviarla oliviarla commented Nov 15, 2024

🔗 Related Issue

⌨️ What I did

  • 본 PR에서는 파이프 연산 요청에서 에러(CLIENT_ERROR, ERROR, SERVER_ERROR) 응답 시 PIPE_ERROR를 끝까지 읽도록 변경한다.
  • 기존에는 에러 응답 시 즉시 예외를 생성해 던졌기 때문에 PIPE_ERROR를 읽지 않았다.
  • 동기 파이프 연산 처리 시 에러로 인해 수행되지 않은 연산을 failedResult를 통해 알려야 하는데, 기존 형태에서는 에러 시 바로 예외를 던지므로, 에러 발생으로 인해 수행되지 않은 연산에 대해 callback.gotStatus()를 호출할 수 없다.
  • 따라서 PIPE_ERROR를 읽도록 변경만 해두고, 수행되지 않은 연산에 대한 gotStatus() 호출은 INTERNAL: make piped insert operations process synchronously #795 에 추가하도록 한다.

@jhpark816 jhpark816 removed their request for review November 15, 2024 11:17
@jhpark816
Copy link
Collaborator

@uhm0311 먼저 리뷰하면 됩니다.

Copy link
Collaborator

@uhm0311 uhm0311 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1차 질문입니다.

Copy link
Collaborator

@uhm0311 uhm0311 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2차, 리뷰 의견과 질문입니다.

@oliviarla oliviarla force-pushed the pipeend branch 2 times, most recently from faec8fa to 20cf3d9 Compare November 19, 2024 06:48
@oliviarla oliviarla self-assigned this Nov 19, 2024
Copy link
Collaborator

@uhm0311 uhm0311 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3차 리뷰 의견입니다.

@jhpark816
Copy link
Collaborator

@oliviarla @uhm0311
CompositeException의 printCallStack() 관련 PR은 merge 되었습니다.

@oliviarla oliviarla force-pushed the pipeend branch 2 times, most recently from 5493230 to 466ff60 Compare November 26, 2024 10:28
@oliviarla
Copy link
Collaborator Author

@uhm0311 @jhpark816
현재 END/PIPE_ERROR가 오지 않아 예외가 발생한다면 아래와 같이 로깅이 되는데요, 이 때 어떤 에러가 어떤 연산에서 났는지 확인하기 어렵다는 단점이 있긴 합니다만, 별다른 해결 방안은 없는 것 같습니다. (pipe operation에서 내부적으로 사용하고 있는 index 정보를 같이 로깅하면 어떨까 생각해보았는데, 메서드 인자 등을 로그로 알기 어려우므로 index를 알더라도 쓸모없는 정보가 될 것 같습니다.)

OperationException: SERVER: Multiple exceptions (3) reported: SERVER_ERROR out of memory @ testnode 0.0.0.0/0.0.0.0:11211, CLIENT_ERROR too large value @ testnode 0.0.0.0/0.0.0.0:11211, END|PIPE_ERROR not received

@oliviarla oliviarla force-pushed the pipeend branch 2 times, most recently from 00d28cd to 63fac49 Compare November 26, 2024 10:53
@oliviarla oliviarla requested a review from uhm0311 November 28, 2024 01:30
Copy link
Collaborator

@uhm0311 uhm0311 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4차 리뷰 의견입니다.

@oliviarla oliviarla force-pushed the pipeend branch 2 times, most recently from a752f86 to 7bf52e7 Compare November 28, 2024 03:09
uhm0311
uhm0311 previously approved these changes Nov 28, 2024
@oliviarla oliviarla requested a review from jhpark816 November 28, 2024 08:23
@oliviarla
Copy link
Collaborator Author

@jhpark816 리뷰 부탁드립니다.

@jhpark816
Copy link
Collaborator

@oliviarla 리뷰 진행 중입니다.

Copy link
Collaborator

@jhpark816 jhpark816 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

일부 리뷰

Copy link
Collaborator

@jhpark816 jhpark816 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 완료,
복잡한 이슈네요.

@oliviarla
Copy link
Collaborator Author

oliviarla commented Dec 9, 2024

@jhpark816 @uhm0311
현재 상황에서 수정할 부분을 대략 정리해봤습니다. 코드로 작성하기 전에 검토 먼저 부탁드립니다.

  • OperationImpl#readFromBuffer의 로직 변경
    • isPipeOperation()가 true이고 첫 번째 응답이 RESPONSE <count> 라면, 이후에는 classifyError()를 거치지 않고 handleLine()에서
    • CLIENT_ERROR, SERVER_ERROR, ERROR를 읽고 gotStatus 콜백 메서드에 넘긴다.
  • handleLine(String line)의 로직 변경
    • END가 왔을 때에는 Operation COMPLETE 상태로 변경
    • PIPE_ERROR가 왔을 때에는 Operation COMPLETE 상태로 변경하고, operation에 예외를 추가해 reconnect되도록 하고, hasErrored가 true를 반환하도록 한다.
  • getFailedResult() 메서드를 pipe 관련 Future에 추가
    • 에러와 상관없이 failedResult 결과를 조회할 수 있도록 한다.

@jhpark816
Copy link
Collaborator

@oliviarla

isPipeOperation()가 true이면 classifyError()를 거치지 않고 handleLine()에서 CLIENT_ERROR, SERVER_ERROR, ERROR를 gotStatus 콜백 메서드에 넘긴다.

  • pipe 요청에 대해 ERROR 등이 바로 나올 수 있으며, 이 경우는 classifyError()를 수행해야 합니다.
  • pipe 요청에 대해 RESPONSE <count>\r\n 응답이 온 이후에는 classifyError()를 거치지 않아야 합니다.

END가 오면 리다이렉트한 후 Operation COMPLETE 상태로 변경
PIPE_ERROR가 오면 리다이렉트한 후 Operation COMPLETE 상태로 변경

리다이렉트한다는 것이 어떤 의미인가요?

future.get()의 로직 변경
hasErrored 일 때에는 exception을 던지지 않는다.

result가 있는 지에 따라 판단해야 할 지 ? 정도의 느낌이 듭니다.

Copy link
Collaborator

@uhm0311 uhm0311 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

변경 내역을 다 따라가지 못해서 질문 남깁니다.

@oliviarla oliviarla changed the title INTERNAL: read while END/PIPE_ERROR received in the pipe operation INTERNAL: read while PIPE_ERROR received in the pipe operation Dec 27, 2024
@oliviarla
Copy link
Collaborator Author

@uhm0311 리뷰 완료되셨을까요?

@uhm0311
Copy link
Collaborator

uhm0311 commented Jan 2, 2025

@oliviarla

진행 중입니다.

uhm0311
uhm0311 previously approved these changes Jan 2, 2025
@oliviarla oliviarla requested a review from jhpark816 January 3, 2025 02:03
Copy link
Collaborator

@jhpark816 jhpark816 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 완료

Copy link
Collaborator

@jhpark816 jhpark816 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 완료

protected void handleError(OperationErrorType eType, String line) throws IOException {
getLogger().error("Error: %s by %s", line, this);
exception = createException(eType, line);
if (count == 0 && index == 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CollectionPipedInsertOperationImpl 클래스에서
명시적으로 index를 0으로 초기화해 두는 것처럼
명시적으로 count도 0으로 초기화해 두면 좋겠습니다.

그리고, count == 0 조건만 있어야 하고, index == 0 조건은 빠져야 합니다.
아래 경우에 index == 0이기 때문입니다.

RESPONSE 1
CLIENT_ERROR ...
PIPE_ERROR

그리고, switchover와 redirect하는 경우를 고려한다면,
count == 0 조건만 있으면 충분한 지 간단히 설명해 주세요.

Copy link
Collaborator Author

@oliviarla oliviarla Jan 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switchover / redirect하는 경우 count 값이 초기화되도록 수정했습니다. (count 값은 현재 사용하고 있지 않기 때문에 최신 RESPONSE <count> 정보를 저장해두는 용도로만 사용해도 됩니다.)
이를 통해 첫 번째 응답으로 ERROR가 올 경우 바로 예외를 던지고, RESPONSE 이후에 ERROR가 올 경우 PIPE_ERROR를 읽도록 합니다.

@oliviarla
Copy link
Collaborator Author

리뷰 모두 반영했습니다.

uhm0311
uhm0311 previously approved these changes Jan 8, 2025
Copy link
Collaborator

@jhpark816 jhpark816 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰 완료

import net.spy.memcached.ops.OperationType;
import net.spy.memcached.ops.StatusCode;

import static net.spy.memcached.ops.OperationErrorType.CLIENT;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

질문입니다.

  • import static에서 static은 어떤 의미가 되나요?
  • 기존 코드에서도 CLIENT가 사용되고 있습니다. 이미 관련된 import가 존재하지 않는 지 ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static import를 하게 되면 해당 변수나 상수를 사용할 때 정의된 클래스 이름을 명시하지 않고 사용할 수 있습니다.
예를 들어 일반 import 시에는 OperationErrorType.CLIENT로 사용해야 하지만, static import 시에는 CLIENT로 사용할 수 있는데, 기존에는 switch문을 사용해서 static import할 필요가 없었습니다.

다만 CLIENT만 사용하는 것보단 OperationErrorType.CLIENT 사용하는 것이 더 이해가 쉬울 것 같아 static import를 제거했습니다.

if (hasSwitchedOver(line)) {
this.insert.setNextOpIndex(index);
prepareSwitchover(line);
count = 0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switchover 경우를 예로 들면,
이미 일부가 수행된 상태에서 나머지를 switchover한 후에 수행하면,
그 이후의 결과는 원소 결과로 처리해야 할 것 같습니다.

NOT_MY_KEY 경우도 함께 검토 바랍니다.

Copy link
Collaborator Author

@oliviarla oliviarla Jan 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switchover, redirect 로 인해 새로운 별도 요청을 보낸 후 응답을 받았을 때, RESPONSE가 올 수도 있고 하나의 ERROR 라인이 올 수도 있습니다.
이 때 RESPONSE가 왔을 때에만 예외를 던지지 않도록 하여 PIPE_ERROR까지 읽도록 합니다.

@oliviarla
Copy link
Collaborator Author

@jhpark816
count 대신 readUntilLastLine 플래그를 두도록 변경하고 주석도 추가했습니다.

@jhpark816 jhpark816 merged commit fa44194 into naver:develop Jan 9, 2025
2 checks passed
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.

4 participants