|
19 | 19 | package org.apache.pulsar.broker.service; |
20 | 20 |
|
21 | 21 | import static org.mockito.ArgumentMatchers.any; |
| 22 | +import static org.mockito.ArgumentMatchers.nullable; |
22 | 23 | import static org.mockito.Mockito.doAnswer; |
23 | 24 | import static org.mockito.Mockito.doReturn; |
24 | 25 | import static org.mockito.Mockito.mock; |
|
34 | 35 | import io.netty.buffer.UnpooledByteBufAllocator; |
35 | 36 | import java.lang.reflect.Field; |
36 | 37 | import java.util.ArrayList; |
| 38 | +import java.util.HashMap; |
37 | 39 | import java.util.HashSet; |
38 | 40 | import java.util.List; |
| 41 | +import java.util.Map; |
39 | 42 | import java.util.Optional; |
40 | 43 | import java.util.Set; |
41 | 44 | import java.util.concurrent.CompletableFuture; |
| 45 | +import java.util.concurrent.CountDownLatch; |
42 | 46 | import java.util.concurrent.TimeUnit; |
43 | 47 | import java.util.concurrent.atomic.AtomicBoolean; |
44 | 48 | import java.util.concurrent.atomic.AtomicInteger; |
@@ -1099,4 +1103,58 @@ public void testGetFindPositionRange_SingleClosedLedger() { |
1099 | 1103 | assertNull(range.getRight()); |
1100 | 1104 | assertEquals(range.getLeft(), PositionFactory.create(1, 9)); |
1101 | 1105 | } |
| 1106 | + |
| 1107 | + @Test |
| 1108 | + @SuppressWarnings("unchecked") |
| 1109 | + void testExpireMessagesNeverLoseMarkDeleteProperties() throws Exception { |
| 1110 | + final String ledgerAndCursorName = "testExpireMessagesNeverLoseMarkDeleteProperties"; |
| 1111 | + |
| 1112 | + ManagedLedgerConfig config = new ManagedLedgerConfig(); |
| 1113 | + config.setRetentionSizeInMB(10); |
| 1114 | + config.setRetentionTime(1, TimeUnit.HOURS); |
| 1115 | + ManagedLedgerImpl ledger = (ManagedLedgerImpl) factory.open(ledgerAndCursorName, config); |
| 1116 | + ManagedCursorImpl cursor = (ManagedCursorImpl) ledger.openCursor(ledgerAndCursorName); |
| 1117 | + ManagedCursorImpl spyCursor = spy(cursor); |
| 1118 | + |
| 1119 | + Position pos1 = ledger.addEntry(createMessageWrittenToLedger("msg-1")); |
| 1120 | + Position pos2 = ledger.addEntry(createMessageWrittenToLedger("msg-2")); |
| 1121 | + |
| 1122 | + CountDownLatch expiryMarkDeleteEnteredLatch = new CountDownLatch(1); |
| 1123 | + CountDownLatch cursorMarkDeleteCompletedLatch = new CountDownLatch(1); |
| 1124 | + CountDownLatch expiryMarkDeleteCompletedLatch = new CountDownLatch(1); |
| 1125 | + |
| 1126 | + doAnswer(invocation -> { |
| 1127 | + Map<String, Long> invocationProperties = invocation.getArgument(1); |
| 1128 | + // Pause the expiry-triggered mark-delete so the user markDelete() can complete first. |
| 1129 | + if (invocationProperties == null || invocationProperties.isEmpty()) { |
| 1130 | + expiryMarkDeleteEnteredLatch.countDown(); |
| 1131 | + assertTrue(cursorMarkDeleteCompletedLatch.await(5, TimeUnit.SECONDS)); |
| 1132 | + try { |
| 1133 | + return invocation.callRealMethod(); |
| 1134 | + } finally { |
| 1135 | + expiryMarkDeleteCompletedLatch.countDown(); |
| 1136 | + } |
| 1137 | + } |
| 1138 | + |
| 1139 | + return invocation.callRealMethod(); |
| 1140 | + }).when(spyCursor) |
| 1141 | + .asyncMarkDelete(any(Position.class), nullable(Map.class), any(AsyncCallbacks.MarkDeleteCallback.class), |
| 1142 | + nullable(Object.class)); |
| 1143 | + |
| 1144 | + PersistentTopic topic = mockPersistentTopic("topicname"); |
| 1145 | + PersistentMessageExpiryMonitor monitor = new PersistentMessageExpiryMonitor(topic, |
| 1146 | + spyCursor.getName(), spyCursor, null); |
| 1147 | + |
| 1148 | + CompletableFuture.runAsync(() -> monitor.findEntryComplete(pos2, null)); |
| 1149 | + assertTrue(expiryMarkDeleteEnteredLatch.await(5, TimeUnit.SECONDS)); |
| 1150 | + |
| 1151 | + Map<String, Long> properties = new HashMap<>(); |
| 1152 | + properties.put("test-property", 1L); |
| 1153 | + spyCursor.markDelete(pos1, properties); |
| 1154 | + cursorMarkDeleteCompletedLatch.countDown(); |
| 1155 | + |
| 1156 | + assertTrue(expiryMarkDeleteCompletedLatch.await(5, TimeUnit.SECONDS)); |
| 1157 | + assertEquals(spyCursor.getMarkDeletedPosition(), pos2); |
| 1158 | + assertEquals(spyCursor.getProperties(), properties); |
| 1159 | + } |
1102 | 1160 | } |
0 commit comments