Skip to content

INTERNAL: Register the vop ASCII extension - #6

Merged
jhpark816 merged 1 commit into
developfrom
extension
Oct 26, 2026
Merged

jhpark816 merged 1 commit into
developfrom
extension

Conversation

@ing-eoking

@ing-eoking ing-eoking commented Oct 24, 2026 •

Copy link
Copy Markdown
Collaborator

🔗 Related Issue

⌨️ What I did

memcached가 -X로 arcus-vector를 불러올 때 vop 명령을 받을 수 있도록 ASCII 프로토콜 확장을 등록합니다.
아직 실제 명령은 구현하지 않았으며, 모든 vop 명령에 NOT_SUPPORTED로 응답합니다.

  • src/lib.rs
    • cargo init 예제 코드를 지우고, memcached가 호출하는 진입점 memcached_extensions_initialize를 추가합니다.
    • 서버 API에서 확장 등록 함수를 얻어 ASCII 프로토콜 확장을 등록합니다.
  • src/ascii.rs: EE의 example_protocol.c와 같은 구조의 descriptor입니다.

Summary by CodeRabbit

  • 새로운 기능
    • memcached ASCII 프로토콜 확장을 등록하고 초기화할 수 있습니다.
    • 첫 토큰이 vop인 명령을 인식하며, 해당 명령에는 지원되지 않는다는 응답을 반환합니다.
  • 오류 처리
    • 확장 초기화에 필요한 서버 정보가 없거나 등록에 실패하면 초기화 오류를 반환합니다.

@coderabbitai

This comment was marked as resolved.

@ing-eoking
ing-eoking changed the base branch from master to develop October 24, 2026 08:47
@ing-eoking ing-eoking changed the title Extension INTERNAL: Register the vop ASCII extension Oct 24, 2026
@ing-eoking
ing-eoking marked this pull request as draft October 24, 2026 09:00
@ing-eoking
ing-eoking marked this pull request as ready for review October 24, 2026 12:26
coderabbitai[bot]

This comment was marked as resolved.

Comment thread src/lib.rs
/// The symbol memcached looks up when it loads this library with `-X`.
#[unsafe(no_mangle)]
pub extern "C" fn memcached_extensions_initialize(
_config: *const c_char,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

memcached 쪽으로 패닉이 넘어가지 않게 최대한 막아야 하는 걸로 알고 있습니다.

지금은 린트로 패닉 자체가 발생하지 않도록 막고 있긴 한데, FFI 경계마다 catch_unwind를 두어 안전망을 하나 더 두는 건 어떨까요?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

수정되었습니다.

가독성을 높이기 위해 catch_unwind를 guard 함수로 래핑했습니다.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

panic이 발생하게 되는 경우 처리 흐름은 다음와 같습니다.

진입점 실패·패닉 시 반환 서버(core) 처리
memcached_extensions_initialize EXTENSION_FATAL load_extension 실패 → exit(EXIT_FAILURE)로 서버 시작 중단
accept true 본문을 읽지 않고 같은 스레드에서 바로 execute 호출(아래 참고)
execute false 해당 연결만 닫음(conn_closing), 데몬과 다른 연결은 유지

accept에서 패닉이 났을 때

순서 동작
1 *ndata = 0으로 되돌려 코어에서 conn_nread로 가지 않게 함
2 스레드 로컬 플래그 ACCEPT_PANICKED 설정
3 true 반환 → 줄을 이 확장이 받은 것으로 처리 (ERROR unknown command를 보내지 않음)
4 core가 같은 스레드에서 곧바로 execute 호출
5 execute가 플래그를 보고 false 반환 → 연결 종료, 클라이언트가 보낸 본문은 연결과 함께 버려짐

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

accept에서 패닉 발생 시에 false 리턴해야 하지 않나요?
현재 extention에서 처리할 수 있는 명령인지를 확인하지 못했기 때문이며, 따라서 다른 extension에서 처리할 수 있는 지 확인하기 때문입니다.

@zhy2on zhy2on Oct 25, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

주요 패닉은 린트로 막고 있어서, 발생한다면 예상하지 못한 버그인 경우라고 생각합니다. 그때는 accept가 어디까지 처리했는지 믿을 수 없으니 연결을 끊는 게 안전해 보입니다.

명령 이름 비교에서는 패닉이 날 여지가 거의 없어서, 패닉이 난다면 이미 vop로 확인된 뒤일 가능성이 높습니다. 그래서 다른 extension이 처리하도록 false를 반환하는 경우는 크게 고려하지 않아도 될 것 같습니다.

오히려 false를 반환하면 코어가 ERROR unknown command를 보내고 연결을 유지한 채 다음 줄을 읽습니다. 앞으로 vop upsert, vop search처럼 본문이 있는 명령이 들어오면 본문이 다음 명령으로 해석되어 응답이 어긋나거나, 본문 내용이 다른 명령으로 실행될 수 있습니다.

accept에서 연결을 끊으려면 true로 받은 뒤 execute에서 false를 반환하는 방법뿐이라, 지금 방식이 맞다고 봅니다.

다만 SASL 권한 검사에서 막히면 execute가 호출되지 않아 ACCEPT_PANICKED가 남을 수 있으니, accept 시작 시 플래그를 초기화해두면 좋을 것 같습니다.

@jhpark816

jhpark816 commented Oct 25, 2026 •

Copy link
Copy Markdown

@ing-eoking
아직 익숙하지 않아서 질문하는 것인데요.
이번 vector 기능에서 C 구현보다 rust 구현이 가지는 장점이 분명히 있나요?
scrub 기능의 C 구현을 보면 간단한데,
vector 기능의 rust 구현은 상당히 복잡해 보여 질문합니다.

@ing-eoking

ing-eoking commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator Author

@jhpark816

scrub처럼 기능 자체는 엔진에 이미 구현되어 있고 확장은 프로토콜만 연결해 주는 경우라면, 코드가 짧고 단순해서 C로 구현하는 편이 더 낫다고 생각합니다.

다만 vector 기능은 엔진 처리만으로 끝나지 않는 비교적 무거운 기능입니다. HNSW 인덱스 관리, 검색을 처리하는 별도 스레드, 엔진 이벤트에 맞춘 인덱스 갱신, 메타데이터·필터 처리처럼 확장 쪽에 들어가야 하는 코드가 많습니다. 이런 상황에서 Rust는 다음과 같은 장점이 있습니다.

  • 메모리·동시성 문제를 컴파일 단계에서 잡아 줍니다.
    • Rust는 소유권과 타입 검사로 이런 실수의 상당 부분을 빌드할 때 막아 줍니다.
    • 위험한 코드는 unsafe로 범위가 드러나서 리뷰할 곳도 분명해집니다.
  • 구조화가 쉽습니다.
    • 구조체·열거형·트레이트로 요청, 인덱스, 에러 같은 개념을 타입으로 표현할 수 있어서, 코드가 커져도 역할이 명확하게 나뉩니다.
  • 테스트가 언어에 내장되어 있습니다.
    • 서버를 띄우지 않아도 cargo test로 프로토콜 파서나 인덱스 로직을 바로 검증할 수 있습니다.
  • 의존성 관리가 편합니다.
    • HNSW(usearch), BSON 같은 라이브러리를 Cargo로 버전까지 고정해서 가져다 쓸 수 있습니다. 직접 구현하거나 빌드 스크립트로 붙일 필요가 없습니다.

정리하면, 단순히 엔진 기능을 노출하는 확장은 C가, vector처럼 확장 쪽에 무거운 로직이 들어가는 기능은 Rust가 더 안전하고 유지보수하기 좋다고 판단해서 Rust를 선택했습니다.

@jhpark816

Copy link
Copy Markdown

@zhy2on
리뷰 잘 부탁해요. (나는 리뷰가 힘드네요)

Comment thread src/lib.rs
extension_type_t_EXTENSION_ASCII_PROTOCOL,
};

pub(crate) fn guard<T>(on_panic: impl FnOnce() -> T, f: impl FnOnce() -> T) -> T {

@zhy2on zhy2on Oct 25, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Rust 기본 패닉 처리기는 메시지를 stderr로 출력하는데,

memcached를 -d로 띄우면 -v가 없을 때 stderr가 /dev/null로 돌려져서 운영 환경에서는 패닉 위치와 메시지가 남지 않습니다.

초기화 시 std::panic::set_hook으로 패닉 메시지를 memcached logger로 남기면 좋을 것 같습니다.

이슈로 두고 추후에 적용해도 좋을 것 같습니다.

@ing-eoking ing-eoking Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

추후에 logger 모듈을 추가하는 PR을 올릴 예정입니다.
set_hook 부분은 해당 PR에서 함께 처리될 것 같습니다.

Comment thread src/ascii.rs
}

#[test]
fn a_panicked_accept_closes_the_connection() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

ACCEPT_PANICKED가 true일 때 false로 종료하는지 확인하는 테스트로 보입니다.
그런데 response_handler가 None이어도 false가 반환되어서, 지금은 ACCEPT_PANICKED 때문에 종료된 것인지 구분하기 어려울 것 같습니다.

None 대신 Some(record)를 넘기면 더 확실하게 확인할 수 있을 것 같습니다.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

수정되었습니다.

@zhy2on zhy2on Oct 26, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

확인했습니다. 이상 없습니다. 머지해도 될 것 같습니다. @jhpark816

@jhpark816
jhpark816 merged commit d963995 into develop Oct 26, 2026
4 checks passed
@ing-eoking
ing-eoking deleted the extension branch October 26, 2026 01:41

This branch was successfully deployed

1 active deployment
ee — 4967335a Deployed Oct 26, 2026 by ing-eoking via Build arcus-memcached #32
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.

3 participants