-
Notifications
You must be signed in to change notification settings - Fork 46
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
FIX: Element sequence when using asyncLopInsert api. #633
Conversation
@brido4125 |
@uhm0311 @oliviarla 리뷰 바랍니다. |
@namsic 간단 내용이라 리뷰해 봅시다. |
@@ -51,7 +51,7 @@ public static class ListPipedInsert<T> extends CollectionPipedInsert<T> { | |||
|
|||
private static final String COMMAND = "lop insert"; | |||
private final Collection<T> list; | |||
private final int index; | |||
private int index; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사용자가 입력한 인자라는 의미에서 final
속성을 유지하고,
실제 명령을 보내는 시점에는 [0, list_size)
값을 갖는 지역변수를 활용하여
index + offset
형태로 명령을 생성하는 구현은 어떤가요?
src/test/manual/net/spy/memcached/bulkoperation/PipeInsertTest.java
Outdated
Show resolved
Hide resolved
@@ -61,7 +62,7 @@ public void testInsertWithAttribute() { | |||
} | |||
|
|||
Map<Integer, CollectionOperationStatus> insertResult = mc | |||
.asyncLopPipedInsertBulk(KEY, INDEX, valueList, attr).get(); | |||
.asyncSopPipedInsertBulk(KEY, valueList, attr).get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
별도의 commit으로 분리할 필요는 없나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
INDEX 변수도 사용하지 않을 것이므로, 제거하시죠.
본 수정을 별도 PR로 주면 바로 merge할 수 있습니다.
c2e108e
to
a77c2d6
Compare
@@ -90,7 +90,7 @@ public ByteBuffer getAsciiCommand() { | |||
CollectionCreate.makeCreateClause(attribute, cd.getFlags()) : ""; | |||
for (int i = this.nextOpIndex; i < eSize; i++) { | |||
byte[] each = encodedList.get(i); | |||
setArguments(bb, COMMAND, key, index, each.length, | |||
setArguments(bb, COMMAND, key, index + i, each.length, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
replication과 migration이 발생할 경우를 고려하여 index + i
를 통해 리스트 요소들의 순서를 보장합니다.
i의 시작값인 nextOpIndex의 경우
piped연산을 구성하는 연산들의 index 값을 받는 변수입니다.
쉽게말해 하나의 파이프 연산에 10개의 insert 연산이 있는 경우
3번째 연산을 완료했을 때, nextOpIndex
는 4로 설정됩니다.
즉, 지금까지 완료된 연산의 Index값을 nextOpIndex가 가지고 있습니다.
그래서 replication과 migration이 발생했을 때
nextOpIndex
값을 통해 요소를 삽입할 위치를 정해야
이전까지 삽입된 요소들의 순서에 맞게 요소를 삽입할 수 있습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
리뷰 완료
@@ -61,7 +62,7 @@ public void testInsertWithAttribute() { | |||
} | |||
|
|||
Map<Integer, CollectionOperationStatus> insertResult = mc | |||
.asyncLopPipedInsertBulk(KEY, INDEX, valueList, attr).get(); | |||
.asyncSopPipedInsertBulk(KEY, valueList, attr).get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
INDEX 변수도 사용하지 않을 것이므로, 제거하시죠.
본 수정을 별도 PR로 주면 바로 merge할 수 있습니다.
a77c2d6
to
9672dca
Compare
@jhpark816 |
9672dca
to
4b7d56a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
리뷰 완료
|
||
|
||
CollectionFuture<Map<Integer, CollectionOperationStatus>> future = mc | ||
.asyncLopPipedInsertBulk(KEY, 1, elements, attr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래 3 경우 모두 시험에 넣어 주세요.
- index = 0
- index = 1
- index = -1
ec5b3eb
to
01f83fa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
리뷰 완료
int offset = i; | ||
if (index < 0) { | ||
offset = 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int eIndex = index; // element index
if (eIndex >= 0) {
eIndex += i;
}
setArguments(..., eIndex, ...);
mc.asyncLopPipedInsertBulk(KEY, 0, headerElements, attr); | ||
CollectionFuture<Map<Integer, CollectionOperationStatus>> future3 = | ||
mc.asyncLopPipedInsertBulk(KEY, -1, footerElements, attr); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line 1개 제거합니다.
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기는 2개 empty line 모두 제거합시다.
|
||
try { | ||
CollectionAttributes attr = new CollectionAttributes(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
empty line 제거
List<Object> list = mc.asyncLopGet(KEY, 0, 9999, false, false).get(); | ||
|
||
System.out.println("list = " + list); | ||
|
||
Assert.assertEquals((elementCount * 3) + 2, list.size()); | ||
|
||
Assert.assertEquals(headerElements, list.subList(0, elementCount)); | ||
Assert.assertEquals(middleElements, list.subList(elementCount + 1, elementCount * 2 + 1)); | ||
Assert.assertEquals(footerElements, list.subList(elementCount * 3 - 1, elementCount * 3 + 2)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래 형태가 보기가 수월합니다.
List<Object> list = mc.asyncLopGet(KEY, 0, 9999, false, false).get();
System.out.println("list = " + list);
Assert.assertEquals((elementCount * 3) + 2, list.size());
int offset = 0;
Assert.assertEquals(headerElements, list.subList(offset, offset+elementCount));
offset += (elementCount + 1);
Assert.assertEquals(middleElements, list.subList(offset, offset+elementCount));
offset += (elementCount + 1);
Assert.assertEquals(footerElements, list.subList(offset, offset+elementCount));
@@ -74,7 +74,7 @@ public void testInsertWithAttribute() { | |||
// check values | |||
List<Object> list2 = mc.asyncLopGet(KEY, 0, 10, false, false).get(); | |||
for (int i = 0; i < list2.size(); i++) { | |||
Assert.assertEquals(10 - i, list2.get(i)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
기존 테스트를 보니, 순서가 반대인 것을 인지하고 있었던 것 같습니다.
그런데, 이상하다고 생각하지 않았던 이유는 무엇인지?
c client는 어떤가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
기존 테스트를 보니, 순서가 반대인 것을 인지하고 있었던 것 같습니다.
그런데, 이상하다고 생각하지 않았던 이유는 무엇인지?
죄송합니다. 해당 PR을 올리기 전에는 위 테스트를 확인하지 않았습니다. 다음부터 테스트 코드도 신경쓰겠습니다.
c client는 어떤가요?
C 클라이언트는 구조가 파악이 아직 안되어, 시간이 좀 소요될것 같습니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
c client는 어떤가요?
https://github.com/naver/arcus-c-client/blob/master/docs/04-list-API.md#list-element-일괄-삽입
c client는 element의 개수만큼 index를 받고 있습니다. 따라서 사용자가 입력되는 순서를 결정할 수 있습니다.
/* [A, E]에 [B, C, D]를 insert하는 경우 */
// indexes = {1, 1, 1}
[A,E] -> [A,D,C,B,E]
// indexes = {1, 2, 3}
[A,E] -> [A,B,C,D,E]
@@ -74,7 +74,7 @@ public void testInsertWithAttribute() { | |||
// check values | |||
List<Object> list2 = mc.asyncLopGet(KEY, 0, 10, false, false).get(); | |||
for (int i = 0; i < list2.size(); i++) { | |||
Assert.assertEquals(10 - i, list2.get(i)); | |||
Assert.assertEquals(i + 1, list2.get(i)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래 형태가 나은 것 같습니다.
for (int i = 1; i <= list2.size(); i++) {
Assert.assertEquals(i, list2.get(i));
}
상위의 valueList 생성 부분도 아래와 같이 수정하죠.
for (int i = 1; i <= 10; i++) {
valueList.add(i);
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assert.assertEquals(i, list2.get(i - 1));
로 수정하겠습니다.
2cd25ce
to
2984dca
Compare
for (int i = 0; i < list2.size(); i++) { | ||
Assert.assertEquals(10 - i, list2.get(i)); | ||
for (int i = 1; i <= list2.size(); i++) { | ||
Assert.assertEquals(i, list2.get(i - 1)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분은 내가 제대로 확인하지 못했네요.
이전 PR 코드가 나은 것 같습니다.
for (int i = 0; i < list2.size(); i++) {
Assert.assertEquals(i+1, list2.get(i));
}
2984dca
to
661cf0a
Compare
Redis에서 List 자료구조에 대한 InsertionRedis에서는 RPUSH Api는 현재 LOP Bulk Insertion과 비교 가능합니다. 또한 아래와 같이 단건 또는 다건으로 삽입할 요소들을 인자로 지정합니다.
위 api가 다건 삽입으로 수행 시 elements들의 순서가 보장되어 삽입되게 됩니다. 공식문서 참조 바랍니다. 추가로 Java List의 addAll() 메서드를 통해 하나의 리스트에 새로운 리스트를 추가할 수 있습니다. |
OK. 다건 element 삽입 시, element 순서가 그대로 보장되는 현재 PR 방식대로 구현해야 되겠네요. |
현재 문제점
아래 예는 [A,E] 리스트에 [B,C,D] 리스트의 elements를
asyncLopPipedInsertBulk(Key, 1, elements, attr)
API로 삽입할 경우의 결과입니다.현재 동작은 고정된 index 값을 사용하여 의도하지 않은 결과를 만듭니다.
따라서, 이를 수정하여 아래의 변경 후 동작의 결과로 만들고자 합니다.
변경사항