Strange behavior of open cursor with initial position
- Dominant language
- Java
- Stars
- 15.3k
- Forks
- 3.8k
- Avg merge
- 1d 14h
- Merged PRs (30d)
- 160
Description
v2.8.0, managed-ledger:
When using ManagedLedger.openCursor with InitialPosition, for the first time (creation), it seems that the markDeletePosition will be persisted using the LAC position at that moment, regardless of the initial position parameter passed to the openCursor method. After that the cursor position will be set according the initial position parameter in-memory only, and the cursor can read entries before LAC. But, if I do reopen everything, the cursor can only read entries after the persisted markDelete position, even if entries before that are not read at all.
Refer to the following test, pos1 was read normally, but after reopen, the same cursor cannot read pos2 or pos3 any more.
```java
@Test
public void cursorInitialPositionIssue() throws Exception {
MetadataStore metadataStore = new ZKMetadataStore(ZK_CONNECTION, MetadataStoreConfig.builder().build());
ClientConfiguration bkClientConf = new ClientConfiguration();
bkClientConf.setMetadataServiceUri(METADATA_SERVICE_URI);
ManagedLedgerFactoryImpl factory = new ManagedLedgerFactoryImpl(metadataStore, bkClientConf);
ManagedLedger ml = factory.open(ML_NAME);
Position pos1 = ml.addEntry("Hello".getBytes(StandardCharsets.UTF_8));
Position pos2 = ml.addEntry("world".getBytes(StandardCharsets.UTF_8));
Position pos3 = ml.addEntry("!!!".getBytes(StandardCharsets.UTF_8));
ManagedCursor c = ml.openCursor("test-cursor", InitialPosition.Earliest);
List entries = c.readEntries(1);
assertEquals(1, entries.size());
assertEquals(pos1, entries.get(0).getPosition());
assertEquals("Hello", new String(entries.get(0).getData()));
c.close();
ml.close();
factory.shutdown();
factory = new ManagedLedgerFactoryImpl(metadataStore, bkClientConf);
ml = factory.open(ML_NAME);
c = ml.openCursor("test-cursor");
entries = c.readEntries(3);
assertEquals(2, entries.size());
assertEquals(pos2, entries.get(0).getPosition());
assertEquals("world", new String(entries.get(0).getData()));
assertEquals(pos3, entries.get(1).getPosition());
assertEquals("!!!", new String(entries.get(1).getData()));
}
```
Contributor guide
Research direction
Start with the reported cursorInitialPositionIssue test and ManagedLedger.openCursor(..., InitialPosition.Earliest). Trace how the initial mark-delete position is persisted on first creation versus restored after reopen. Done means a regression test passes across close and reopen while preserving the requested initial-position behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100