naver / arcus-c-client

ARCUS C client
https://github.com/naver/arcus
Apache License 2.0
12 stars 16 forks source link

DOC: Add examples for the KV API #312

Closed ing-eoking closed 4 weeks ago

ing-eoking commented 2 months ago

πŸ”— Related Issue

⌨️ What I did

namsic commented 2 months ago

https://github.com/ing-eoking/arcus-c-client/blob/kvdoc/docs/03-key-value-API.md#key-value-item-μ €μž₯

jhpark816 commented 1 month ago

@ing-eoking μ•„λž˜ 메뉴얼도 μ°Έκ³ ν•˜μ—¬, μ„€λͺ…을 λ³΄κ°•ν•˜λŠ” μž‘μ—…λ„ λ‹€λ₯Έ PR둜 μ§„ν–‰ν•˜λ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€. https://docs.oracle.com/cd/E88353_01/html/E37842/memcached-get-3libmemcached.html

namsic commented 1 month ago

@jhpark816

image

ν˜„μž¬ PR은 κΈ°μ‘΄ λ¬Έμ„œμ™€ μœ μ‚¬ν•œ ꡬ쑰λ₯Ό 갖도둝 μž‘μ„±λ˜μ—ˆλŠ”λ°μš”. (assert λ“±) λ§Œμ•½ μ΄λŸ¬ν•œ ꡬ쑰가 μ μ ˆν•˜μ§€ μ•Šλ‹€λ©΄ 이 PR의 λ‚΄μš©λ§Œ μˆ˜μ •ν•˜λŠ” κ²ƒμœΌλ‘œλŠ” μΆ©λΆ„ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μˆ˜μ •λœ λ‚΄μš©μ— 맞게 κΈ°μ‘΄ λͺ¨λ“  λ¬Έμ„œλ₯Ό λ‹€μ‹œ 정리해야 ν•˜λŠ”λ°, 이 PRμ—μ„œ λ¬Έμ„œ ꡬ쑰λ₯Ό κ²°μ •ν•˜κΈ°λ³΄λ‹€λŠ” λ³„λ„μ˜ 이슈λ₯Ό λ§Œλ“€μ–΄ 의견이 μΆ©λΆ„νžˆ μ •λ¦¬λœ 뒀에 일괄 μ μš©ν•˜λŠ” 것이 μ’‹κ² μŠ΅λ‹ˆλ‹€.

κ°œμΈμ μœΌλ‘œλŠ”, μ‹€νŒ¨ μ‹œ 처리 방법 등은 νŠΉμ • API에 κ΅­ν•œλ˜λŠ” 것이 μ•„λ‹ˆλ―€λ‘œ ν•¨μˆ˜λ§ˆλ‹€ μ˜ˆμ™Έ μ²˜λ¦¬ν•˜λŠ” μ˜ˆμ‹œλ₯Ό 맀 번 μž‘μ„±ν•΄ λ‘λŠ” 것은 λΉ„νš¨μœ¨μ΄λΌκ³  λ΄…λ‹ˆλ‹€. ν•œ 가지 μˆ˜μ • 사항이 생길 λ•Œλ§ˆλ‹€ λͺ¨λ“  API λ¬Έμ„œλ₯Ό ν•¨κ»˜ λ³€κ²½ν•΄μ•Ό ν•  것이고, μ‹œκ°„μ΄ 흐λ₯΄λ©΄ λ¬Έμ„œ κ°„ 일관성이 κΉ¨μ Έ 이λ₯Ό λ§žμΆ”λŠ” μž‘μ—…μ„ λ‹€μ‹œ μ§„ν–‰ν•˜κ²Œ 될 κ²ƒμž…λ‹ˆλ‹€.

μΊμ‹œ μ„œλ²„μ˜ λ¬Έμ„œμ²˜λŸΌ 각 ν•¨μˆ˜μ˜ 결과둜 λ°˜ν™˜λ  수 μžˆλŠ” rc λͺ©λ‘κ³Ό κ·Έ 의미 μ •λ„λ§Œ λ‚˜μ—΄ν•΄ 두고, μ˜ˆμ™Έ 처리 및 λ‘œκΉ… 등은 ARCUS C Client와 같은 곡톡 λ¬Έμ„œμ— μž‘μ„±ν•΄ 두면 μΆ©λΆ„ν•  κ²ƒμž…λ‹ˆλ‹€.

μ•„λž˜ 메뉴얼도 μ°Έκ³ ν•˜μ—¬, μ„€λͺ…을 λ³΄κ°•ν•˜λŠ” μž‘μ—…λ„ λ‹€λ₯Έ PR둜 μ§„ν–‰ν•˜λ©΄ μ’‹κ² μŠ΅λ‹ˆλ‹€. https://docs.oracle.com/cd/E88353_01/html/E37842/memcached-get-3libmemcached.html

μœ„ 링크의 λ‚΄μš© μžμ²΄λŠ” arcus-c-client에도 μžˆλŠ” λ‚΄μš©μž…λ‹ˆλ‹€. λ§Œμ•½ 링크와 같은 ν˜•νƒœμ˜ 메뉴얼이 ν•„μš”ν•˜λ‹€λ©΄, 이미 μžˆλŠ” λ‚΄μš©μ„ μ€‘λ³΅μœΌλ‘œ μž‘μ„±ν•  것이 μ•„λ‹ˆλΌ man2htmlκ³Ό 같은 도ꡬλ₯Ό μ‚¬μš©ν•˜λŠ” κ²ƒμœΌλ‘œ μΆ©λΆ„ν•  κ²ƒμž…λ‹ˆλ‹€.

jhpark816 commented 1 month ago

@ing-eoking λ³Έ μž‘μ—…λ„ 진행해 μ£Όμ„Έμš”.

μ˜ˆμ‹œ μ½”λ“œλ₯Ό 톡해 보이고자 ν•˜λŠ” 사항은

μœ„ 사항을 λ³΄μ΄λŠ” μ˜ˆμ‹œ μ½”λ“œλ₯Ό ν•˜λ‚˜ μ€€λΉ„ν•˜μ—¬ 리뷰 및 λ…Όμ˜λ₯Ό 거쳐 μ˜ˆμ‹œ μ½”λ“œ ν˜•νƒœλ₯Ό κ²°μ •ν•˜κ³ , κ·Έ ν˜•νƒœλ‘œ 일괄 μ μš©ν•˜μ‹œμ£ .

ing-eoking commented 1 month ago

@jhpark816

ν˜„μž¬ ν•΄λ‹Ή PR에 λŒ€ν•˜μ—¬ μ œκ°€ μƒκ°ν•˜κ³  μžˆλŠ” μ˜ˆμ‹œλŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

int arcus_kv_store(memcached_st *memc)
{
  const char *key= "item:a_key";
  const char *value= "value";
  uint32_t exptime= 600;
  uint32_t flags= 0;
  memcached_return_t rc;

  rc= memcached_set(memc, key, strlen(key), value, strlen(value), exptime, flags);
  if (memcached_failed(rc)) {
    fprintf(stderr, "Failed to memcached_set: %d(%s)\n", rc, memcached_strerror(mc, rc));
    return -1;
  }

  assert(rc == MEMCACHED_SUCCESS);
  return 0;
}

리턴 κ°’μ˜ μ‚¬μš©λ²• (성곡, μ‹€νŒ¨)

성곡과 μ‹€νŒ¨μ˜ νŒλ‹¨ 기쀀을 ν•¨μˆ˜μ˜ 리턴 κ°’λ³΄λ‹€λŠ” APIμ—μ„œ μ œκ³΅ν•˜λŠ” μ—λŸ¬κ°’μ— λ‘λŠ” 것이 더 μ μ ˆν•˜λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, memcached_get λͺ…λ Ήμ–΄λ₯Ό μˆ˜ν–‰ν–ˆμ„ λ•Œ λ°˜ν™˜λœ μ—λŸ¬κ°’μ΄ MEMCACHED_SUCCESS인 경우, valueκ°€ NULL이고 value_lengthκ°€ 0이라면, μ΄λŠ” 성곡적인 μˆ˜ν–‰μ΄μ§€λ§Œ 데이터가 μ—†μŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.

이에 λŒ€ν•œ μ˜ˆμ œλŠ” λ‹€λ₯Έ 성곡과 λ™μΌν•˜κ²Œ μ²˜λ¦¬ν•˜λ©΄ λ˜μ§€ μ•Šμ„κΉŒ μƒκ°ν•©λ‹ˆλ‹€.

fprintf(stdout, "[DEBUG] memcached_get: %.*s=%.*s\n", key_len, key, value_len, value);
ing-eoking commented 1 month ago

@jhpark816 @namsic

λ³€κ²½λœ μ½”λ“œ λ³΄μ‹œκ³ , 리뷰 μ§„ν–‰ν•΄μ£Όμ‹œλ©΄ 될 것 κ°™μŠ΅λ‹ˆλ‹€.

ing-eoking commented 1 month ago

@namsic

μ˜ˆμ‹œ μ½”λ“œ μΆ”κ°€ μ™Έ λ‹€λ₯Έ μ„€λͺ…은 ν˜„μž¬ μƒνƒœλ‘œ μΆ©λΆ„ν•˜λ‹€κ³  λ³΄λŠ” κ²ƒμΈκ°€μš”?

개인적으둜 μ†Œμ œλͺ©μ„ ν•˜λ‚˜ 더 λ‘λŠ” 편이 더 깔끔해보여 λ³€κ²½ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€. 리뷰 μ§„ν–‰ν•΄μ£Όμ‹œλ©΄ 될 것 κ°™μŠ΅λ‹ˆλ‹€.

μ•„λž˜λŠ” μ˜ˆμ‹œμž…λ‹ˆλ‹€.


Key-Value Item μ €μž₯

key-value item을 μ €μž₯ν•˜λŠ” API둜 set, add, replace, prepend/appendκ°€ μžˆλ‹€

μ£Όμš” νŒŒλΌλ―Έν„°

ν•¨μˆ˜ μ„€λͺ…

μƒˆλ‘œμš΄ μ•„μ΄ν…œμ„ μ €μž₯ν•˜κ±°λ‚˜ κ΅μ²΄ν•˜λŠ” APIλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

memcached_return_t memcached_set(...)
memcached_return_t memcached_add(...)
memcached_return_t memcached_replace(...)

λŒ€ν‘œμ μœΌλ‘œ set을 ν™œμš©ν•˜λŠ” μ˜ˆμ œλŠ” λ‹€μŒκ³Ό κ°™λ‹€.

int arcus_kv_store(memcached_st *memc)
{
  ...
}

Key-Value Item 쑰회

...

Key-Value 제거

...

jhpark816 commented 1 month ago

@namsic 리뷰 μ™„λ£Œν•œ μƒνƒœκ°€ μ•„λ‹ˆμ£ ?

namsic commented 1 month ago

리뷰 μ™„λ£Œν•œ μƒνƒœκ°€ μ•„λ‹ˆμ£ ?

예. 아직 확인 쀑 μž…λ‹ˆλ‹€.

ing-eoking commented 1 month ago

@jhpark816

mgetμ—μ„œ 값이 빈 λ¬Έμžμ—΄μΈ 경우 NULL이 λ°˜ν™˜λ˜λŠ” 원인 뢄석

(이 λ¬Έμ œλŠ” getμ—μ„œλ„ λ™μΌν•˜κ²Œ λ°œμƒν•©λ‹ˆλ‹€.)

memcached_fetch ν•¨μˆ˜λ₯Ό μ‚΄νŽ΄λ³΄λ©΄, μ•„λž˜μ™€ 같이 result ꡬ쑰체 λ‚΄μ—μ„œ 값을 가져와 λ¬Έμžμ—΄ ν˜•νƒœλ‘œ λ°˜ν™˜ν•©λ‹ˆλ‹€.

char *memcached_fetch(...)
{
  ...
  return memcached_string_take_value(&result_buffer->value);
}

memcached_string_take_value ν•¨μˆ˜ λ‚΄λΆ€λŠ” λ‹€μŒκ³Ό 같이 κ΅¬ν˜„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

char *memcached_string_take_value(memcached_string_st *self)
{
  assert_msg(self, "Invalid memcached_string_st");
  // If we fail at adding the null, we copy and move on
  if (memcached_success(memcached_string_append_null(self)))
  {
    return memcached_string_c_copy(self);
  }

  char *value= self->string;

  _init_string(self);

  return value;
}

이 ν•¨μˆ˜λŠ” λ¬Έμžμ—΄ 끝에 null 문자λ₯Ό μ„±κ³΅μ μœΌλ‘œ μΆ”κ°€ν•  경우(μ‹€νŒ¨ μΌ€μ΄μŠ€λŠ” λͺ¨λ₯΄κ² μŠ΅λ‹ˆλ‹€), memcached_string_c_copyλ₯Ό ν˜ΈμΆœν•˜μ—¬ λ³΅μ‚¬ν•œ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

memcached_string_c_copy ν•¨μˆ˜λŠ” λ‹€μŒκ³Ό 같이 κ΅¬ν˜„λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

char *memcached_string_c_copy(memcached_string_st *string)
{
  if (not memcached_string_length(string))
    return NULL;

  char *c_ptr= static_cast<char *>(libmemcached_malloc(string->root, (memcached_string_length(string)+1) * sizeof(char)));

  if (not c_ptr)
    return NULL;

  memcpy(c_ptr, memcached_string_value(string), memcached_string_length(string));
  c_ptr[memcached_string_length(string)]= 0;

  return c_ptr;
}

첫 번째 μ‘°κ±΄λ¬Έμ—μ„œ memcached_string_lengthκ°€ 0일 경우 NULL이 λ°˜ν™˜λ˜λ„λ‘ λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

jhpark816 commented 1 month ago

μ΅œμ‹  libmemcached도 λ™μΌν•˜κ²Œ μ²˜λ¦¬ν•˜κ³  μžˆλ‚˜μš”?

ing-eoking commented 1 month ago

@jhpark816

μ΅œμ‹  libmemcached도 λ™μΌν•˜κ²Œ μ²˜λ¦¬ν•˜κ³  μžˆλ‚˜μš”?

λ‘œμ§μ€ 쑰금 λ³€κ²½λ˜μ—ˆμ§€λ§Œ 길이가 0이면, NULL을 λ°˜ν™˜ν•˜λŠ” λ™μž‘ μžμ²΄λŠ” λ™μΌν•©λ‹ˆλ‹€.

char *memcached_string_take_value(memcached_string_st *self) {
  char *value = NULL;

  assert_msg(self, "Invalid memcached_string_st");
  if (self) {
    if (memcached_string_length(self)) {
      // If we fail at adding the null, we copy and move on
      if (memcached_failed(memcached_string_append_null(self))) {
        return NULL;
      }

      value = self->string;
      _init_string(self);
    }
  }

  return value;
}
ing-eoking commented 1 month ago

fetchκ°€ μ‹€νŒ¨ν•  경우 λ°˜ν™˜λ˜λŠ” μ—λŸ¬λŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€. (아직 ν™•μ‹€ν•˜μ§€λŠ” μ•Šμ§€λ§Œ, λŒ€λΆ€λΆ„μ˜ μƒν™©μ—μ„œ μ•„λž˜μ˜ μ—λŸ¬λ§Œ λ°˜ν™˜λ˜λŠ” κ²ƒμœΌλ‘œ λ³΄μž…λ‹ˆλ‹€.)

MEMCACHED_NOTFOUND : λͺ¨λ“  μ„œλ²„μ—μ„œ 읽을 수 μžˆλŠ” κ²°κ³Όκ°€ μ—†λŠ” κ²½μš°μ— λ°˜ν™˜λ©λ‹ˆλ‹€. MEMCACHED_CONNECTION_FAILURE : νŠΉμ • μ„œλ²„μ™€μ˜ 연결에 λ¬Έμ œκ°€ μžˆλŠ” 경우(예: 잘λͺ»λœ μ†ŒμΌ“ 파일) λ°˜ν™˜λ©λ‹ˆλ‹€.

특히 MEMCACHED_CONNECTION_FAILUREκ°€ λ°œμƒν•˜λ”λΌλ„, λ‹€λ₯Έ μ„œλ²„μ—μ„œ 읽을 수 μžˆλŠ” κ²°κ³Όκ°€ μžˆλŠ” κ²½μš°μ—λŠ” MEMCACHED_SUCCESS둜 μ²˜λ¦¬λ©λ‹ˆλ‹€.

jhpark816 commented 1 month ago

mget μ‹€νŒ¨ν•˜λŠ” κ²½μš°κ°€ failure, some_errros 2가지 μ•„λ‹Œκ°€μš”? λ‹€λ₯Έ 경우의 였λ₯˜λ₯Ό μ„€λͺ…ν•˜λŠ” κ°€μš”?

κ·Έλž˜μ„œ, get, mget μ˜ˆμ‹œ μ½”λ“œλŠ” μ–΄λ–»κ²Œ ν•˜λ©΄ λ˜λ‚˜μš”?

ing-eoking commented 1 month ago

@jhpark816

mget μ‹€νŒ¨ν•˜λŠ” κ²½μš°κ°€ failure, some_errros 2가지 μ•„λ‹Œκ°€μš”? λ‹€λ₯Έ 경우의 였λ₯˜λ₯Ό μ„€λͺ…ν•˜λŠ” κ°€μš”?

μ œκ°€ 잘λͺ» μž‘μ„±ν–ˆλ„€μš”. fetch에 λŒ€ν•œ μ„€λͺ…μ΄μ—ˆμŠ΅λ‹ˆλ‹€. 결둠적으둜, fetch μˆ˜ν–‰ κ³Όμ •μ—μ„œ μ‹€νŒ¨ν•  κ²½μš°μ—λŠ” λ‚˜λ¨Έμ§€ 연산을 계속 μ§„ν–‰ν•˜μ§€ μ•Šκ³  λ°”λ‘œ λ¦¬ν„΄ν•˜λŠ” 것이 더 λ‚˜μ„ 것 κ°™μŠ΅λ‹ˆλ‹€.

ing-eoking commented 1 month ago

@jhpark816

μ—λŸ¬ 처리λ₯Ό value == NULL ν˜Ήμ€ memcached_failed(rc) 쀑 μ–΄λ–€ 방식은 ν™œμš©ν•˜λŠ”κ°€?

빈 λ¬Έμžμ—΄μ„ μ €μž₯ν•˜λŠ” 경우 valueκ°€ NULL인 κ²½μš°κ°€ λ°œμƒν•˜λ―€λ‘œ memcached_failed(rc) κ°€ μ ν•©ν•©λ‹ˆλ‹€.

memcached_fetch 쀑 μ—λŸ¬κ°€ λ°œμƒν•˜λŠ” 경우 μ€‘μ§€ν•˜μ§€ 말고, 계속 μ§„ν–‰ν•˜λŠ” 것이 λ§žλŠ”μ§€?

일반적으둜 memcached_fetch μ—μ„œ memcached_failedλ₯Ό 톡해 μ—λŸ¬λ‘œ κ°μ§€λ˜λŠ” μ—λŸ¬λŠ” MEMCACHED_NOTFOUND와 MEMCACHED_CONNECTION_FAILURE μž…λ‹ˆλ‹€.

두 μ—λŸ¬ λͺ¨λ‘ 더 이상 μ„±κ³΅μ μœΌλ‘œ 값을 읽을 수 μ—†λŠ” κ²½μš°μ— λ°˜ν™˜λ˜λŠ” κ²ƒμœΌλ‘œ 보이기에 λ°”λ‘œ λ¦¬ν„΄ν•˜λŠ” 편이 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ, get, mget μ˜ˆμ‹œ μ½”λ“œλŠ” μ–΄λ–»κ²Œ ν•˜λ©΄ λ˜λ‚˜μš”?

ν˜„μž¬ PR에 반영된 μƒνƒœλ‘œ κ°€λŠ” 편이 μ’‹λ‹€κ³  μƒκ°ν•©λ‹ˆλ‹€.

int arcus_kv_get(memcached_st *memc)
{
  const char *key= "item:a_key";
  const char *value;
  size_t value_length;
  uint32_t flags;
  memcached_return_t rc;

  value= memcached_get(memc, key, strlen(key), &value_length, &flags, &rc);
  if (memcached_failed(rc)) {
    fprintf(stderr, "Failed to memcached_get: %d(%s)\n", rc, memcached_strerror(mc, rc));
    return -1;
  }

  assert(rc == MEMCACHED_SUCCESS);
  if (value != NULL) {
    fprintf(stdout, "memcached_get: %s=%s\n", key, value);
    free((void*)value);
  } else {
    fprintf(stdout, "memcached_get: %s=<empty value>.\n", key);
  }
  return 0;
}

int arcus_kv_mget(memcached_st *memc)
{
  const char * const keys[]= { "item:a_key1", "item:a_key2", "item:a_key3" };
  size_t keys_len[3];
  size_t number_of_keys = 3;
  uint32_t flags;
  memcached_return_t rc;

  for (size_t i=0; i<number_of_keys; i++)
  {
    keys_len[i]= strlen(keys[i]);
  }

  rc= memcached_mget(memc, keys, keys_len, number_of_keys);
  if (rc == MEMCACHED_FAILURE) {
    fprintf(stderr, "Failed to memcached_get: %d(%s)\n", rc, memcached_strerror(mc, rc));
    return -1;
  }

  assert(rc == MEMCACHED_SUCCESS || rc == MEMCACHED_SOME_ERRORS);
  while (true)
  {
    char key[MEMCACHED_MAX_KEY];
    size_t key_length;
    size_t value_length;

    char *value= memcached_fetch(mc, key, &key_length, &value_length, &flags, &rc);
    if (memcached_failed(rc)) {
      fprintf(stderr, "Failed to memcached_fetch: %d(%s)\n", rc, memcached_strerror(mc, rc));
      return -1;
    }

    if (rc == MEMCACHED_END) {
      break;
    }

    assert(rc == MEMCACHED_SUCCESS);
    if (value != NULL) {
      fprintf(stdout, "memcached_mget: %s=%s\n", key, value);
      free((void*)value);
    } else {
      fprintf(stdout, "memcached_mget: %s=<empty value>.\n", key);
    }
  }
  return 0;
}
ing-eoking commented 1 month ago

@jhpark816 @namsic

리뷰 λΆ€νƒλ“œλ¦½λ‹ˆλ‹€.

ing-eoking commented 4 weeks ago

@jhpark816

일괄 μˆ˜μ •λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

jhpark816 commented 4 weeks ago

@ing-eoking cas 연산은 별도 PR둜 μΆ”κ°€ν•΄ μ£Όμ‹œμ£ .