DanielLeens commented on PR #10680:
URL: https://github.com/apache/seatunnel/pull/10680#issuecomment-6368709411

   I prepared a concrete conflict-resolution patch for unchanged PR head 
`0570563e5bf5892908e0776396ed70d09bcfba3c` against `apache/seatunnel:dev` at 
`14a27ac26a0a71b56722f86cdf8ec2779094ceaf`.
   
   There is an important result after resolving: **the entire resolved tree is 
identical to that pinned `dev` commit** (`git diff --cached --exit-code 
14a27ac26a0a71b56722f86cdf8ec2779094ceaf --` passed). There is no remaining 
unique source fix after retaining the newer upstream implementation and tests. 
This makes the supersession discussed above directly reproducible.
   
   The resolution retains both 
[#11431](https://github.com/apache/seatunnel/pull/11431) (`46fefa7c611`) and 
the newer [#12692](https://github.com/apache/seatunnel/pull/12692) 
(`787380c35a2`), including pending-batch/label retention, explicit label-state 
confirmation, ABORTED-only replacement labels, interruption handling, the 
bounded label-state deadline, Publish Timeout handling, and the upstream 
regression matrix. Replacing those files with this PR's old versions would lose 
the newer behavior.
   
   If the branch needs to be reconciled for comparison, use a clean checkout at 
the exact PR head, save the diff below as `pr10680-resolve-conflicts.patch`, 
and run:
   
   ```bash
   git fetch https://github.com/apache/seatunnel.git 
14a27ac26a0a71b56722f86cdf8ec2779094ceaf
   git -c merge.conflictStyle=merge -c rerere.enabled=false merge --no-commit 
--no-ff 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
   # The merge is expected to stop with conflicts in the three files below.
   git apply --check pr10680-resolve-conflicts.patch
   git apply pr10680-resolve-conflicts.patch
   git add -- 
seatunnel-connectors-v2/connector-starrocks/src/main/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksStreamLoadVisitor.java
 
seatunnel-connectors-v2/connector-starrocks/src/test/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksSinkManagerTest.java
 
seatunnel-connectors-v2/connector-starrocks/src/test/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksStreamLoadVisitorTest.java
   git diff --cached --exit-code 14a27ac26a0a71b56722f86cdf8ec2779094ceaf --
   ```
   
   The patch applies to the conflict-marked working files produced by that 
exact merge. If the head/base or conflict output differs, re-evaluate the 
resolution instead of forcing it. The final comparison must be empty; it is 
evidence that the source work is already upstream. Maintainers can use that 
result to decide whether this superseded branch needs any further contribution.
   
   Validation performed: exact merge/conflict inspection, forward patch 
applicability, and full resolved-tree equality to pinned `dev`. No local 
compilation, unit tests, or runtime tests were run, and this does not claim CI 
passed. The old Build check reports workflow-run detection failure; a 
contributor push would require fresh CI on its resulting head.
   
   <details>
   <summary>Conflict-marker resolution patch for the pinned merge</summary>
   
   ```diff
   --- 
a/seatunnel-connectors-v2/connector-starrocks/src/main/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksStreamLoadVisitor.java
   +++ 
b/seatunnel-connectors-v2/connector-starrocks/src/main/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksStreamLoadVisitor.java
   @@ -67,17 +67,6 @@
        private final long labelStateTimeoutMs;
    
        public StarRocksStreamLoadVisitor(SinkConfig sinkConfig, TableSchema 
tableSchema) {
   -<<<<<<< HEAD
   -        this(sinkConfig, tableSchema, new HttpHelper(sinkConfig));
   -    }
   -
   -    /** Creates a visitor with an explicit HTTP boundary for deterministic 
response-state tests. */
   -    StarRocksStreamLoadVisitor(
   -            SinkConfig sinkConfig, TableSchema tableSchema, HttpHelper 
httpHelper) {
   -        this.sinkConfig = sinkConfig;
   -        this.tableSchema = tableSchema;
   -        this.httpHelper = httpHelper;
   -=======
            this(sinkConfig, tableSchema, new HttpHelper(sinkConfig), 0L);
        }
    
   @@ -114,7 +103,6 @@
                                : DEFAULT_LABEL_STATE_TIMEOUT_MS;
            }
            this.labelStateTimeoutMs = Math.max(1, configuredTimeoutMs);
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
            checkBatchMaxBytes(sinkConfig.getBatchMaxBytes(), 
sinkConfig.getBatchMaxSize());
        }
    
   @@ -185,27 +173,8 @@
                    errorBuilder.append(JsonUtils.toJsonString(loadResult));
                    errorBuilder.append('\n');
                }
   -            String message =
   -                    loadResult.containsKey("Message")
   -                            ? String.valueOf(loadResult.get("Message"))
   -                            : "";
   -            boolean labelAlreadyUsed = message.contains("has already been 
used");
   -            if (labelAlreadyUsed) {
   -                // A reused label can belong to a committed transaction. 
Check its state before
   -                // deciding whether the batch is complete or needs a new 
label.
   -                checkLabelState(host, flushData.getLabel());
   -                return true;
   -            }
                throw new StarRocksConnectorException(
                        StarRocksConnectorErrorCode.FLUSH_DATA_FAILED, 
errorBuilder.toString());
   -<<<<<<< HEAD
   -        } else if (RESULT_LABEL_EXISTED.equals(loadResult.get(keyStatus))) {
   -            LOG.debug("StreamLoad response:\n" + 
JsonUtils.toJsonString(loadResult));
   -            // has to block-checking the state to get the final result
   -            checkLabelState(host, flushData.getLabel());
   -            return true;
   -=======
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
            }
            // Publish Timeout, Label Already Exists, a Fail response blaming a 
reused label, or any
            // other non-terminal status: StarRocks received the request but 
the transaction outcome is
   @@ -293,21 +262,8 @@
        private void checkLabelState(String host, String label, Map<String, 
Object> loadResult)
                throws IOException {
            int idx = 0;
   -<<<<<<< HEAD
   -        while (true) {
   -            try {
   -                TimeUnit.SECONDS.sleep(Math.min(++idx, MAX_SLEEP_TIME));
   -            } catch (InterruptedException ex) {
   -                Thread.currentThread().interrupt();
   -                throw new StarRocksConnectorException(
   -                        StarRocksConnectorErrorCode.FLUSH_DATA_FAILED,
   -                        String.format("Interrupted while checking the state 
of label[%s].", label),
   -                        ex);
   -            }
   -=======
            long deadlineNanos = System.nanoTime() + 
TimeUnit.MILLISECONDS.toNanos(labelStateTimeoutMs);
            while (System.nanoTime() < deadlineNanos) {
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
                try {
                    String queryLoadStateUrl =
                            new StringBuilder(host)
   --- 
a/seatunnel-connectors-v2/connector-starrocks/src/test/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksSinkManagerTest.java
   +++ 
b/seatunnel-connectors-v2/connector-starrocks/src/test/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksSinkManagerTest.java
   @@ -24,11 +24,8 @@
    import org.junit.jupiter.api.BeforeEach;
    import org.junit.jupiter.api.Test;
    
   -<<<<<<< HEAD
   -=======
    import java.util.ArrayList;
    import java.util.List;
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
    import java.util.concurrent.atomic.AtomicInteger;
    
    import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
   @@ -64,11 +61,7 @@
            when(mockSinkConfig.getMaxRetries()).thenReturn(3);
            when(mockSinkConfig.getRetryBackoffMultiplierMs()).thenReturn(0);
            when(mockSinkConfig.getMaxRetryBackoffMs()).thenReturn(1000);
   -<<<<<<< HEAD
   -        AtomicInteger labelSequence = new AtomicInteger();
   -=======
            labelSequence = new AtomicInteger();
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
            this.sinkManager =
                    new StarRocksSinkManager(mockSinkConfig, null, 
mockStreamLoadVisitor) {
                        public String createBatchLabel() {
   @@ -83,47 +76,6 @@
         * <p>A later successful flush must still send the record retained 
after retries are exhausted.
         */
        @Test
   -<<<<<<< HEAD
   -    void testUnclassifiedLabelMessageDoesNotChangeLabel() throws Exception {
   -        AtomicInteger attempts = new AtomicInteger();
   -        when(mockStreamLoadVisitor.doStreamLoad(any()))
   -                .thenAnswer(
   -                        invocation -> {
   -                            StarRocksFlushTuple tuple = 
invocation.getArgument(0);
   -                            if (attempts.incrementAndGet() == 1) {
   -                                assertEquals("test-label-1", 
tuple.getLabel());
   -                                throw new RuntimeException(
   -                                        "Label [test-label-1] has already 
been used");
   -                            }
   -                            assertEquals("test-label-1", tuple.getLabel());
   -                            return true;
   -                        });
   -
   -        sinkManager.write("test-record");
   -
   -        assertDoesNotThrow(() -> sinkManager.flush());
   -        verify(mockStreamLoadVisitor, times(2)).doStreamLoad(any());
   -    }
   -
   -    @Test
   -    void testLabelAlreadyUsedExhaustionPreservesBatchForNextFlush() throws 
Exception {
   -        when(mockStreamLoadVisitor.doStreamLoad(any()))
   -                .thenAnswer(
   -                        invocation -> {
   -                            StarRocksFlushTuple tuple = 
invocation.getArgument(0);
   -                            throw new RuntimeException(
   -                                    "Label [" + tuple.getLabel() + "] has 
already been used");
   -                        });
   -
   -        sinkManager.write("test-record");
   -
   -        assertThrows(StarRocksConnectorException.class, () -> 
sinkManager.flush());
   -        verify(mockStreamLoadVisitor, times(4)).doStreamLoad(any());
   -
   -        org.mockito.Mockito.reset(mockStreamLoadVisitor);
   -        when(mockStreamLoadVisitor.doStreamLoad(any())).thenReturn(true);
   -
   -=======
        void testLabelAlreadyMessageDoesNotDiscardBufferedRecords() throws 
Exception {
            doThrow(new RuntimeException("Label [test-label-1] has already been 
used"))
                    .when(mockStreamLoadVisitor)
   @@ -135,51 +87,9 @@
            verify(mockStreamLoadVisitor, times(4)).doStreamLoad(any());
    
            doReturn(true).when(mockStreamLoadVisitor).doStreamLoad(any());
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
            assertDoesNotThrow(() -> sinkManager.flush());
            verify(mockStreamLoadVisitor, times(5)).doStreamLoad(any());
            assertEquals(1, labelSequence.get());
   -    }
   -
   -    @Test
   -    void testLabelAlreadyUsedWithNoRetriesFailsWithoutDroppingBatch() 
throws Exception {
   -        when(mockSinkConfig.getMaxRetries()).thenReturn(0);
   -        when(mockStreamLoadVisitor.doStreamLoad(any()))
   -                .thenAnswer(
   -                        invocation -> {
   -                            StarRocksFlushTuple tuple = 
invocation.getArgument(0);
   -                            throw new RuntimeException(
   -                                    "Label [" + tuple.getLabel() + "] has 
already been used");
   -                        });
   -
   -        sinkManager.write("test-record");
   -
   -        assertThrows(StarRocksConnectorException.class, () -> 
sinkManager.flush());
   -        verify(mockStreamLoadVisitor, times(1)).doStreamLoad(any());
   -    }
   -
   -    @Test
   -    void testReCreateLabelExceptionRetriesWithNewLabel() throws Exception {
   -        AtomicInteger attempts = new AtomicInteger();
   -        when(mockStreamLoadVisitor.doStreamLoad(any()))
   -                .thenAnswer(
   -                        invocation -> {
   -                            StarRocksFlushTuple tuple = 
invocation.getArgument(0);
   -                            if (attempts.incrementAndGet() == 1) {
   -                                assertEquals("test-label-1", 
tuple.getLabel());
   -                                throw new StarRocksConnectorException(
   -                                        
StarRocksConnectorErrorCode.FLUSH_DATA_FAILED,
   -                                        "The previous label cannot be 
reused",
   -                                        true);
   -                            }
   -                            assertEquals("test-label-2", tuple.getLabel());
   -                            return true;
   -                        });
   -
   -        sinkManager.write("test-record");
   -
   -        assertDoesNotThrow(() -> sinkManager.flush());
   -        verify(mockStreamLoadVisitor, times(2)).doStreamLoad(any());
        }
    
        @Test
   --- 
a/seatunnel-connectors-v2/connector-starrocks/src/test/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksStreamLoadVisitorTest.java
   +++ 
b/seatunnel-connectors-v2/connector-starrocks/src/test/java/org/apache/seatunnel/connectors/seatunnel/starrocks/client/StarRocksStreamLoadVisitorTest.java
   @@ -25,10 +25,7 @@
    
    import java.io.IOException;
    import java.nio.charset.StandardCharsets;
   -<<<<<<< HEAD
   -=======
    import java.time.Duration;
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.List;
   @@ -37,19 +34,12 @@
    import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
    import static org.junit.jupiter.api.Assertions.assertFalse;
    import static org.junit.jupiter.api.Assertions.assertThrows;
   -<<<<<<< HEAD
   -import static org.junit.jupiter.api.Assertions.assertTrue;
   -import static org.mockito.ArgumentMatchers.any;
   -import static org.mockito.ArgumentMatchers.anyMap;
   -import static org.mockito.ArgumentMatchers.anyString;
   -=======
    import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
    import static org.junit.jupiter.api.Assertions.assertTrue;
    import static org.mockito.ArgumentMatchers.any;
    import static org.mockito.ArgumentMatchers.anyInt;
    import static org.mockito.ArgumentMatchers.anyString;
    import static org.mockito.Mockito.atLeastOnce;
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
    import static org.mockito.Mockito.mock;
    import static org.mockito.Mockito.never;
    import static org.mockito.Mockito.times;
   @@ -136,25 +126,6 @@
                    });
        }
    
   -<<<<<<< HEAD
   -    @Test
   -    void treatsVisibleReusedLabelAsSuccessful() throws Exception {
   -        StarRocksStreamLoadVisitor visitor = 
visitorWithReusedLabelState("VISIBLE");
   -
   -        assertTrue(visitor.doStreamLoad(flushTuple()));
   -    }
   -
   -    @Test
   -    void treatsCommittedReusedLabelAsSuccessful() throws Exception {
   -        StarRocksStreamLoadVisitor visitor = 
visitorWithReusedLabelState("COMMITTED");
   -
   -        assertTrue(visitor.doStreamLoad(flushTuple()));
   -    }
   -
   -    @Test
   -    void marksAbortedReusedLabelForRecreation() throws Exception {
   -        StarRocksStreamLoadVisitor visitor = 
visitorWithReusedLabelState("ABORTED");
   -=======
        /**
         * Verifies that Publish Timeout is resolved through the label state 
instead of being trusted as
         * success.
   @@ -225,21 +196,10 @@
            when(httpHelper.doHttpGet(anyString(), any(), 
anyInt())).thenReturn(labelState);
            StarRocksStreamLoadVisitor visitor =
                    new StarRocksStreamLoadVisitor(sinkConfig, 
createTableSchema(), httpHelper, 500);
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
    
            StarRocksConnectorException exception =
                    assertThrows(
                            StarRocksConnectorException.class,
   -<<<<<<< HEAD
   -                        () -> visitor.doStreamLoad(flushTuple()));
   -
   -        assertTrue(exception.needReCreateLabel());
   -    }
   -
   -    @Test
   -    void keepsUnknownReusedLabelFromBeingResubmitted() throws Exception {
   -        StarRocksStreamLoadVisitor visitor = 
visitorWithReusedLabelState("UNKNOWN");
   -=======
                            () -> visitor.doStreamLoad(createFlushTuple()));
            assertFalse(exception.needReCreateLabel());
            verify(httpHelper, atLeastOnce()).doHttpGet(anyString(), any(), 
anyInt());
   @@ -379,54 +339,10 @@
            when(httpHelper.doHttpGet(anyString(), any(), 
anyInt())).thenReturn(labelState);
            StarRocksStreamLoadVisitor visitor =
                    new StarRocksStreamLoadVisitor(sinkConfig, 
createTableSchema(), httpHelper, 500);
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
    
            StarRocksConnectorException exception =
                    assertThrows(
                            StarRocksConnectorException.class,
   -<<<<<<< HEAD
   -                        () -> visitor.doStreamLoad(flushTuple()));
   -
   -        assertFalse(exception.needReCreateLabel());
   -    }
   -
   -    @Test
   -    void treatsLabelAlreadyExistsWithVisibleStateAsSuccessful() throws 
Exception {
   -        StarRocksStreamLoadVisitor visitor =
   -                visitorWithLoadResultAndLabelState("Label Already Exists", 
null, "VISIBLE");
   -
   -        assertTrue(visitor.doStreamLoad(flushTuple()));
   -    }
   -
   -    @Test
   -    void interruptionWhileCheckingLabelStateFailsWithoutRecreatingLabel() 
throws Exception {
   -        StarRocksStreamLoadVisitor visitor = 
visitorWithReusedLabelState("PREPARE");
   -
   -        Thread.currentThread().interrupt();
   -        try {
   -            StarRocksConnectorException exception =
   -                    assertThrows(
   -                            StarRocksConnectorException.class,
   -                            () -> visitor.doStreamLoad(flushTuple()));
   -
   -            assertFalse(exception.needReCreateLabel());
   -            assertTrue(Thread.currentThread().isInterrupted());
   -        } finally {
   -            Thread.interrupted();
   -        }
   -    }
   -
   -    /** Builds a visitor whose stream-load response requires checking an 
existing label state. */
   -    private StarRocksStreamLoadVisitor visitorWithReusedLabelState(String 
labelState)
   -            throws IOException {
   -        return visitorWithLoadResultAndLabelState(
   -                "Fail", "Label [test-label] has already been used", 
labelState);
   -    }
   -
   -    /** Builds a visitor with deterministic stream-load and label-state 
responses. */
   -    private StarRocksStreamLoadVisitor visitorWithLoadResultAndLabelState(
   -            String status, String message, String labelState) throws 
IOException {
   -=======
                            () -> visitor.doStreamLoad(createFlushTuple()));
            assertFalse(exception.needReCreateLabel());
            verify(httpHelper, atLeastOnce()).doHttpGet(anyString(), any(), 
anyInt());
   @@ -607,7 +523,6 @@
         * @return mocked sink configuration for one JSON Stream Load target
         */
        private SinkConfig createSinkConfig() {
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
            SinkConfig sinkConfig = mock(SinkConfig.class);
            
when(sinkConfig.getLoadFormat()).thenReturn(SinkConfig.StreamLoadFormat.JSON);
            when(sinkConfig.getBatchMaxBytes()).thenReturn(1024L);
   @@ -615,33 +530,6 @@
            
when(sinkConfig.getNodeUrls()).thenReturn(Collections.singletonList("localhost:8030"));
            when(sinkConfig.getDatabase()).thenReturn("test_db");
            when(sinkConfig.getTable()).thenReturn("test_table");
   -<<<<<<< HEAD
   -        when(sinkConfig.getUsername()).thenReturn("user");
   -        when(sinkConfig.getPassword()).thenReturn("password");
   -
   -        TableSchema tableSchema = mock(TableSchema.class);
   -        when(tableSchema.getColumns()).thenReturn(Collections.emptyList());
   -
   -        HttpHelper httpHelper = mock(HttpHelper.class);
   -        
when(httpHelper.tryHttpConnection("http://localhost:8030";)).thenReturn(true);
   -        Map<String, Object> loadResult = new HashMap<>();
   -        loadResult.put("Status", status);
   -        if (message != null) {
   -            loadResult.put("Message", message);
   -        }
   -        when(httpHelper.doHttpPut(anyString(), any(byte[].class), 
anyMap())).thenReturn(loadResult);
   -        when(httpHelper.doHttpGet(anyString(), anyMap()))
   -                .thenReturn(Collections.singletonMap("state", labelState));
   -
   -        return new StarRocksStreamLoadVisitor(sinkConfig, tableSchema, 
httpHelper);
   -    }
   -
   -    /** Creates one JSON row under the label used by the response-state 
tests. */
   -    private StarRocksFlushTuple flushTuple() {
   -        byte[] row = "{}".getBytes(StandardCharsets.UTF_8);
   -        return new StarRocksFlushTuple(
   -                "test-label", (long) row.length, 
Collections.singletonList(row));
   -=======
            when(sinkConfig.getUsername()).thenReturn("test_user");
            when(sinkConfig.getPassword()).thenReturn("test_password");
            
when(sinkConfig.getStreamLoadProps()).thenReturn(Collections.emptyMap());
   @@ -678,6 +566,5 @@
            Map<String, Object> loadResult = new HashMap<>();
            loadResult.put("Status", status);
            return loadResult;
   ->>>>>>> 14a27ac26a0a71b56722f86cdf8ec2779094ceaf
        }
    }
   ```
   
   </details>
   
   <!-- contributor-patch:10680:0570563e5bf5892908e0776396ed70d09bcfba3c -->
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to