From abca23b3c8430966bf8f2d26651cd167f240d307 Mon Sep 17 00:00:00 2001 From: Loki Date: Sat, 25 Jul 2026 18:42:56 +0800 Subject: [PATCH 01/12] fix: prevent sender control future race --- .../computer/core/sender/QueuedMessage.java | 12 ++ .../core/sender/QueuedMessageSender.java | 100 +++++++----- .../core/sender/QueuedMessageSenderTest.java | 153 ++++++++++++++++++ .../suite/integrate/SenderIntegrateTest.java | 132 ++++++++++++--- 4 files changed, 329 insertions(+), 68 deletions(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessage.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessage.java index 7401daea4..f105ab1ad 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessage.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessage.java @@ -18,6 +18,7 @@ package org.apache.hugegraph.computer.core.sender; import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; import org.apache.hugegraph.computer.core.network.message.MessageType; @@ -26,11 +27,18 @@ public class QueuedMessage { private final int partitionId; private final MessageType type; private final ByteBuffer buffer; + private final CompletableFuture controlFuture; public QueuedMessage(int partitionId, MessageType type, ByteBuffer buffer) { + this(partitionId, type, buffer, null); + } + + public QueuedMessage(int partitionId, MessageType type, ByteBuffer buffer, + CompletableFuture controlFuture) { this.partitionId = partitionId; this.type = type; this.buffer = buffer; + this.controlFuture = controlFuture; } public int partitionId() { @@ -44,4 +52,8 @@ public MessageType type() { public ByteBuffer buffer() { return this.buffer; } + + public CompletableFuture controlFuture() { + return this.controlFuture; + } } diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java index b2006b886..ab4842f39 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java @@ -85,15 +85,12 @@ public void addWorkerClient(int workerId, TransportClient client) { public CompletableFuture send(int workerId, MessageType type) throws InterruptedException { WorkerChannel channel = this.channels[channelId(workerId)]; - CompletableFuture future = channel.newFuture(); - future.whenComplete((r, e) -> { - channel.resetFuture(future); - }); + CompletableFuture future = new CompletableFuture<>(); /* * Control message just need message type is enough, * partitionId = -1 and buffer = null represents a meaningless value */ - channel.queue.put(new QueuedMessage(-1, type, null)); + channel.queue.put(new QueuedMessage(-1, type, null, future)); return future; } @@ -108,7 +105,7 @@ public void send(int workerId, QueuedMessage message) public void transportExceptionCaught(TransportException cause, ConnectionId connectionId) { for (WorkerChannel channel : this.channels) { if (channel.client.connectionId().equals(connectionId)) { - channel.futureRef.get().completeExceptionally(cause); + channel.transportExceptionCaught(cause); } } } @@ -227,75 +224,92 @@ private static class WorkerChannel { private final MessageQueue queue; // Each target worker has a TransportClient private final TransportClient client; - private final AtomicReference> futureRef; + private final AtomicReference> controlFutureRef; public WorkerChannel(int workerId, MessageQueue queue, TransportClient client) { this.workerId = workerId; this.queue = queue; this.client = client; - this.futureRef = new AtomicReference<>(); - } - - public CompletableFuture newFuture() { - CompletableFuture future = new CompletableFuture<>(); - if (!this.futureRef.compareAndSet(null, future)) { - throw new ComputerException("The origin future must be null"); - } - return future; - } - - public void resetFuture(CompletableFuture future) { - if (!this.futureRef.compareAndSet(future, null)) { - throw new ComputerException("Failed to reset futureRef, " + - "expect future object is %s, " + - "but some thread modified it", - future); - } + this.controlFutureRef = new AtomicReference<>(); } public boolean doSend(QueuedMessage message) throws TransportException, InterruptedException { switch (message.type()) { case START: - this.sendStartMessage(); + this.sendStartMessage(message.controlFuture()); return true; case FINISH: - this.sendFinishMessage(); + this.sendFinishMessage(message.controlFuture()); return true; default: return this.sendDataMessage(message); } } - public void sendStartMessage() throws TransportException { - this.client.startSessionAsync().whenComplete((r, e) -> { - CompletableFuture future = this.futureRef.get(); - assert future != null; - + public void sendStartMessage(CompletableFuture future) + throws TransportException { + this.setControlFuture(future); + try { + this.client.startSessionAsync().whenComplete((r, e) -> { if (e != null) { LOG.info("Failed to start session connected to {}", this); - future.completeExceptionally(e); } else { LOG.info("Start session connected to {}", this); - future.complete(null); } - }); + this.completeControlFuture(future, e); + }); + } catch (TransportException e) { + this.completeControlFuture(future, e); + throw e; + } } - public void sendFinishMessage() throws TransportException { - this.client.finishSessionAsync().whenComplete((r, e) -> { - CompletableFuture future = this.futureRef.get(); - assert future != null; - + public void sendFinishMessage(CompletableFuture future) + throws TransportException { + this.setControlFuture(future); + try { + this.client.finishSessionAsync().whenComplete((r, e) -> { if (e != null) { LOG.info("Failed to finish session connected to {}", this); - future.completeExceptionally(e); } else { LOG.info("Finish session connected to {}", this); - future.complete(null); } - }); + this.completeControlFuture(future, e); + }); + } catch (TransportException e) { + this.completeControlFuture(future, e); + throw e; + } + } + + public void transportExceptionCaught(TransportException cause) { + CompletableFuture future = this.controlFutureRef.getAndSet(null); + if (future != null) { + future.completeExceptionally(cause); + } + } + + private void setControlFuture(CompletableFuture future) { + if (!this.controlFutureRef.compareAndSet(null, future)) { + ComputerException e = new ComputerException( + "The origin future must be null"); + future.completeExceptionally(e); + throw e; + } + } + + private void completeControlFuture(CompletableFuture future, + Throwable cause) { + if (!this.controlFutureRef.compareAndSet(future, null)) { + return; + } + if (cause == null) { + future.complete(null); + } else { + future.completeExceptionally(cause); + } } public boolean sendDataMessage(QueuedMessage message) diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index 07fd15929..6e3d4e5ab 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -17,8 +17,18 @@ package org.apache.hugegraph.computer.core.sender; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.apache.hugegraph.computer.core.common.exception.TransportException; import org.apache.hugegraph.computer.core.config.ComputerOptions; import org.apache.hugegraph.computer.core.config.Config; +import org.apache.hugegraph.computer.core.network.message.MessageType; import org.apache.hugegraph.computer.core.worker.MockComputation2; import org.apache.hugegraph.computer.suite.unit.UnitTestBase; import org.apache.hugegraph.testutil.Assert; @@ -64,4 +74,147 @@ public void testInitAndClose() { Assert.assertTrue(ImmutableSet.of(Thread.State.TERMINATED) .contains(sendExecutor.getState())); } + + @Test + public void testControlFutureCanQueueNextControlBeforeCompletionDependentFinishes() + throws Exception { + QueuedMessageSender sender = new QueuedMessageSender(this.config); + ControlFutureClient client = new ControlFutureClient(); + sender.addWorkerClient(1, client); + sender.addWorkerClient(2, new MockTransportClient()); + sender.init(); + + CountDownLatch completionStarted = new CountDownLatch(1); + CountDownLatch allowCompletion = new CountDownLatch(1); + Thread completionThread = null; + try { + CompletableFuture startFuture = sender.send(1, + MessageType.START); + Assert.assertTrue(client.awaitStart()); + startFuture.whenComplete((r, e) -> { + completionStarted.countDown(); + try { + allowCompletion.await(); + } catch (InterruptedException exception) { + Thread.currentThread().interrupt(); + throw new AssertionError(exception); + } + }); + + completionThread = new Thread(client::completeStart); + completionThread.start(); + Assert.assertTrue(completionStarted.await(1, TimeUnit.SECONDS)); + + CompletableFuture finishFuture = sender.send(1, + MessageType.FINISH); + allowCompletion.countDown(); + completionThread.join(TimeUnit.SECONDS.toMillis(1)); + Assert.assertFalse(completionThread.isAlive()); + Assert.assertTrue(client.awaitFinish()); + client.completeFinish(); + finishFuture.get(1, TimeUnit.SECONDS); + } finally { + allowCompletion.countDown(); + if (completionThread != null) { + completionThread.join(TimeUnit.SECONDS.toMillis(1)); + } + sender.close(); + } + } + + @Test + public void testTransportExceptionCompletesInFlightControlFuture() + throws Exception { + QueuedMessageSender sender = new QueuedMessageSender(this.config); + ControlFutureClient client = new ControlFutureClient(); + sender.addWorkerClient(1, client); + sender.addWorkerClient(2, new MockTransportClient()); + sender.init(); + + try { + CompletableFuture startFuture = sender.send(1, + MessageType.START); + Assert.assertTrue(client.awaitStart()); + + TransportException cause = + new TransportException("connection failed"); + sender.transportExceptionCaught(cause, client.connectionId()); + assertFutureFailedWith(startFuture, cause); + + client.completeStart(); + assertFutureFailedWith(startFuture, cause); + } finally { + sender.close(); + } + } + + private static void assertFutureFailedWith(CompletableFuture future, + Throwable cause) + throws InterruptedException, TimeoutException { + try { + future.get(1, TimeUnit.SECONDS); + Assert.fail("Expected control future to fail"); + } catch (ExecutionException exception) { + Assert.assertSame(cause, exception.getCause()); + } + } + + private static class ControlFutureClient extends MockTransportClient { + + private final CountDownLatch startCalled; + private final CountDownLatch finishCalled; + private final CompletableFuture startFuture; + private final CompletableFuture finishFuture; + + public ControlFutureClient() { + this.startCalled = new CountDownLatch(1); + this.finishCalled = new CountDownLatch(1); + this.startFuture = new CompletableFuture<>(); + this.finishFuture = new CompletableFuture<>(); + } + + @Override + public CompletableFuture startSessionAsync() { + this.startCalled.countDown(); + return this.startFuture; + } + + @Override + public CompletableFuture finishSessionAsync() { + this.finishCalled.countDown(); + return this.finishFuture; + } + + @Override + public boolean send(MessageType messageType, int partition, + ByteBuffer buffer) { + return true; + } + + @Override + public boolean sessionActive() { + return false; + } + + @Override + public InetSocketAddress remoteAddress() { + return new InetSocketAddress("127.0.0.1", 8080); + } + + public boolean awaitStart() throws InterruptedException { + return this.startCalled.await(1, TimeUnit.SECONDS); + } + + public boolean awaitFinish() throws InterruptedException { + return this.finishCalled.await(1, TimeUnit.SECONDS); + } + + public void completeStart() { + this.startFuture.complete(null); + } + + public void completeFinish() { + this.finishFuture.complete(null); + } + } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 6ae0008be..0ff2a874f 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -19,16 +19,21 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import org.apache.hugegraph.computer.algorithm.centrality.pagerank.PageRankParams; +import org.apache.hugegraph.computer.core.common.exception.ComputerException; import org.apache.hugegraph.computer.core.common.exception.TransportException; import org.apache.hugegraph.computer.core.config.ComputerOptions; import org.apache.hugegraph.computer.core.config.Config; @@ -46,6 +51,7 @@ import org.apache.hugegraph.testutil.Whitebox; import org.apache.hugegraph.util.Log; import org.junit.AfterClass; +import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import org.slf4j.Logger; @@ -57,6 +63,9 @@ public class SenderIntegrateTest { public static final Logger LOG = Log.logger(SenderIntegrateTest.class); private static final Class COMPUTATION = MockComputation.class; + private static final long BSP_WAIT_TIMEOUT = TimeUnit.SECONDS.toMillis(30L); + private static final long SERVICE_WAIT_TIMEOUT = + TimeUnit.SECONDS.toMillis(35L); @BeforeClass public static void init() { @@ -68,6 +77,21 @@ public static void clear() { // pass } + @Test + public void testWaitForServicesFailsFast() { + CompletableFuture failedWorker = new CompletableFuture<>(); + CompletableFuture waitingMaster = new CompletableFuture<>(); + IllegalStateException cause = new IllegalStateException("worker failed"); + failedWorker.completeExceptionally(cause); + + try { + waitForServices(Arrays.asList(failedWorker, waitingMaster)); + Assert.fail("Expected worker failure to stop service wait"); + } catch (ComputerException e) { + Assert.assertSame(cause, e.getCause()); + } + } + @Test public void testOneWorker() { AtomicReference masterServiceRef = new AtomicReference<>(); @@ -81,9 +105,10 @@ public void testOneWorker() { .withResultClass(DoubleValue.class) .withMessageClass(DoubleValue.class) .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withBufferThreshold(50) + .withComputationClass(COMPUTATION) + .withWorkerCount(1) + .withTestBspTimeouts() + .withBufferThreshold(50) .withBufferCapacity(60) .withRpcServerHost("127.0.0.1") .withRpcServerPort(8611) @@ -109,9 +134,10 @@ public void testOneWorker() { .withResultClass(DoubleValue.class) .withMessageClass(DoubleValue.class) .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withBufferThreshold(50) + .withComputationClass(COMPUTATION) + .withWorkerCount(1) + .withTestBspTimeouts() + .withBufferThreshold(50) .withBufferCapacity(60) .withTransoprtServerPort(0) .build(); @@ -129,10 +155,10 @@ public void testOneWorker() { workerThread.start(); try { - CompletableFuture.allOf(workerFuture, masterFuture).join(); + waitForServices(Arrays.asList(workerFuture, masterFuture)); } finally { - workerServiceRef.get().close(); - masterServiceRef.get().close(); + closeWorker(workerServiceRef.get()); + closeMaster(masterServiceRef.get()); } } @@ -151,10 +177,11 @@ public void testMultiWorkers() throws IOException { .withResultClass(DoubleValue.class) .withMessageClass(DoubleValue.class) .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(workerCount) - .withPartitionCount(partitionCount) - .withRpcServerHost("127.0.0.1") + .withComputationClass(COMPUTATION) + .withWorkerCount(workerCount) + .withPartitionCount(partitionCount) + .withTestBspTimeouts() + .withRpcServerHost("127.0.0.1") .withRpcServerPort(0) .build(); try { @@ -186,6 +213,7 @@ public void testMultiWorkers() throws IOException { .withComputationClass(COMPUTATION) .withWorkerCount(workerCount) .withPartitionCount(partitionCount) + .withTestBspTimeouts() .withTransoprtServerPort(0) .withDataDirs(dir) .build(); @@ -211,12 +239,12 @@ public void testMultiWorkers() throws IOException { List> futures = new ArrayList<>(workers.values()); futures.add(masterFuture); try { - CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); + waitForServices(futures); } finally { for (WorkerService workerService : workerServices) { - workerService.close(); + closeWorker(workerService); } - masterServiceRef.get().close(); + closeMaster(masterServiceRef.get()); } } @@ -233,9 +261,10 @@ public void testOneWorkerWithBusyClient() { .withResultClass(DoubleValue.class) .withMessageClass(DoubleValue.class) .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withWriteBufferHighMark(10) + .withComputationClass(COMPUTATION) + .withWorkerCount(1) + .withTestBspTimeouts() + .withWriteBufferHighMark(10) .withWriteBufferLowMark(5) .withRpcServerHost("127.0.0.1") .withRpcServerPort(0) @@ -261,9 +290,10 @@ public void testOneWorkerWithBusyClient() { .withResultClass(DoubleValue.class) .withMessageClass(DoubleValue.class) .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withWriteBufferHighMark(20) + .withComputationClass(COMPUTATION) + .withWorkerCount(1) + .withTestBspTimeouts() + .withWriteBufferHighMark(20) .withWriteBufferLowMark(10) .withTransoprtServerPort(transoprtServerPort) .build(); @@ -283,10 +313,10 @@ public void testOneWorkerWithBusyClient() { workerThread.start(); try { - CompletableFuture.allOf(workerFuture, masterFuture).join(); + waitForServices(Arrays.asList(workerFuture, masterFuture)); } finally { - workerServiceRef.get().close(); - masterServiceRef.get().close(); + closeWorker(workerServiceRef.get()); + closeMaster(masterServiceRef.get()); } } @@ -331,6 +361,50 @@ private WorkerService initWorker(String[] args) { return service; } + private static void waitForServices(List> futures) { + CompletableFuture result = new CompletableFuture<>(); + for (CompletableFuture future : futures) { + future.whenComplete((r, e) -> { + if (e != null) { + result.completeExceptionally(e); + } + }); + } + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .whenComplete((r, e) -> { + if (e == null) { + result.complete(null); + } else { + result.completeExceptionally(e); + } + }); + try { + result.get(SERVICE_WAIT_TIMEOUT, TimeUnit.MILLISECONDS); + } catch (TimeoutException e) { + throw new ComputerException("Timed out to wait for master and " + + "worker services", e); + } catch (ExecutionException e) { + throw new ComputerException("Failed to wait for master and " + + "worker services", e.getCause()); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ComputerException("Interrupted when waiting for master " + + "and worker services", e); + } + } + + private static void closeWorker(WorkerService service) { + if (service != null) { + service.close(); + } + } + + private static void closeMaster(MasterService service) { + if (service != null) { + service.close(); + } + } + private static class OptionsBuilder { private final List options; @@ -395,6 +469,14 @@ public OptionsBuilder withWorkerCount(int count) { return this; } + public OptionsBuilder withTestBspTimeouts() { + this.options.add(ComputerOptions.BSP_WAIT_WORKERS_TIMEOUT.name()); + this.options.add(String.valueOf(BSP_WAIT_TIMEOUT)); + this.options.add(ComputerOptions.BSP_WAIT_MASTER_TIMEOUT.name()); + this.options.add(String.valueOf(BSP_WAIT_TIMEOUT)); + return this; + } + public OptionsBuilder withPartitionCount(int count) { this.options.add(ComputerOptions.JOB_PARTITIONS_COUNT.name()); this.options.add(String.valueOf(count)); From 1f28ea119ae45086d286f73fa36d1fa202f330d6 Mon Sep 17 00:00:00 2001 From: Loki Date: Sat, 25 Jul 2026 19:55:08 +0800 Subject: [PATCH 02/12] fix ci --- .../computer/suite/integrate/SenderIntegrateTest.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 0ff2a874f..4584e475c 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -63,9 +63,9 @@ public class SenderIntegrateTest { public static final Logger LOG = Log.logger(SenderIntegrateTest.class); private static final Class COMPUTATION = MockComputation.class; - private static final long BSP_WAIT_TIMEOUT = TimeUnit.SECONDS.toMillis(30L); + private static final long BSP_WAIT_TIMEOUT = TimeUnit.MINUTES.toMillis(5L); private static final long SERVICE_WAIT_TIMEOUT = - TimeUnit.SECONDS.toMillis(35L); + BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L); @BeforeClass public static void init() { @@ -92,6 +92,13 @@ public void testWaitForServicesFailsFast() { } } + @Test + public void testCiTimeoutsAllowHeavyInputStep() { + Assert.assertEquals(TimeUnit.MINUTES.toMillis(5L), BSP_WAIT_TIMEOUT); + Assert.assertEquals(BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L), + SERVICE_WAIT_TIMEOUT); + } + @Test public void testOneWorker() { AtomicReference masterServiceRef = new AtomicReference<>(); From 6672de9c9f725868a4b07e03ea7345eac5e3fd8d Mon Sep 17 00:00:00 2001 From: Loki Date: Sun, 26 Jul 2026 14:55:58 +0800 Subject: [PATCH 03/12] fix: harden sender control lifecycle --- .../core/sender/QueuedMessageSender.java | 14 +- .../core/sender/QueuedMessageSenderTest.java | 48 ++++ .../suite/integrate/SenderIntegrateTest.java | 211 ++++++++++++++---- 3 files changed, 229 insertions(+), 44 deletions(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java index ab4842f39..75c300604 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java @@ -250,7 +250,12 @@ public boolean doSend(QueuedMessage message) public void sendStartMessage(CompletableFuture future) throws TransportException { - this.setControlFuture(future); + try { + this.setControlFuture(future); + } catch (ComputerException e) { + // The control future has been completed exceptionally + return; + } try { this.client.startSessionAsync().whenComplete((r, e) -> { if (e != null) { @@ -268,7 +273,12 @@ public void sendStartMessage(CompletableFuture future) public void sendFinishMessage(CompletableFuture future) throws TransportException { - this.setControlFuture(future); + try { + this.setControlFuture(future); + } catch (ComputerException e) { + // The control future has been completed exceptionally + return; + } try { this.client.finishSessionAsync().whenComplete((r, e) -> { if (e != null) { diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index 6e3d4e5ab..288debe1f 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -148,6 +148,43 @@ public void testTransportExceptionCompletesInFlightControlFuture() } } + @Test + public void testControlFutureConflictKeepsSendExecutorAlive() + throws Exception { + QueuedMessageSender sender = new QueuedMessageSender(this.config); + ControlFutureClient client = new ControlFutureClient(); + sender.addWorkerClient(1, client); + sender.addWorkerClient(2, new MockTransportClient()); + sender.init(); + + try { + CompletableFuture startFuture = sender.send(1, + MessageType.START); + Assert.assertTrue(client.awaitStart()); + + CompletableFuture conflictingFinishFuture = sender.send( + 1, MessageType.FINISH); + assertFutureFailedWithMessage(conflictingFinishFuture, + "The origin future must be null"); + + Thread sendExecutor = Whitebox.getInternalState(sender, + "sendExecutor"); + sendExecutor.join(TimeUnit.SECONDS.toMillis(1)); + Assert.assertTrue(sendExecutor.isAlive()); + + client.completeStart(); + startFuture.get(1, TimeUnit.SECONDS); + + CompletableFuture finishFuture = sender.send(1, + MessageType.FINISH); + Assert.assertTrue(client.awaitFinish()); + client.completeFinish(); + finishFuture.get(1, TimeUnit.SECONDS); + } finally { + sender.close(); + } + } + private static void assertFutureFailedWith(CompletableFuture future, Throwable cause) throws InterruptedException, TimeoutException { @@ -159,6 +196,17 @@ private static void assertFutureFailedWith(CompletableFuture future, } } + private static void assertFutureFailedWithMessage(CompletableFuture future, + String message) + throws InterruptedException, TimeoutException { + try { + future.get(1, TimeUnit.SECONDS); + Assert.fail("Expected control future to fail"); + } catch (ExecutionException exception) { + Assert.assertContains(message, exception.getCause().getMessage()); + } + } + private static class ControlFutureClient extends MockTransportClient { private final CountDownLatch startCalled; diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 4584e475c..b2a805da0 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -23,13 +23,13 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; import org.apache.hugegraph.computer.algorithm.centrality.pagerank.PageRankParams; @@ -56,8 +56,6 @@ import org.junit.Test; import org.slf4j.Logger; -import com.google.common.collect.Sets; - public class SenderIntegrateTest { public static final Logger LOG = Log.logger(SenderIntegrateTest.class); @@ -99,10 +97,43 @@ public void testCiTimeoutsAllowHeavyInputStep() { SERVICE_WAIT_TIMEOUT); } + @Test + public void testServiceLifecycleClosesLateRegisteredService() { + ServiceLifecycle lifecycle = new ServiceLifecycle(); + AtomicBoolean closed = new AtomicBoolean(); + + lifecycle.closeAll(); + + Assert.assertFalse(lifecycle.register(() -> closed.set(true))); + Assert.assertTrue(closed.get()); + } + + @Test + public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { + ServiceLifecycle lifecycle = new ServiceLifecycle(); + AtomicBoolean closed = new AtomicBoolean(); + CountDownLatch started = new CountDownLatch(1); + Thread thread = new Thread(() -> { + started.countDown(); + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + }); + lifecycle.register(() -> closed.set(true)); + thread.start(); + Assert.assertTrue(started.await(1, TimeUnit.SECONDS)); + + closeServicesAndJoin(lifecycle, Arrays.asList(thread)); + + Assert.assertTrue(closed.get()); + Assert.assertFalse(thread.isAlive()); + } + @Test public void testOneWorker() { - AtomicReference masterServiceRef = new AtomicReference<>(); - AtomicReference workerServiceRef = new AtomicReference<>(); + ServiceLifecycle lifecycle = new ServiceLifecycle(); CompletableFuture masterFuture = new CompletableFuture<>(); Thread masterThread = new Thread(() -> { String[] args = OptionsBuilder.newInstance() @@ -121,10 +152,18 @@ public void testOneWorker() { .withRpcServerPort(8611) .withRpcServerPort(0) .build(); - try (MasterService service = initMaster(args)) { - masterServiceRef.set(service); - service.execute(); - masterFuture.complete(null); + try { + MasterService service = initMaster(args); + try { + if (!lifecycle.register(service::close)) { + masterFuture.cancel(false); + return; + } + service.execute(); + masterFuture.complete(null); + } finally { + closeMaster(service); + } } catch (Exception e) { LOG.error("Failed to execute master service", e); masterFuture.completeExceptionally(e); @@ -148,10 +187,18 @@ public void testOneWorker() { .withBufferCapacity(60) .withTransoprtServerPort(0) .build(); - try (WorkerService service = initWorker(args)) { - workerServiceRef.set(service); - service.execute(); - workerFuture.complete(null); + try { + WorkerService service = initWorker(args); + try { + if (!lifecycle.register(service::close)) { + workerFuture.cancel(false); + return; + } + service.execute(); + workerFuture.complete(null); + } finally { + closeWorker(service); + } } catch (Throwable e) { LOG.error("Failed to execute worker service", e); workerFuture.completeExceptionally(e); @@ -164,8 +211,8 @@ public void testOneWorker() { try { waitForServices(Arrays.asList(workerFuture, masterFuture)); } finally { - closeWorker(workerServiceRef.get()); - closeMaster(masterServiceRef.get()); + closeServicesAndJoin(lifecycle, + Arrays.asList(masterThread, workerThread)); } } @@ -173,8 +220,7 @@ public void testOneWorker() { public void testMultiWorkers() throws IOException { int workerCount = 3; int partitionCount = 3; - AtomicReference masterServiceRef = new AtomicReference<>(); - Set workerServices = Sets.newConcurrentHashSet(); + ServiceLifecycle lifecycle = new ServiceLifecycle(); CompletableFuture masterFuture = new CompletableFuture<>(); Thread masterThread = new Thread(() -> { String[] args = OptionsBuilder.newInstance() @@ -193,9 +239,16 @@ public void testMultiWorkers() throws IOException { .build(); try { MasterService service = initMaster(args); - masterServiceRef.set(service); - service.execute(); - masterFuture.complete(null); + try { + if (!lifecycle.register(service::close)) { + masterFuture.cancel(false); + return; + } + service.execute(); + masterFuture.complete(null); + } finally { + closeMaster(service); + } } catch (Throwable e) { LOG.error("Failed to execute master service", e); masterFuture.completeExceptionally(e); @@ -226,9 +279,16 @@ public void testMultiWorkers() throws IOException { .build(); try { WorkerService service = initWorker(args); - workerServices.add(service); - service.execute(); - workerFuture.complete(null); + try { + if (!lifecycle.register(service::close)) { + workerFuture.cancel(false); + return; + } + service.execute(); + workerFuture.complete(null); + } finally { + closeWorker(service); + } } catch (Throwable e) { LOG.error("Failed to execute worker service", e); workerFuture.completeExceptionally(e); @@ -248,17 +308,15 @@ public void testMultiWorkers() throws IOException { try { waitForServices(futures); } finally { - for (WorkerService workerService : workerServices) { - closeWorker(workerService); - } - closeMaster(masterServiceRef.get()); + List threads = new ArrayList<>(workers.keySet()); + threads.add(masterThread); + closeServicesAndJoin(lifecycle, threads); } } @Test public void testOneWorkerWithBusyClient() { - AtomicReference masterServiceRef = new AtomicReference<>(); - AtomicReference workerServiceRef = new AtomicReference<>(); + ServiceLifecycle lifecycle = new ServiceLifecycle(); CompletableFuture masterFuture = new CompletableFuture<>(); Thread masterThread = new Thread(() -> { String[] args = OptionsBuilder.newInstance() @@ -276,10 +334,18 @@ public void testOneWorkerWithBusyClient() { .withRpcServerHost("127.0.0.1") .withRpcServerPort(0) .build(); - try (MasterService service = initMaster(args)) { - masterServiceRef.set(service); - service.execute(); - masterFuture.complete(null); + try { + MasterService service = initMaster(args); + try { + if (!lifecycle.register(service::close)) { + masterFuture.cancel(false); + return; + } + service.execute(); + masterFuture.complete(null); + } finally { + closeMaster(service); + } } catch (Throwable e) { LOG.error("Failed to execute master service", e); masterFuture.completeExceptionally(e); @@ -304,12 +370,20 @@ public void testOneWorkerWithBusyClient() { .withWriteBufferLowMark(10) .withTransoprtServerPort(transoprtServerPort) .build(); - try (WorkerService service = initWorker(args)) { - workerServiceRef.set(service); - // Let send rate slowly - this.slowSendFunc(service, transoprtServerPort); - service.execute(); - workerFuture.complete(null); + try { + WorkerService service = initWorker(args); + try { + if (!lifecycle.register(service::close)) { + workerFuture.cancel(false); + return; + } + // Let send rate slowly + this.slowSendFunc(service, transoprtServerPort); + service.execute(); + workerFuture.complete(null); + } finally { + closeWorker(service); + } } catch (Throwable e) { LOG.error("Failed to execute worker service", e); workerFuture.completeExceptionally(e); @@ -322,8 +396,8 @@ public void testOneWorkerWithBusyClient() { try { waitForServices(Arrays.asList(workerFuture, masterFuture)); } finally { - closeWorker(workerServiceRef.get()); - closeMaster(masterServiceRef.get()); + closeServicesAndJoin(lifecycle, + Arrays.asList(masterThread, workerThread)); } } @@ -400,6 +474,27 @@ private static void waitForServices(List> futures) { } } + private static void closeServicesAndJoin(ServiceLifecycle lifecycle, + List threads) { + lifecycle.closeAll(); + for (Thread thread : threads) { + thread.interrupt(); + } + for (Thread thread : threads) { + try { + thread.join(SERVICE_WAIT_TIMEOUT); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ComputerException("Interrupted when waiting for " + + "service thread to stop", e); + } + if (thread.isAlive()) { + throw new ComputerException("Timed out to wait for service " + + "thread to stop"); + } + } + } + private static void closeWorker(WorkerService service) { if (service != null) { service.close(); @@ -412,6 +507,38 @@ private static void closeMaster(MasterService service) { } } + private static class ServiceLifecycle { + + private final List closers = new ArrayList<>(); + private boolean closing; + + public boolean register(Runnable closer) { + boolean closeImmediately; + synchronized (this) { + closeImmediately = this.closing; + if (!closeImmediately) { + this.closers.add(closer); + } + } + if (closeImmediately) { + closer.run(); + } + return !closeImmediately; + } + + public void closeAll() { + List closers; + synchronized (this) { + this.closing = true; + closers = new ArrayList<>(this.closers); + this.closers.clear(); + } + for (Runnable closer : closers) { + closer.run(); + } + } + } + private static class OptionsBuilder { private final List options; From 3d8441a5244b23d37496c0360663d77629408187 Mon Sep 17 00:00:00 2001 From: Loki Date: Sun, 26 Jul 2026 22:28:11 +0800 Subject: [PATCH 04/12] Fix sender control future and service cleanup races --- .../core/sender/QueuedMessageSender.java | 4 + .../core/sender/QueuedMessageSenderTest.java | 64 +++++++++++++- .../suite/integrate/SenderIntegrateTest.java | 88 +++++++++++++++---- 3 files changed, 138 insertions(+), 18 deletions(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java index 75c300604..f004befea 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java @@ -268,6 +268,8 @@ public void sendStartMessage(CompletableFuture future) } catch (TransportException e) { this.completeControlFuture(future, e); throw e; + } catch (RuntimeException e) { + this.completeControlFuture(future, e); } } @@ -291,6 +293,8 @@ public void sendFinishMessage(CompletableFuture future) } catch (TransportException e) { this.completeControlFuture(future, e); throw e; + } catch (RuntimeException e) { + this.completeControlFuture(future, e); } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index 288debe1f..ffd3ff1ea 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -107,10 +107,10 @@ public void testControlFutureCanQueueNextControlBeforeCompletionDependentFinishe CompletableFuture finishFuture = sender.send(1, MessageType.FINISH); + Assert.assertTrue(client.awaitFinish()); allowCompletion.countDown(); completionThread.join(TimeUnit.SECONDS.toMillis(1)); Assert.assertFalse(completionThread.isAlive()); - Assert.assertTrue(client.awaitFinish()); client.completeFinish(); finishFuture.get(1, TimeUnit.SECONDS); } finally { @@ -141,8 +141,54 @@ public void testTransportExceptionCompletesInFlightControlFuture() sender.transportExceptionCaught(cause, client.connectionId()); assertFutureFailedWith(startFuture, cause); + CompletableFuture finishFuture = sender.send(1, + MessageType.FINISH); + Assert.assertTrue(client.awaitFinish()); client.completeStart(); assertFutureFailedWith(startFuture, cause); + + client.completeFinish(); + finishFuture.get(1, TimeUnit.SECONDS); + } finally { + sender.close(); + } + } + + @Test + public void testSynchronousControlFailureCompletesFutureAndKeepsExecutorAlive() + throws Exception { + QueuedMessageSender sender = new QueuedMessageSender(this.config); + ControlFutureClient client = new ControlFutureClient(); + sender.addWorkerClient(1, client); + sender.addWorkerClient(2, new MockTransportClient()); + sender.init(); + + try { + RuntimeException startCause = + new IllegalArgumentException("start session failed"); + client.failStartWith(startCause); + CompletableFuture startFuture = sender.send(1, + MessageType.START); + assertFutureFailedWith(startFuture, startCause); + + RuntimeException finishCause = + new IllegalArgumentException("finish session failed"); + client.failFinishWith(finishCause); + CompletableFuture finishFuture = sender.send(1, + MessageType.FINISH); + assertFutureFailedWith(finishFuture, finishCause); + + Thread sendExecutor = Whitebox.getInternalState(sender, + "sendExecutor"); + sendExecutor.join(TimeUnit.SECONDS.toMillis(1)); + Assert.assertTrue(sendExecutor.isAlive()); + + client.failStartWith(null); + CompletableFuture nextStartFuture = sender.send(1, + MessageType.START); + Assert.assertTrue(client.awaitStart()); + client.completeStart(); + nextStartFuture.get(1, TimeUnit.SECONDS); } finally { sender.close(); } @@ -213,6 +259,8 @@ private static class ControlFutureClient extends MockTransportClient { private final CountDownLatch finishCalled; private final CompletableFuture startFuture; private final CompletableFuture finishFuture; + private RuntimeException startFailure; + private RuntimeException finishFailure; public ControlFutureClient() { this.startCalled = new CountDownLatch(1); @@ -223,12 +271,18 @@ public ControlFutureClient() { @Override public CompletableFuture startSessionAsync() { + if (this.startFailure != null) { + throw this.startFailure; + } this.startCalled.countDown(); return this.startFuture; } @Override public CompletableFuture finishSessionAsync() { + if (this.finishFailure != null) { + throw this.finishFailure; + } this.finishCalled.countDown(); return this.finishFuture; } @@ -264,5 +318,13 @@ public void completeStart() { public void completeFinish() { this.finishFuture.complete(null); } + + public void failStartWith(RuntimeException failure) { + this.startFailure = failure; + } + + public void failFinishWith(RuntimeException failure) { + this.finishFailure = failure; + } } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index b2a805da0..c7f8696cf 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -104,10 +104,34 @@ public void testServiceLifecycleClosesLateRegisteredService() { lifecycle.closeAll(); - Assert.assertFalse(lifecycle.register(() -> closed.set(true))); + Assert.assertFalse(lifecycle.registerWorker(() -> closed.set(true))); Assert.assertTrue(closed.get()); } + @Test + public void testServiceLifecycleClosesWorkersBeforeMasterAfterFailure() { + ServiceLifecycle lifecycle = new ServiceLifecycle(); + AtomicBoolean activeWorkerClosed = new AtomicBoolean(); + AtomicBoolean masterClosed = new AtomicBoolean(); + RuntimeException workerFailure = + new IllegalStateException("worker close failed"); + + lifecycle.registerMaster(() -> { + Assert.assertTrue(activeWorkerClosed.get()); + masterClosed.set(true); + }); + lifecycle.registerWorker(() -> { + throw workerFailure; + }); + lifecycle.registerWorker(() -> activeWorkerClosed.set(true)); + + Throwable failure = lifecycle.closeAll(); + + Assert.assertSame(workerFailure, failure); + Assert.assertTrue(activeWorkerClosed.get()); + Assert.assertTrue(masterClosed.get()); + } + @Test public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { ServiceLifecycle lifecycle = new ServiceLifecycle(); @@ -121,7 +145,7 @@ public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { Thread.currentThread().interrupt(); } }); - lifecycle.register(() -> closed.set(true)); + lifecycle.registerWorker(() -> closed.set(true)); thread.start(); Assert.assertTrue(started.await(1, TimeUnit.SECONDS)); @@ -155,7 +179,7 @@ public void testOneWorker() { try { MasterService service = initMaster(args); try { - if (!lifecycle.register(service::close)) { + if (!lifecycle.registerMaster(service::close)) { masterFuture.cancel(false); return; } @@ -190,7 +214,7 @@ public void testOneWorker() { try { WorkerService service = initWorker(args); try { - if (!lifecycle.register(service::close)) { + if (!lifecycle.registerWorker(service::close)) { workerFuture.cancel(false); return; } @@ -240,7 +264,7 @@ public void testMultiWorkers() throws IOException { try { MasterService service = initMaster(args); try { - if (!lifecycle.register(service::close)) { + if (!lifecycle.registerMaster(service::close)) { masterFuture.cancel(false); return; } @@ -280,7 +304,7 @@ public void testMultiWorkers() throws IOException { try { WorkerService service = initWorker(args); try { - if (!lifecycle.register(service::close)) { + if (!lifecycle.registerWorker(service::close)) { workerFuture.cancel(false); return; } @@ -337,7 +361,7 @@ public void testOneWorkerWithBusyClient() { try { MasterService service = initMaster(args); try { - if (!lifecycle.register(service::close)) { + if (!lifecycle.registerMaster(service::close)) { masterFuture.cancel(false); return; } @@ -373,7 +397,7 @@ public void testOneWorkerWithBusyClient() { try { WorkerService service = initWorker(args); try { - if (!lifecycle.register(service::close)) { + if (!lifecycle.registerWorker(service::close)) { workerFuture.cancel(false); return; } @@ -476,7 +500,7 @@ private static void waitForServices(List> futures) { private static void closeServicesAndJoin(ServiceLifecycle lifecycle, List threads) { - lifecycle.closeAll(); + Throwable closeFailure = lifecycle.closeAll(); for (Thread thread : threads) { thread.interrupt(); } @@ -493,6 +517,9 @@ private static void closeServicesAndJoin(ServiceLifecycle lifecycle, "thread to stop"); } } + if (closeFailure != null) { + throw new ComputerException("Failed to close service", closeFailure); + } } private static void closeWorker(WorkerService service) { @@ -509,15 +536,24 @@ private static void closeMaster(MasterService service) { private static class ServiceLifecycle { - private final List closers = new ArrayList<>(); + private final List workerClosers = new ArrayList<>(); + private final List masterClosers = new ArrayList<>(); private boolean closing; - public boolean register(Runnable closer) { + public boolean registerWorker(Runnable closer) { + return this.register(this.workerClosers, closer); + } + + public boolean registerMaster(Runnable closer) { + return this.register(this.masterClosers, closer); + } + + private boolean register(List closers, Runnable closer) { boolean closeImmediately; synchronized (this) { closeImmediately = this.closing; if (!closeImmediately) { - this.closers.add(closer); + closers.add(closer); } } if (closeImmediately) { @@ -526,16 +562,34 @@ public boolean register(Runnable closer) { return !closeImmediately; } - public void closeAll() { - List closers; + public Throwable closeAll() { + List workerClosers; + List masterClosers; synchronized (this) { this.closing = true; - closers = new ArrayList<>(this.closers); - this.closers.clear(); + workerClosers = new ArrayList<>(this.workerClosers); + masterClosers = new ArrayList<>(this.masterClosers); + this.workerClosers.clear(); + this.masterClosers.clear(); } + Throwable failure = closeAll(workerClosers, null); + return closeAll(masterClosers, failure); + } + + private static Throwable closeAll(List closers, + Throwable failure) { for (Runnable closer : closers) { - closer.run(); + try { + closer.run(); + } catch (Throwable e) { + if (failure == null) { + failure = e; + } else { + failure.addSuppressed(e); + } + } } + return failure; } } From 187a83f6e9b26d6c33157afb9694ba27626903b6 Mon Sep 17 00:00:00 2001 From: Loki Date: Mon, 27 Jul 2026 09:24:08 +0800 Subject: [PATCH 05/12] fix ci --- .../core/sender/QueuedMessageSender.java | 69 ++++---- .../2798d820-e45e-4b0a-9440-5b9a3035333b | 1 + .../9eee6074-26ca-4a24-bb6e-4cf9e2a93220 | 1 + .../value_file_3 | Bin 0 -> 32 bytes .../hgkv_1.hgkv | Bin 0 -> 385101 bytes .../edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 | Bin 0 -> 112279 bytes .../hgkv_1.hgkv | Bin 0 -> 6651 bytes .../hgkv_1.hgkv | Bin 0 -> 1356 bytes .../hgkv_1.hgkv | Bin 0 -> 510526 bytes .../hgkv_1.hgkv | Bin 0 -> 1356 bytes .../e35b2a4a-1fe3-4583-a44e-0102ad0c780f | Bin 0 -> 1336 bytes .../f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b | 1 + .../hgkv/hgkv_1.hgkv/hgkv_1.hgkv | Bin 0 -> 88 bytes .../netty/NettyTransportClientTest.java | 8 +- .../core/sender/QueuedMessageSenderTest.java | 125 +++++++++++++- .../suite/integrate/SenderIntegrateTest.java | 153 +++++++++++++++--- 16 files changed, 299 insertions(+), 59 deletions(-) create mode 100644 computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b create mode 100644 computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 create mode 100644 computer/computer-test/b0b0da9a-f337-43af-8750-49c838504f1c/value_file_3 create mode 100644 computer/computer-test/data_dir1/local_001/edge/-1/a27aa466-b5ee-48c9-91ef-7b6ea2fc70dc/hgkv_1.hgkv create mode 100644 computer/computer-test/data_dir1/local_001/edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 create mode 100644 computer/computer-test/data_dir1/local_001/msg/0/eb8a977f-3da7-49fe-9b71-f7d569ebc5cf/hgkv_1.hgkv create mode 100644 computer/computer-test/data_dir1/local_001/vertex/-1/a03d03d8-7a76-4d9c-80ca-939649f04492/hgkv_1.hgkv create mode 100644 computer/computer-test/data_dir2/local_001/edge/-1/71126e9c-c8fe-495c-bfa2-7d4d7f6f70c8/hgkv_1.hgkv create mode 100644 computer/computer-test/data_dir2/local_001/vertex/-1/313192a6-de7b-46e4-9525-ccd7907c07db/hgkv_1.hgkv create mode 100644 computer/computer-test/data_dir2/local_001/vertex/e35b2a4a-1fe3-4583-a44e-0102ad0c780f create mode 100644 computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b create mode 100644 computer/computer-test/hgkv/hgkv_1.hgkv/hgkv_1.hgkv diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java index f004befea..c3ed4c254 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java @@ -86,11 +86,19 @@ public CompletableFuture send(int workerId, MessageType type) throws InterruptedException { WorkerChannel channel = this.channels[channelId(workerId)]; CompletableFuture future = new CompletableFuture<>(); + if (!channel.setControlFuture(future)) { + return future; + } /* * Control message just need message type is enough, * partitionId = -1 and buffer = null represents a meaningless value */ - channel.queue.put(new QueuedMessage(-1, type, null, future)); + try { + channel.queue.put(new QueuedMessage(-1, type, null, future)); + } catch (InterruptedException e) { + channel.completeControlFuture(future, e); + throw e; + } return future; } @@ -248,51 +256,41 @@ public boolean doSend(QueuedMessage message) } } - public void sendStartMessage(CompletableFuture future) - throws TransportException { - try { - this.setControlFuture(future); - } catch (ComputerException e) { - // The control future has been completed exceptionally + public void sendStartMessage(CompletableFuture future) { + if (!this.controlFutureInFlight(future)) { return; } try { this.client.startSessionAsync().whenComplete((r, e) -> { - if (e != null) { - LOG.info("Failed to start session connected to {}", this); - } else { - LOG.info("Start session connected to {}", this); - } - this.completeControlFuture(future, e); + if (e != null) { + LOG.info("Failed to start session connected to {}", this); + } else { + LOG.info("Start session connected to {}", this); + } + this.completeControlFuture(future, e); }); } catch (TransportException e) { this.completeControlFuture(future, e); - throw e; } catch (RuntimeException e) { this.completeControlFuture(future, e); } } - public void sendFinishMessage(CompletableFuture future) - throws TransportException { - try { - this.setControlFuture(future); - } catch (ComputerException e) { - // The control future has been completed exceptionally + public void sendFinishMessage(CompletableFuture future) { + if (!this.controlFutureInFlight(future)) { return; } try { this.client.finishSessionAsync().whenComplete((r, e) -> { - if (e != null) { - LOG.info("Failed to finish session connected to {}", this); - } else { - LOG.info("Finish session connected to {}", this); - } - this.completeControlFuture(future, e); + if (e != null) { + LOG.info("Failed to finish session connected to {}", this); + } else { + LOG.info("Finish session connected to {}", this); + } + this.completeControlFuture(future, e); }); } catch (TransportException e) { this.completeControlFuture(future, e); - throw e; } catch (RuntimeException e) { this.completeControlFuture(future, e); } @@ -305,13 +303,18 @@ public void transportExceptionCaught(TransportException cause) { } } - private void setControlFuture(CompletableFuture future) { - if (!this.controlFutureRef.compareAndSet(null, future)) { - ComputerException e = new ComputerException( - "The origin future must be null"); - future.completeExceptionally(e); - throw e; + private boolean setControlFuture(CompletableFuture future) { + if (this.controlFutureRef.compareAndSet(null, future)) { + return true; } + ComputerException e = new ComputerException( + "The origin future must be null"); + future.completeExceptionally(e); + return false; + } + + private boolean controlFutureInFlight(CompletableFuture future) { + return this.controlFutureRef.get() == future; } private void completeControlFuture(CompletableFuture future, diff --git a/computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b b/computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b new file mode 100644 index 000000000..0aa6fb546 --- /dev/null +++ b/computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b @@ -0,0 +1 @@ +test data \ No newline at end of file diff --git a/computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 b/computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 new file mode 100644 index 000000000..0aa6fb546 --- /dev/null +++ b/computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 @@ -0,0 +1 @@ +test data \ No newline at end of file diff --git a/computer/computer-test/b0b0da9a-f337-43af-8750-49c838504f1c/value_file_3 b/computer/computer-test/b0b0da9a-f337-43af-8750-49c838504f1c/value_file_3 new file mode 100644 index 0000000000000000000000000000000000000000..2fa63a9853c4f880f84e02ca14594d09ff6103e6 GIT binary patch literal 32 ccmb1OU|^60Vksb&24Wc?mIY!tAeIMW01of~-2eap literal 0 HcmV?d00001 diff --git a/computer/computer-test/data_dir1/local_001/edge/-1/a27aa466-b5ee-48c9-91ef-7b6ea2fc70dc/hgkv_1.hgkv b/computer/computer-test/data_dir1/local_001/edge/-1/a27aa466-b5ee-48c9-91ef-7b6ea2fc70dc/hgkv_1.hgkv new file mode 100644 index 0000000000000000000000000000000000000000..a7702ab97f25a013d92b08e9375c97096d0ba2b3 GIT binary patch literal 385101 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­oQ+o+64kjs#(kn50}kXuP>hsJMdlHpEos;%xr9zq^N zoL9l|$h8h~uY+9dphB~Am1D|X4(h3G<8sG{ z+a2V32f5!tE_jd|9^{G#6*`_v9aC;~P<+qm#C;>HKL@5Cgy8JQa_6PO+{l|CoztWF? zb{&M=2ch=NOE*HMTnQm}Ldc~M>TUeI?ydfCP&gyXVnk7lD2WjTF`^ts6vK#87*PoK zmUmDl^G1=3D1i|LFrxfL6u*el7g6{k%3eg#+pvR@m^TVyM7fJ7b`hm6qR>T@xribc zQQ{&B+=d;Lzr0cWB1&6CVT&kh5k)Pcq(v08h;kND%r@+x)a8vr7g5F{idaMmizr|b zmeHp)mHZ*4b$fXZ*>w{eTphE9+(PPR@52|nD>c@z?ALQ}}x&1+|e~|kh z2TkV_#{XoY=^U)+7wpBKt&MDdI$oe_mIqHIPK&4`j2Q7|LQ zC?m>bM3Iarkr4$lqC7?v$B5FnVF!gXZ{jj&?3rNL@|pfWgB)-=<-IHi?qF# zO+*QcC}0ugE24Nsl&*-v6;ZY}?9dxOUtdUn$Uw+o$WX{|$VkX&$e5&@t>c=g{(P7S znGBf`5rPaDethLiE4+%kfo62kd=_tkhPHYkd2T{NqL7YO;kHcRk2u4=S`h z*E^=%@1XiNE_{r*@j a%YXg9|Ms_E{_Fov{`>!8`hWab_5TA~_=ZgY literal 0 HcmV?d00001 diff --git a/computer/computer-test/data_dir1/local_001/edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 b/computer/computer-test/data_dir1/local_001/edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 new file mode 100644 index 0000000000000000000000000000000000000000..132932123169c1111daaa3e73f5ccf4cec641c8e GIT binary patch literal 112279 zcmZ^p;lEW^R%KJq7-NhvrmNG{>FVl05<(D>Lc|g=7K9Ljh=_}>Fr@9jMK@vA%EO6%OJo(fP(-B0S*Ej1ULwA5a6IUGidJy-`IQs8h%Z%;jQg&^49WA z0KW;~Hv#-6fZqi0n*e?jz;6QhP2S3&y;bp>(BL-#-rRg8;MWBod3*c2y}f)l!0!h5 z-2lHE;CBQ3Zh+qn@Vfzix3@EBZzuh3H2B>BzZ>9p1K!$vN#HjGKjfY5Z~M;jZ2`Y6 z;I{?*wt(Lj@Y@1@TflD%_-)_GpuOey+tT2-1^l*v-xl!O0)AWI?akK)epB#czrX$c zzrTEc!0!+E{Qf@cRRP|L;$O{Qflf{Qf@cRRPf8d?X z4*~v%;GlQ6f6=?kF9Q5UfWHXv7Xkhvz+VLTivWKS;4gZ28ssmc!CwUUivWKS;4cFF zMS#Bu@D~C8BEVm?4BC_P_cy%#DGT=`J{K%#DGT=`J{Kc+m;IRN63*fN;9t+^H z{BRoNvC!bL03HkAu>c+m;IRN63*fN;9t+^HEQ9u(&|{&&V*xxCz+(YC7QkZx-rJlH z@P7oq|Btp0>PO2#0Ui|KK>;2V;6VW%6yQMt9u(j~{b(BGLDAqr0Ui|KK>;2V;6VW% z6yQMt9u(j~&4WBB8ayb#g91D#z=HxjD8PdPJSgCYn-c^6ui!6wfBWd(Uycs&=m3un z@aO=K4)Evzj}GwY0FUndX^=-pgGUE=bbv<(cyxeA2Y7UVM+bOxfJZkE^5|&r=m3un z@aO=K4)Evzj}GwY0FMsv=$1iy-u|P_k<#%01b_0u?Xx|&oGswl0-i14*#e#|;MoG6 zE#TP#p6$VDkY`JSXA5|?fM*MMwt!~~c(#CN3wXAGXFCt_Y-#Xp0nZljYyr;}@N5Ck z7VvBV&ld1(mqB|W;@Q&R*#hrx4jDKgcnBYEpZ15#X#<`%;AsP%HsEOko;KiV1D-bE zX@58k^0aC2v;j{W@U#I>8}PINPaE*G0Z$w7wC6#dHVvLO;AsP%HsEOko;KiV1D-bE zX#<}2GH5TYJZ&00ZNSq8JZ<3M=GcJ`1drv=_W2)L&L8mn0nZ=s`~lA&@caSKAMpGE z&;QUg$n&Sc^9MYC!1D(@f57txJb%FR2Rwhk^PdNK{xo?0faec*{($EXc>aLr4|x87 z=MQ-P%b>kj^!#b?`~lA&@caSKAMpHv4>uP9d?a{KhqrI!@Ny%7Hv)JgfHwkoBY-yo zcq4!}0(c{br$OEb4c-XgjR4*V;Ee#@2;hwX-U#500N%(v$Qz--8v(o#z#9R)5x^S( zyb-_~0lX2w8<_`rBQ$s;fHwkoBY-yocq4!}0(c|9q0Q9*9}6Dck?lJ=vfL5i9Rc1E z;2i{ zhED{~_UQH{9$hXG@Dc$p5%3ZLFA?w(0WT5o5&5%3ZLFA?w(0WT5o z5&5aFXuyjGyy)Z8ATOE*FBZ8oX%0iw3-Cz>5aFXuyjG zylB9S2E6EH(B3b;?UOnK|171Dg)dOBV;MLEAym}hEdcdm(yn4W^ z2fTW~s|UP#z^ezm`gxF7PlHzvc=do+4|w%}R}XmgfL9NA^?+AD5Ay11@ah4t9`Nb` zuO9H~0k0nL>Ve~%9RPkTctPfZGDNE%P9^g$B0;a9aSk1#nvcw*_!p0JjBjTL8CZ9^|&r;I;s63*fc@ zZVTYH0B#H5wg7Gm;I_!sU5gWCd} z+^h}odxF>clkNTa$+ACy`vbT?fcpcuKY;rKxIcjV1GqmwnFhH(G`K&2`vbT?fcpcu zKY;rKxIcjV1Gqo)Aoqs`_Xlu)0QU!Qe*pIfaDM>z2XKD?_h%mD{?Oq50PYXq{s8U| z;Qj#a58(a)?hoMp%!Aw?8r&bi{Q=w`!2JQ-AHe+q+#kUG0oq=-z>NajD8P*Z+$g|}0^BITjRM@Ld5{}LgBu07QGgo- zxKV%`1-Maw8wI#gfEzUra-(Q)qX0JwaH9Y>3UH$UHwtj005=M7qn1H?FU)Qf4Q>?R zMgeXV;6?#%6!4SHY5{*Bc=cztckIlvV}LsbxMP4j2DoE@I|jI8fI9}bV`rv8?ida3 z7~qZp?ik>X0qz*!jsfl%;En#i3~aK`|5Y#!u} z(cq2&?ik>X0qz*!jsfl%;En;OH_Hb6q2Mxny1jLuE?Wn4<1+&aLm1Kc{mtpnUTz^$7Hxpg$Sb%0w3xOISA2e@^BTL-vx zfLjN+b@L#%js~|5aO(iK4sh!Lw+?XY0Jjcs>j1ZI9^}^1;MM_d9pKghZXMv(0d5`O z)&XuE;MUE9+&UWEI>4<1+&aLm1Kc{mtpnUTz^wz^x@FMbKLVWDY$FYSB)Ba<-CoO| zE^7(6mVj#sxR!ux3AmPkYYDiPfNS~FX^?A4gKG)6mVj#sxR!ux3AmPkYYDiPfNMDq zaxH0aEdkdOa4iAX5^ya6*Aj3o0oM|6E$2b5B@M16;93H%CE!{Dt|j1F0U1YAqNwFF#Cz_pwQxt27zmVj#sxR!ux3AmPkYYDiPfNKf3 zmdl{Mf7WmcupPdEDs{ITHvoZDX1bIYOvE-K)n0xl}xq5>`|;GzO9D&V4?n+Cb4 zG`OgMiwd}?fQt&asDO(KxTt`O3b?5AAQzPe7Zq?(0T&f;Q2`efa8Usl6>w1j7j+)w zqSD}^0xl}xq5>`|;GzO9D&V35E-K)n&VyW38eCMsMFm_`z(oaIRKP_ATvWhC1zgm5 zkc&!#iwd}?fQt&asDO(KxTt`O3b?3%i@FTj`-d7Al?E3Ta8Usl75M39V}Y}R8+Cqr zbeArq0H@AV;OYXdF5v0{t}fu} z&VyWC8eCn#)dgH#z|{p@UBJ}^TwTD`1zg>EkgH3Bs|&cgfU66*x`3+-xVnI=3%I&~ zt2+;Jb!l*Q0aq7rbpclwaCHG!7jSg}R~K+~=RvM64X!TW>H@AV;OYXdF5v0{t}fu} z0Se6-ZnE{s>aG3#@8E}~a zml<%G0hjs0G{|M9!DR+qX24|zTxP&!23%&qWd>Ykz-68Xxy&@U%z(=bxXggd47kjI z%M7^8fXfWH%<~|ZnFf~`aG3#@8E}~aml<%G0hbwYnE{u19^^99;4%X)GvG1Y*G6OC%;4;sHTxJ?vX24|zTxP&!23%&qWd>Ykz-0zp=6R6IOoPh|xXggd47kjI z%M7^8fXfV=-)uGTx!~4a++OdC%X$N@H{f~$t~cO%1FkpVdIPRE;Cf%22D#oexZZ&4 z4Y=Nb>kYWxfa?vo-hk^3xZd+1*P8~{8*se=*BfxX0oNOFy#d!7aJ>Q7dmiL^)8Kjo zt~cO%1FkpVdIPRE;CchDH{g2DgIsSKTyMbj23&8z^#)vT!1V@PZ@~2iT<>|1>rI2} z4Y=Nb>kYWxfa?vo-hk^3xZZ&4Jr8odX>h#(*BfxX0oNOFy#d!7aJ>Q78*sgsL3{r^ zcww{lG<+ermY25o|I)Jmfcp=)|A6}sxc`9r54it;`wzJPm!?7PKMn3b;Qj;dKj8iY z?myuE1MWZI{sZp+Jjng0!Tkr^f580*+<(CR2i$+a{RiBC!2O>Gx&Jh{|A6}sxc`9r z54it;`wzJPfcp=)|MMXCp9c3IaQ^}KA8`Kx_aAWo0rwwp{{i=Z9_0Sh;Qj;dKj8iY z?myuE1MWZI{sZnm;Qr5p+>Xz!nJRRj$x0#FfviU2NcqyhYi z;Obu4*2tAbBY+wK)CizP05t-r5kQRqY6MUtSEfN~ga$PNs1ZPo0BQtKBY+wK)CizP z05viXQX@2|5kQRqY6MUtfEoeR2%ts)H3F!Sd5{{RL5%=v1W+S@8UfS@phf^S0;mx{ zjm(482n}ikP$PgE0n`YfMgTPes1ZPo0BU3&q(*2^BY+wK)CizP05t-r5kQRqY6MUt z^B^@sgBk(U2%ts)H3Fy+K#c%u1W+S@8d(PI{iC!Rp+SuRY6MUtfEoeR2yl5L7T`|> zm-*_pYOXG-0aOj3Y5-LOs2V`k0ICL1HGrzQIt@}aG^iRt)c~pnP&I(60aOj3Y5-LO zsG50@s-Z#E0ICL1HGrxCR1KhN096C18bH;|gH#O-ss>OsfT{sh4WMcORRgFRK-B=M zW*($!XiznPssU6DplSeB1E?B6)c~pnP&M-)RYQZS0aOj3Y5-LOs2V`k0ICL1HGry_ z2dNqwR1KhN096C18bH+mss>OsfT{sh%{)le(4cAnRRgFRK-B=M22eGCssXNS^M}Rs4)DfVL0CfbYBS0Mi>IhIr*QP=0hz4~8s3Slf0qO`)M}Rs4)DfVL z0ChAEQb#nXBS0Mi>IhIrfI0%y5ulC$bp)uRd5}7yK^+0=2vA3WIs()YppF1_1gIlG z9nFK(5e@1HP)C3|0@M+pjsSH8s3Slf0qSTTq>gA%M}Rs4)DfVL0CfbYBS0Mi>IhIr z^B{FZgE|7#5ulC$bp)s*Kpg?<2vA3WI+_QmBO25ZppF1_1gIlG9RcbHP)C3|0@Tqm zXzyPRT;1r4hCdhF|LfaAyS@kwP-uWc0~8vd&;W%7C^SH!0SfKbX)PbX)P0dVtac zl-@i@>CvF{0Hp^gJwWLJN)J$afYJk$9-#E*K}wGXr3WZIKbX)P0dVtaclpdh;0Hp^gJwWNr zgOnZ(N)J$afYJk$9-#C9r3WZIKg_L1Qa8n80SHX zkp{&GC`Ldr0*Vn(jDTVU6eFM*0mV2EQj9bxMnEwFiV;wZfMNs`BcK=o#Rw?Id5~hH zK`{b~5m1bPVgwW;pcnzg2q;ECG0uY&BMpiXP>g_L1Qa8n7y-oyC`Ldr0*Y}Sq!?*X zjDTVU6eFM*0mTR?MnEwFiV;wZ^B~1YgJJ{}BcK=o#Rw=yKrsS}5m1bPVq6C8{d*O~ zNP}Vo6eFM*0mTR?M&QOqmB3#Ks^;dlJZ~=Y1e7PBJOSkiC{I9n0?HFmo`CYaISo>t zG$>C%c>>B4P@aJD1e7PBJOSkiD9?G2@}xm|0?HFmo`CWMlqaA(0p$rOPe6IjgOn!? z$`eqYfbs;CC!jn5>B4P@eN3>B4P@aJD1e7Q6vyD!HzZTTdt!=^H zS_BIySU|x73KmeXfPw`SETCWk1$%26q+n@Kuz-RE6fB@%0R;;vSU|x73KmeX^B@IF zgMtMVETCWk1q&!xK*0hE7ErK&f}IB`SQ->8pkM(73n*AX!2${vP_Tf41r+Q&NWs#e zU;zaSC|E$j0tyyTuz-RE6fB@%=RpdV1_cW!SU|x73KmeXfPw`SETCWk1v?K?urw%G zK*0hE7ErK&f&~;TpkM(73n98c@-IiUw3PprQd4 z4X9{9MbCp&Gz}^mP|<*j22?blq5%~RsAxb%11fqRq@rn1(SV8uR5YNX0Tm6XXh1~+ zDjHDH^B@&XgNg=JG@zmZ6%D9pKt%&88c@-Iik=6lXc|;BprQd44X9{9MFT1tP|<*j z22}JsNJZ12q5%~RsAxb%11cI&(SV8uR5YNX=Rqo(1{DpcXh1~+DjHDHfQklGG@zmZ z6}=4F`&Uvbng$gO+}cPR_*+5g{d`;FKVLKssBu7z18N*lfX^H4dn8K#c=x98lwc8lMNLaT?S( zpvD0;4ybWJjRR^NP~(6a2h{jHNR88=#sM`BsBu7z18N*lH9ikg<20yoK#c=x98lwc8VA%kpvD0;4yf^E(B8lMQsXqJ zaX^g&Y8<$|5j*gAf?~Y8t@^u*>H$>`sCq!v1F9ZS^?<4eR6U^T?@ohMJq@ZJQ1yVS z2UIH$>`sCq!v1FC)=r0Qu<^?<4eR6U^T0aXvEdO+0!svc1F^B`4EgQ^EqJ)r6V zRS&3oK-B}P9#Hjws-Fj`dKy$cpy~lt52$)T)dQ*?Q1yVS2UPt$NY&Gz>H$>`sCq!v z1F9ZS^?<4eR6U^T=RvBT22~HJdO+0!svc1FfT{;nJ)r6VRX-0>^)#q@K-B}P9#Hjw zss~g(py~lt52*TikgBIa)dQ*?Q1yVS2UIH$>`sCq!vFN5~}C7Y_JLDd7Q9#Hjw zss~g(@biuQfjffoytnNG_ZA-j^Z`I00Q3Ps9{}_LKpz0~0YD$PHx1GUXwU}$eE`r0 z0DS<^2LOEl&<6m00MG~KLHYm<`T(F00Qvx+4*>cApbr500H6;5`oKI$AD}@W0Q3Ps z9{}_LKpz0~0YD!B^Z`I0mJ^<(gfIa}|1AsmN=mUU00O$krAbo%aeE`r0 z0DS<^2LOEl&<6m00MG{jePAA>573|w0Qvx+4*>cApbr500H6;5`T(F0%!Bj+8uS4` z9{}_LKpz0~0YD!B^Z`I00Q7-*kUl_zJ^<(gfIa}|1AsmN=mUU00O$jNJ}?i`2WZd- z0DS<^2LOEl&<6m00MG}3yBk9Qz7iDd{cUHszc>S+GXOdRpfdnE1E4biIs>3H06N3{ zX^_r9gU$fx41mr6=nR0)0O$;W&H(5PfX*-v(iv#b833ID&=~-o0nix$odM7p0G$EQ z8RkJc0}VO@pfdnE1E4biIs>3H06GJpGXOfnJV3H06GJpGXOdRpfk*abOsu920&*3bOu0Y0CWaGX8?2t zKxY7ShIx?AK!eTz=nR0)0O$;W&H(5PfX)Eu41mtC4BGqGhW9p(LBrRAihi(d9S;`k z0JIK3>j1P4K30IdViIsmN$&^iFE1JF7Etpm_H=0REq z4O$1FbpToipmhLR2cUHTS_hzY09wa9Nb8_M>j1P4KzD^= z9W-bifYt$M9e~yWXdQso0cah7)&Xc8^B}E*2CW0oIsmN$&^iFE1JF7Etpm_H0Ig#l zq;=4sbpToipmhLR2cUHTS_hzY09ps2bj1Ql zd63pYgVq6P9e~yWXdQso0cah7)&Xc8fYvb&(mH6+IsmN$&^iFE1JF7Etpm_H0IdVi zI+j6u|9(>Iph4>Z?r%H<_(o9U54X+a;bJC$W&&s?fMx<{CV*xFXeNMW0%#@=r$L$t z4Vnp{nE;vzpqT)g380w(nhBtp0Gi1>NHd{9GXXRcKr;a}6F@ToG!sBG0W=dpGnofz zCNyX!fMx<{CV*xFXeNMW0%#_HW&&s?^B~QH2F(P}OaRRU&`bc$1kg+X%>>X)0L^3` zq?yp5nE;vzpqT)g380w(nhBtp0GbJ)naqPU6B;xVKr;a}6F@ToG!sBG0W=dpGXXS{ zd5~s8gJuF~CV*xFXeNMW0%#_HW&&s?fMzle(oAU3OaRRU&`bc$1kg+X%>>X)0L=u@ zOy)tF2@RSFpqT)g380w(nhBtp0GbJ)nE;x}GHCB#glZ-^I-wLY! z(YC!jTI>bTUI6U{&|U!T1<+mq?FGC(4gS}8V;c0 z02&UU;Q$&Apy2=-4xr)8gESl(G#o&~0W=&y!vQoLK*Iqv96-YXG@N;mhC_pf186va zh689gfQAETIDm!&XgGj|GY`^mXwYx~4F}M001XGwZ~zSl&~N|^2heclK^hJX8V;c0 z02&UU;Q$&Apy2=-4xr%x8qPdO!=XXL0W=&y!vQoLK*Iqv96-YXG#o&~nFnb&G-x=0 zh689gfQAETIDm!&XgI*5jq?EiAm|KFwk_z%VnKiw1ZY8k76fQPfEEO3L4XznXhBb= zL0S+ES`eTG0a_5C1p!(RpalV15TFGCTF^X53!*^_0<<7N3j(wtKnnu2AV3QOv>-qW zng?k?G-yG976fQPfEEO3L4XznXhDD$1ZY9?AT5XnEeOzp04)g6f&eWD(1HLh2+)E6 zEodI31<{}d0a_5C1p!(RpalV15TFGCS`eTG&4aWc8nhrl3j(wtKnnu2AV3QOv>-qW z0<@rckQPLP76fQPfEEO3L4XznXhDD$1ZY8k7Bmmif@si!04)g6f&eWD(1HLh2+)E6 zEeOzp=0REz4O$SO1p!(RpalV15TFGCS`eTG0b0;JNDHDt3j(wtKnnu2AV3QOv>-qW z0<<7N3t9&4{X68x8*8HB9|f)B>9$8bT|5fVqX0b$(4zo73eckfJqpmH06psIG)Rx4 zL5~9TC_s+_^e8}&0`w?Aj{@{4K#!US=}|Q3QGgx==uv9;8Rnphp3E6re`|dK92X0eTdmM*(^iphwMv z^e7tiC_s+_^e8}&0`w?Aj{@{4K#v0SsCkecMS~s%=uvBhc*e-^Zt=i5H^eDN_r9|QC;KpzA2F+d*!^f5pm z1N5=y(;$6}27L_B#{hi{(8mCM4A92_eGJgY0DWv8q>s^{j{*7^ppOCi7@&^<`WT>( z0s0uAkIjShF&gwSKpzA2F+d*!^f5pm1N1RK9|QEUd5}IvgFXi6V}L#e=wpCB2Iyme zJ_hJxfIc=4(#L4f#{hi{(8mCM4A92_eGJgY0DTP5$L2x$7!CRuppOCi7@&^<`WT>( z0s0uAj{*AFJV+m-K_3J3F+d*!^f5pm1N1RK9|QC;Kp&e2>0>nLV}L#e=wpCB2Iyme zJ_hJxfIbH3WAh+=j0SxS(8mCM4A92_eGJgY0DTP5#{hk79;A=appOCi7@&^<`WT>( z0s0uAj{*7^ppPws_Wt#|K1PE+2IymeJ_hJxfIbF1+ZY<~FM@{ii*0B7#o}y$&Iagg zfX)W!Y=F)N=xl(_2Iy?Rm5 zX9ILLKxYGVHb7?sbT&X|19Y}|kj_Sf&IaggfX)W!Y=F)N=xl(_2Iy>n&NdIy*=W$& z0G$oc*#Mml(AfZ;4ba&Doej|0=0Q3e4LTd3vjI9AptAuw8=$iRIvb#~0Xo|}NN1x# zX9ILLKxYGVHb7?sbT&X|19Ub(XPXDfX)W!Y=F)N=xl(_2Iy>n&Iagg^B|p# z2AvJi*#Mml(AfZ;4ba&Doej|00G(|fq_feWvjI9AptAuw8=$iRIvb#~0naxU2mGs` z1-;nzx)+Pr0eT&v*8zGRpw|I<9iZ0%dL5wGy_g2+bu{R8fL;gab%0(6=yiZz2k3Qx zUI*xP^B}#B2E7i@>j1qD(CYxb4$$iWy$;ap0KIM=q}S1)*8zGRpw|I<9iZ0%dL5wG z0eT&v*Uf|UIvVskK(7PzIzX=j^g2MV1N1sTuLJbDd5~U5gI)*db%0(6=yiZz2k3Qx zUI*xPfL=Eb((7o@>j1qD(CYxb4$$iWy$;ap0KE>->*hgv9SwRNpw|I<9iZ0%dL5wG z0eT&v*8zInJV>vjL9YY!IzX=j^g2MV1N1sTuLJZtK(Ctz>2);db%0(6=yiZz2k3Qx zUI*xPfL;gab@L#-jt0FB(CYxb4$$iWy$;ap0KE>->j1rO9;DaNpw|I<9iZ0%dL5wG z0eT&v*8zGRpw}&f_WlQjUu-;(hJO?EsF&Mj_;N8rKr;k1LqIbGG($i$1T;fHGXyll zm(w84kOs{V&9;6x4pcw+1A)pxonjxSW0-7P983LLi zpc&4CG(#FRLqIbGG($i$1T;fHGXyk4Kr;k1!+DTqNP}hwXoi4h2xx|YW(a78fMy72 zhJa=`57G>2&iRC zYkjwEkKZl!2xyOh_6TT?fc6MzkAU_FXpeyQ_}w%}d!#{o1hhv$djzycKzjtVM?iZ7 zv`0XDoCj%-G-!{2_6TT?fc6MzkAU_FXpeyQ2xyPjKp z5zrn1?QtHYJ<^~(0@@>>Jp$SzpgjWGBcMG3+9RMn&V#f^8nj11djzycKzjtVM?iZ7 zv`0XD1hmI_koHJ}_6TT?fc6MzkAU_FXpeyQ2xyOh_BapH9%;}X0qqgc9s%tU&>jKp z5zrn1?Gex(=Rw*d4ca51Jp$SzpgjWGBcMG3+9RMn0@~v|NPDC~djzycKzjtVM?iZ7 zv`0XD1hhv$dz=Spk2GkHfc6MzkAU_FXpeyQ2xyOh_6TT?^C0b!2JI2h9s%tU&>jKp z5zrn1?Gex(0qt=awD&)eXpb~#kAU_FXpg|ljZXsqA-wv^E3bTSXZMu{{NFbQe~GyzBx$a9Hes&(mHovnP+OAqeu4~qbdV-GNEcn3sgI5xjdYMsI!G%Wq?ZoTOb6+vgS68@`spAIb#11WI(qcfLGSmJ zb=6VRRtM>;gEZDbI_n^V+U!ngLK(J+U(j) zjdt|tw1c$TL3-^V&32G(J4m}7q~8wGa0ltQYcuuS(WB`O(sc)EyMun(^VWDrP3Ik? z^$yZ|2Wh@*GqvB*qyG-lfCuTogS6m5dhj4kc#tkUNE;rc53kMCiARrCJV-Adq!|y= zjR$GRgY@G;8uB0=d61U8Hd9j`J-YHBZF!KsJV;|6q%#ltdCyyK9yQH*knX%TQ-2;k z8uTC?dXN@9NRJ+*Ne|Mc2WiuT^yxtw_1a9Wdi3bkgEZ?wy7eIKdXRoSNW&haV-M1@ z2kF^+Gq2;duW$TT*B(9E_8@(Gkj6bo=N_bW5BjcW`=6nB>(1ooJN0uYeh$UYq4+rz zKZoMyQ2ZQt4#m%*_&F3mhvMf@{2Yp(L-BJc ze!em@eojyP9EzVq@pCAC4#m%*_&F3mhvMf@{Cs6*{G6WnITSyK;^$EO9EzVq@pCAC z4#m%*`1#7r_&GiCb0~fe#m}MmITSyK;^$EO9EzVq@$;3L@pF3O=TQ6{il0OAb0~fe z#m}MmITSyK;^&?Du*ad~>;^3eM|+XJP8rMNtO zad{{%55?u7xcth@xI8^^c_=Oq#pR*6JQSCQ;_^^j9*WCDaru>*ad~>;@=#nJipxWB zc_=Oq#pR*6JQSCQ;_@pqO z$pR=@03{2cWC4^cfRY6(Gm{1MBnzNq0hBC&k_Aw*07@1> z$pR=@03{1nW+n^hNftoK0_Z?b?_lYJ(ubvF0Z$xiEm^QKGg&})vH(gJK*<6qSpX#q zpkx7*EP#>)P_kfUX0m{uWC4^cfRY7JvH(gJK*<6qSpX#qpk%?y%wz#Q$pR=@03{2c zWC3)xr+2ROS?PQ!S+FwmLVJ=0d}^`)N)|xL0w`GkB@3Wr0hBC&k_9U>lLho73!r2H zlq`Uf1yHg8N)|xL0w`GkB@0$&CJX3E7C^}YC|Lj{3!r2Hlq`Vm^tA4lz6#BraIZbd z0zTn>Ysms?$pR=@03{2cWC4^cfRY6(zcX1tPqF|?7C^}YC|Lj{3!r2Hlq`Uf1yHh} zGp8(|Cs_a`3!r2Hlq`Uf1yHg8N)}+iOBM{oxi=oYobGXQAY4mt7K{gK>N~rOtEd0< zDIs2OLO}UAC~S`pdKuHKF2>~S`pdKuHKF39&LW2|-U10!l(aNeCzj0iEsXohv0F`0M%BJ`c@%d!ao^2%bwq zKuHKF2>~S`pdKuHKF2>~S`pd~S`pd#{y86y;ZGC5V@%4P-8&ht)(cFNN8&GCI$qgtI zpbUWW`4Hb>e0M0h@y0wexj|2I14?c{$qgvE0VOw}iEkT5^NhN39(yeH@z4_HcWW z8+<}?14?c{$qgvE0VOw}@(C#lv7fZdlQ&t*`I!PX{sfo!u>Ge{)KcH=8C<(gez6C}{#^E|fHZG8M{D zC^O&8Z`(JM?>T-oJxLQNX#yoppri?uG=Y*PP|^fSnm|dDm6=HsdXgqk(gaGHKuHrQ zX#yoppri?uG=Y*PD>IWO^dwE7qzQDOr;s$E_Cae&6KWr|mNcREacc9~9&Yz1r6Z-J z37?QOfs!Ur(gaGHKuHrQX|nP=lP2^eO`xO+lr({oCQ#A@N}51P6DVl{B~4alCQax` znm|btC}{#EO`x+qg`^3!&ss~GQ2RW!`D~LW^nB6hE|$J5T`DC_cp_;6B~75D36wNh z`JG7IWO^dwE7qzRNXfs!Ur(gaGHKzDiy zNfT;cr8b{!(uAI``&`n5+BdB|D1BRcSW24kMA8IGnymcJqzOGq6DVl{B~75D36wN} zk|t2n1WKAfNt4c;(uAI*36wN}k|t2n1WKAfNfRh(f@v;kG7#t9`08@HPf3zD{!5yS zu6laYWK`?wO_NcruQyFbb#ZpER=%^lczLG3HD%0O%@`;d1LgZb$rvc#21>?2`7Tg0 z2Ff>iYo3`eMo+#M#CIR(10`diWDJyyfs!#$G6qVk}*&+21>?2$rvaZ z10`diWDJyyfs!#RGm|m&Bx9gt40NEsI2l9jgVvHU)IMr08AI*k)aJ8I#?bRgpF2|e zt?2$rvaZ1D)+JPR3CCthHnewa-(V&o&uD&li0z8AI*M)-IL)q;$EIjNyr743vyn z`JKradXh0vG6qVIWZ^dw`TWDJyyfs!#$G6qVaAKW1wUV zl#GFrF;FrFO2%~Nlri)qW1wUVl#GFrF;FrFO2$CR7z}dBn1ML=#zU9Woik>1)zh0X zqgq#Q#*Auxy%{sAi?f5Z@@7nb^S=L8zUIEOySRJ4VeJ)8v?aS6Km6AmK^>S-} zTDnq760Q8sBoUvGB!ZGeP?88r5!a5GAvDi?+@2&6&n1bV zBoUM(f|5i~k_bu?K}jMgNz}8Ql8Bxp5tJl?l0;CF2ucz`Ng^mogc&YLG!Wdp&cXk(l&o_T(%BOdl zPf+p+%5Q;^Pf&gdlzf8nJD}tflwa}AJTpIvp5zmhp8zGFp!@(R-yhpP=Lulzdv5nS7!r`2;1OpacCS$tP+bw3d9L z_EBreCu$$3HlJui9iN79gE%`+4SZlviI$laXt^Cg96Q7WLf|5^A@(D^l zLCGg5`2;1OpyU&jd|H{Ae4;1$1SOxK`t3+UKdwXPbPY=Zij< ze4_ScYnMvNC;oc5wd51EE3N%mXr6hsJ;^7YOFlu#Cn)&@C7+<=6O?>{l21_bY2|E_ zPxK_8pyU&je1eisQ1S^%K0$Z-&67{mzWQ%}XYz@julro`iP|@=pP=Lulzf7cPf+p+ zNYlddh=;i>+8*@QC*xJtd%#P`kVLt7YQ}@=F|9? z+I#b9RBP}%yNko;_k4d!t?xIrprjU*UkD|&p!_~4sRiZNK}jtrzwP_;%=}b(l3GxH z7?jk4^0T0%7L*?aQfp;qQj4CX7L?S2l3Gww3rcE1Ni8U;1tqnhq}IyJ zq!v9%Ehwo49q6}CYEk>3wWJock6KG=QTsTx`D~L~^nB9ij+ByG{Pk#SNiAx}T1#qC zJKoxlL-WiN?MZ6!Tv7{4YC%aYD5(V{wV=}F+UNi6?@VgZ^F^OaYEk>LwM(U>7Jt3mT2hPJmDZA4E5GwRNiBN5 z?sG{kYTvY$)S~unYY$6FE&lqbwWQX{?|j^zq!!OTY3-j%PfJNH`jT2uQVU9IK}oI7 zoKlOPq!yIaf|6QLQVU9IK}jtrsfDR6sWlMi-uU2hx^rrcu6lY?YgFs%O|4O_uQ#3^K8MTj7 zo6j~`M$adG?no(F#$S)NmMo)othHnrwd1WN%T|8piT3<%>0~Kc#%CqVpkx`8EQ69| zP_hh4maWW8meG?egOX)XvJ6U=L1+7ol4aCBYb{wu?eo;;vrU%K^F^OamQnk%wM(UB z8GpUpTC$AVmDZAFE5GwGSq3G`R%Ry4=t-7A$ucNe z1|`d&WEqq!gYNVjCCjLNmD+r^$ufGr?sLg9YTvY$ETi^qYY$7wGXDCgwPe}K?|j^z zWEsyrX)Res?P+WOTzXbYmeH3igOX*PIb|6=$ucNe1|`d&WEqq!gOX)XvJ3-TvTPvE zz45r^bmuG^UG?;4*{Igln`NU~UvHL;>f-ERt-M**-@I>n&AnMRKBo5GEF0Ate6ws+ zYw^vpQLU-(>@KdJ-~NLs;eODBgOYGiP6JB9K{*R32?ymQpd=iWbNInLGsi+t5)R5C zKuI_#M*t<^pd0{{goE<)p(NbO%p3+iISYtG8XEy6;h-cOl!Swla8MEsO2R=&xRsen zIC_$BP!bM0(CJAyY9F+ggroLRYe_h2AE!2-Z4!>2Px{=EQWB289&IfNN9|Z^NjPf9 zTT8;N{LT~YNy72m$<}_abgGnuqb~^uCE=hX9F&AxnVE#6CkY27;h-cOl!SxMc6t(y z+GnjL;i!F{+I+T2IC{S5b4fUAU$%Csl!W82ms?B1QM=Mw5^m*pUTsejj_0nmmV~2r zy|uqA-6$pD=u5&uNw}4nNjQ3va8MEsO2R=&I4B7RCE=huot}iF_El>0*(TxW`MS>~ z;i!GnS`v=hx2-)aCE@t%qt=peE5Gw`dy;TG_oTHX9JQydCE=(&Ywcf3&r3+?qqApL29R3 z`~A{SO36X`l7mokaAjt4ke=iqlpKVTgHUo1I@?L-O36X~dcL*f;L6Mk?MV*u+{MyZxwYgVwJWV92UliZZBKHL=dQJu9He%=wd5eR8?F6S>1U2#99)_C zxIM{1o_o?-a**27){=wNp0$=7r1reEe+@0(H{~GR$w4SN2qg!hb@kZr8fu112y&L;HcKtn}efTV{Zj?rcX9fh+YhI7{9)4(%27f|M<@pgB^{w0 zBb0Q6a)?mU@rU!w94S3XM<@pfB^{w0ACz>2a(GbE5z5g)Nyn9$IY@evj!=#bN;*P0 zG$>~VahPN4prj*|bcB+QD>IXh^dudjq$6~opL(#AbmXreww83HcBr+azFjj?|8}mUN_cthJ;gwd1WN9am6YuD6zSq;{jVq$9PYBlOq#>#Wb4eJ<%pchV6`IzmZDDCr0# z9icn@l)I&*%FG`%Goc(Xl+1*3yihU|%HcxEOejYS zB{P3C&&)y7lgxy2tWYu&%ArEZOejYRB{QKMD3r`xnVI9ICz%Q5Frj27l%s@_nNSWA z$~i(D@Yqi%nYl7EnMqGF6G~=62l@#IOUX?B`eAFyOlpT(OJ=UjJlvjSCeIydEtyH} zXluz#YR6hjW>P!eS~7EG=85(sGkNZ0YspM%r&>#9QcGq+$xP^U`~EOA@6eg{Br|y~ znF%E`p=2g>wojZZB{TW!`PPz|E5GwXdy<(vcd@l(CbdhgB{QjAZY`Nf?MiFO%$1o} z+mp=XxofQ@GpSu~EtyH}Mr+ATYROC}nYl9aW}o|;(ydZ5lTS!yLdi@hnF-zL6L(9= z%$1q<+LO%W6YjT`%%t|9wPYr>hpitQ zN$q)S$;{52GL!CPCiJ4u{d?(UDVa%MG80N>VlYc)4#c@Pp0ucCUuxCTo0;Q*ntC&H zRBP+a%u%heH#0}IR^H6)Z{9b(=HAR4&(_|XnWI{RZ)T2aExwsKsx|dyW~cA_uW)Mf z&CKy^jlP*Vs;uPPLXKrIsXxlBCe-_9aPIW}a!!AC*2WB}w_L zBq?;Ze?3=9lJeK{ttClUW?pDdl9cBzww5HNcB!=_DYeV3B}u7WX)Q^*GV^MClB7I$ zt+ga6wd<`VNvYjvElEl(NeU%NS7zSqb4gOVZ?*QfrQ4+>DSb&&=uZE7x0EDZnR%~0 zNm4%HerrimY7bgVl2UuvT9TC7qt=q7D>EOrCrQe4Pg+ZoQhVB3l9bxB){>;up0}1H z?aV1j=}wYDFZx`Pl-kSI{-g9=DM^Z%EJ->L=id0u;<)>=td`y+9S_vho1~*!TW^w% zYK^@~I;yquCTV~3zUejhCh2&#_TD5N)f#-0bX05cP0~@VsW(a2rq|}1q~qBdeUo%l zYxPaiQLWiGNk_HzzO%dddrtn~l&=SyuTU-nO1?t53Mlysxd15n3g!5rx4kce# zX66Fu$@xQE%+LUIpmea5eC4knww8RQcBr-F>&nc-?Mc4!+>zFjuhfpVmVBjlthMAT zwd1WNUsq1^p- zDf!B?=UYp@uFSm9p5!afU2HA+O6^i>$yaKZTT8xDyV6?nb!Fz&_9S098h!J1RBQFk*HNw6H(y7! z_TGH$^nL#YQVoA+cX9kA;)hcTf7ld;cDynuHwGnzq1+dg6oztJP*NDmU41yu%+=A8 z6ozt9P*NDmH9<*XD3=5!g`r##loVc>nG2&QDGcR$prkOA%Yl-@P_70_3PZUVC@H)$ zGuK2!UeNajYQ~Rj3q%gIQQ=88=DNN5NeeOspDa>Dwww4s8cC59e zFty{YC52ah=ZW?tg?a8|Ye`{hr&>!2Q%ed%Nnz-8`;x*dGtaaqDa>=9ww4s8mK280 z_OItkpOuor^nIS%e6~qpdcNp$NnvVVwsxtM6y~p&TT2R4yV6=xc;$CqZBJ5|=dQJu z6sC5)wWKh$8?7aUsU?M>r0~kjn|&@RO!uwUlETz(x0V#9mK28W^sjeIUxntgO$zhe z*X>RUQ~Rd1q%gH_TYFea3iH=TttEw5e&^%%B!zkINoz@AYEN5B3R8R5T2h$W^VX8W zojIj2-AQ5SMW0IwQ+wH3QkdFzttEvqiRGVi2jbitA6ZU!PT|p2Pj3p3YF)i4JgW8e zrtqjP&JNbfo5KCg`=;02o5JH`YVS?qQLVu@g-5j(-xMCzntD@sZF+6KDLkI7(Km%h zwN~F09@UzCQ+QNs?@i%O-}m1?)$p6bLp$CvlzW6;Z7sJ* zE!hm^4xwZ-lp8!W&&-9=lWc}^eNeI)%H=`HW++z&C7YpK9F%NcnVD;(C)o_;(x7BB zlq-Xh%}_23N;X5eE-2Z&GBcM)PqG=xRY3=OqPZw)xhIGV96EzODkYn#eVp2Sw#jCC zKIwBuO37yadbG7)or`wlo zUYU8OJ;`RC`?R%WGqq$hbhdvzSNg1UzVvx$KHFq7pY=t%lg-q=Z0%Ah+00)rx0Yx=rH~U<&neJPyC7Y?;ZY|kN zE!hm+>0j@bz6#A}d#^oTmy*qV);Fyso2h-<+QU+^nZG`2E!n*CJ0G_v+01iKT1z%l zd)ivEncB0~lFihfx0Y<~%qg4cPBud?`dqS^+RN6G&D6eYE!m7AEZIB|=iYe6a=QD{ zv6kL!9uL&io6V#8+A^luJgPPJX7i}l%A3vo&HJX;+?&ng+1h)vc~oog&E`?9#W$Nr zwWi)|UYlNQg_77% zE)+^)L%B{UiM=v2mrG9)8_HEeNo*(=2_>>>?3I~k+LOfQxldb5VpB_ELudQfbEPCUe?8yY=b?FT zFSI9#&2tx9OJY;I)LIgo+U3@g*wn7Hmc(B9ombnF#OAqcttGLkU2iRkP3=Z&No;CK zY$%DnGV^AiOJdV~tFJW#+y1d|kRHGfMuNr<6dpujqZ(@&XO}~jfs^ttH1-W?pE|7p04(#ZfnsoiKTIZiD(4kgD|X5Q>`$#J@GwU!*GcDuFYIJM+Bbf=YxK?WQLWWC$49kh-y9#++Iw?+ZF&vAIX<4P-kp`<&M z%ZHNgP_7!&B_4&}0;13iUY zHMOKWl#7Ov?oh57O1iJi%%#(lJBL_?p?WCk4jpYR=}zrfYe{!%$6HIfugpBro}@d^ zoop@XPVH1{Nq1^VcPQx&oo-*!eP!mE_9WeT?$g$i?$na*(Aoa=Tq)_!U(dIebYGcy zp*=}=p1auEm!(Ukq&t0=TT8lAyV6?HeP!m=_9WeT?pkX}cWT#LOS)6L(OS}-TGAa# zy06T<+2@k(bl++%=}zr-Ye{!%Nq6W@|9ZESbYGcyuRTe3KH+|ANq1@wTKl&2u#|MC z?@?<>_m!EC+mm$XxhJh9-KjloE$L3}S!+pmYR_9sx_9Q3?sO;Jp%;BF=}zrsYe{!% z-?f%>N5o6I55&1QI$s=jU%uATo9^R*ntIcHRBP)^_ff5}H{D0IR^D{)Z{9ck&E<Sr91i04p=I zF7)Ib0LpSec?W>98c^N=pezQIcK|4B0p%TFWoDLyp1cD$lqyaPa41Sop|u|~r$pu7V>$6Cuf0JY<-x313-BPfKInB?*J<^&$K7+06h0;Yk3EtmUjT?Z2x+$ly?CBdcL*11FX!v z(4M>l@Z81L@(w`lQfq%wx?IXT0DV_l%R9iz%&YCmI{?pJYc1~p)ULOdcK~WPTFW~C zwY&pBc?VdTd9%;u9f0mzt>qnn+U?fz4nQsM0MMQO^=>Ke04p=^wI}ZYe8TBVvPrEo31?*QY0ntI;>MzyxycYsl? zvG*NdRBPpZ2k39!H@)WGcYyKiTg%VsJHV*c;QJ0Rsivk_!ugjWH%bNj|C4us00A)p>ycw*_%)-!w*t+V$4*W5$Hv?*qTKk94>_d;+ zlQ#pNd(v9o45&SAEpGAq~PrT5KXJWx~bo585o*865Ksx|h$8H{SJyl)2m&HJX;-1}xQ zo~^z2&0tjDUVdcX3`VsU-#3F%t*Q6TU~PJBzHbKO*&2P{3`Vt9-#3F%t=ad@U{q`G zeKS~_Uc>L3!FaZo-#3F%t?Bp8U{q`SeKQ!<8hzgkI(^@N^H=Ndo56Ut=HEAiQLX*& z>@NPFO*%2XFP!N60+i)~^1c9NwV=E&Kv^s(?+Z}Y3d;M!iFsz0jGnwNKv^j$?+Z{C z3i=I~2ztAe_XTQMCMfRJiN^yGa3$|6B|Ux2bkP~I1yED@CV1t=>7<$YmgW)_N` zye~jmALu}TNtTCN-WQ;(4wUx=D2oH-ePLy0)`*_GFF;uuDDMkURtC!Z0+fY;vM&&e zG&~5(`@+i16Ya_S0^KKD%liVgQ?2EFfm+@dpu8_Yr`wnJg_W6S+LQMMp8K@5yf0A8 z`vP>fe?3>q`vQMG-&)=mR%TvkPu>@J?qX|sU!ZoWwY)D-yWCpd7pPrn?axB9R<5=u z?+ZM4t+l)_P`ln*-WRCdXf5vx)bhRn<$Yo0ci!xCd0(LWR%>}*pmw{pyf0A8`vP>Q zf4y7E`@+i1d+o{l0-tcdwY)D-d(c|m7pOgKE$<7|9<`SDg_W6)+w+g5C#AeE@L5k= z%liVgXRYOZf!g!d^1jfS)B6J5d0&8D^trq*P0-WRBS*IM2e5Z>~>Fc9b7Xm#15 zeTiL5@B6}dpr+pUg;A}o_kCehYwUer7}Z*N-xvCu_f4<4_kCeJTYK;O!l>5Z`@S%$ z?<_yP?+c?^Q}6r2+Vt9d-xtQSHTu3UjB2gE?+c?^v+w)DsMg;5zOXjEhTr#v@oX)> z?+c?^)9?GjsMhxTzA&ma`o1r8`o90-u-4!Ah4F07zwZm9TKn(&!l*U?c6PTC;NML=0LC~pxbv(x)#X7%XFTLhFvgYp&uWzC?xML=0H z=r>&~=$%sDBL07!X7pQUcGXeILRH@>rIgY(rGWa5qEQq@6XUvWWJMu_5JE5$H%;Bh zvO)+(1QV41oVAnnt-0bJ-j;rMpS#D-KKm?=gq(wju z7NkWidOBv*Xc3S@1>Neu+L0pDA|M9}(jp+o3DP1KJsmD;vU2fV=W5oFh8T0}kfEP`q+0{YN7ErRT(Op74< zSf)jA$u^4^WOIMMhug;8dB+Bw$`(VNn7k$#H6kAETW%zr+dpiilX)8X9nDl$wFC>dtb#KjQ5p%XhpG8dCs?Q=OZP{lLleXToh*kF%eikuj zTlrbUq%Hj{V$#-r7BOjyK8sj&Z}n#pbGGH5MNHcI&mt!60mvdIZRH<)+IGHEcYDt* zZs!(|g9zyskYfnx7LY>-=@yV92Gf209 z95P6^SoCz{sL?GT2Mp3JAjb>REg**r(k&oI3(_qXJsmV^oHK|4oIMBW7SQc7-GWTF zfOHG!PIbD)qUYUebPLYiE7L8=bPMQypB_fK1)m<3=@yHg$JOW-oI5GgEyx~}=@w+C zWx55~!!q4s(eqI?x&`MRm;GJzB+@OYds?Pjkm(kXZn5b3ymPt*)i26)3$n8^-GWTF zfL`|Ld8At`dcLYgx8NIIm+2N{7iGEy*_$%mg6y(Pw^;PNsz$fq+}kqUg6v({zeVpO z-GaL7GTow{du~CsZUKGhoNhsOQ>I&xeJs;0xKNv046?aD-??q$?!4};^xR?&wA6Ep zNn7i=#iT9v++xyJd2Z3qywknqo?Fb>)_ZO-X$wBLn6wq2TTI$g&n;HnzrX$3a*H|J zqR%ZRZPn)%leX-0i%DDWxy7n`3qQA*v#tExV$zm=ZZTZ-gWgwyNM;Zv3g9&LM zkYfpHAdo`|X&{T9jwm%62;@LQx9aXVl4&52!w6|0kfR7`Ad8+3CN&xek# z8VKYFLK+C<074qbqNn3XjRpcae2}vTF}kxMAq@o5Kp+hSx>KD7vgmoY8V!VV_sTR7 zG7SW}-=~L>2EwODWg5t$=W#U}2_OMI?S@e8VjRwNG$7LD_ z*^{!rkDf*v2z43=q=77YKJT0cLiLL>4TS8hOamd)K%kd>dLC&Yi=MBl(Lnfy*JT>D?J0511lJ1DUj?pMgx;+Rs2HZP8~StM0A-3}nu>{4_UIIC=&>w#pQs@VfUP9)uLV5}0s6u+lqNjsP zja~vdrqHcAIizHI3FL@EdI{u!LVC%fr{hYEUIICskX`~gnvh-sIhc@M0y&nDUb5)v zkW!g-ZTFM;lq=_QMvcdOA$ICrm1FCo)Qp!`C1e+6dI{N^GQEWCvP>^o z^t`G@FX7zVGQEWCU721&_P$InA-gX74{6(ddtO4dUIKmSoL)k9Q>K@YeJs;UxG0;K z46?aD-=(eVjv2Jl^O8BxQqM~!ZLQ}eleXCNl1W?Tc}c(Lo$f97ykyR{-t&@4Tkv_w zq^PfGne>O-uQ)H6v}K={Oxk+SOIF=m_<6~kZRO`BleYBp zl1W?pdC8z9BfEifgEc{TY(&ENL#tP-_sGNMq7a#Xh>Uu9A`*d zfgEN?TY(&9NLyL-bg-$>Rv^b1(pDgc82XbhgA4sI(pJbEU`Sh8^mLr5(N-Xb7rNEA zI=W=q3gqBI+6v^@LfXorr$bDQwgNe_khTIju#mO_Ij)el0y(UZwzBBy=u)GtKn^OT ztw4?`q^&>>Dddbo4DW1RNLyL-yjzX7LiN2eZG}u*f$sO|VWh3_=~0=svgmnSjkdzM zlQM0E>_M5fLUvlFt&lw|(^eKeA628RaPD!LwnFx#Oj{v)TBfa#JuCZ1Y5#scuSQ$p z+>0`8h3u?MTOrd{pqG7m9%(C!pYv5U+6v$Bx=dRkyC~CE$ljD`D`b~t+RCEmRW;fQ z=iZiSD`fA=v=y@VW!ehab(ywO&plhA`ai4w5NRuXdQ+yYkbNxER=5P4tqiicKi`|} zUv$S8TIt!!9B8R$E0ea?vz19(?Agkst@3Q8pLwTy%RO6}v#s}RWzrUWwlZleK3kcz zrJk*PfigcJoPludp9R_lwp<8`} z15KvGK#nt{!$1x*q{A$FI@;9eFpz@`=`fIE4CyeCLk#IKkRuG~FpHiJG&MR5*&OI*EVaT48=`dtZ%XApBXJtCfqUZB!{waD9 z=`eiPS(y$)ro%ul`}920VHQ1KRinf34X?{|7_y5p9fs^pnGQpCS*F7*dR|qd!*K3x znGQqtu1tp^dtau*kX@JQF!kJX7^-y`=tJlJE4qnv80tQj=`alZ<}ib7?$38(+qgRx z(Mr!@=0Hn5hncjsp2JMqV$WeFZI$OR{meVvTkbi`oNc}5Fq5|6bC^k6@j1+-E%h8` z)x9;J!_3(heGW5et3HRBv}K>eO#0*PpCgA^b#LM4Fmtw*pTkVr($8TgZSChUleXw{ zm{s>ye-1NeTmCuBq^p+cW13CPVW&=6;kY)op z_>g7;Irfldv*_t1phmNS9C=8yfgE^9vw<9UNV9<)cIeN(4EUnwkNqUGq1r)*ZuO~S zPNvyF4mqURK#n-1*(`cG@YHBFkmC($Hju*&X*Q6f4QV!zgAHjmi=K`-HJT0NP(zvx zN^r^8K+vkfuyv)Lid2GVSx`+a&CX*PU%RHoT1dLCD!*>LWp zOtT?-P^Q_Cot9}fWDmHk^A= z_RrB-q}foX*+4J*^gPmR7Cm28quKBcugf$WvWqg!hU`t5We%^;im^ZaiccgHPS z>6y(OXsKs5leX3~n@L;jna!lF^30~6d8d2JJ+qm!t@q4k(iVJXGifV6vzfG|p4qIr zx8^gOIoqPoY$k2hXEu|z>@%B5Tko08s{2p3f3(bI&bIP1n@L;xna!lF{mf?47JX*3 z>fY+lZ02msKeL&%^`F^H+5?c;OxnuNY*yWS1TvdB+cS{aOxi<`*-Y9~kl9Sy^3QDQ zzVkP}JqHJ$w)eoBak%F{hxrfWWr6e`$g2YBKadv%(tjYY38eoV?)UW4P^14qUJ*$D zfxIA){sVbEApHmOazOgeqNi7d8vO_IVnF&2_K>82l_(S^7qNkUE z8vO@y^dbERa_}Mj2XgEo{ReXBA^m63(`wM zjsC;Aw`KYd*}F3RhwOcs{zG9*OyR(bxj>fUnCf97ji@A=Q9E%^Lr(pG%_Giggb z|59+U5 z7JdG+>fY+lf97ji{`t?Ot^fRI(jI{PXVO-F{fwUsXD+6goi=JK}YP2HA>jG&-ke3D0iXg8Fq!mG4 z6i6#t^z_sO5I)t4AnymH6+zyPMNcmaHNWUvy&7a%5#+^yv?9oB z0ck~$mjcp?7CpTp)M!PJ7Xs3XAg=?Y6+vDGNGpQ83XoQ`=;_6vMk|8629Q<+c?lrz z0L0}OQ-b~`(u&A_X|_MNS`jtB>fA~6>*ztG6>;LUOe-RLSf&*%e$GeLXhocRT&5L~ zJt@n;l)a43qu)sTzgw+{Z}@H1S`pdr z$}XbcM{gpnh!dA(TG8U?ysAbk;@sOZt%&ShnN~#hzDz43yDrm;>bYk{RBJ`hht6q5 zWH)765!uHwt%#xB{;$v=oBQ)zZ@=ArE1IfydR8=PTRkh9w7s4cO}cG%uvMNF^)v5u zZ@Fhh^EIvatZ32}d{#7RD?Tflw56UEt-817v!XfMqR)yZZPjN*leX-$qDfotS<$L{ z3qLEGv#tF8uh67F-~NHKqDfo(S<$2|`mAWxz15!;&DoZJRy1krKP#HF2Ouk&w3VL~ zt-ALJWJPnfXCNz@w1*%onzW}NE1IfnIWG*Et^|2qAYBRavOu~Lt^|2W zAYBRaia@#&qeqiS>|&OI*EmB^ly=}Kfz%XB5OXJxw5qUZB!bS2Kc zDASe5&dPKpvTw>>M(5FQr2V;lRn2ds*U|5yi|F^!n@CsUzvHq@S6cj>SJmiBoO@fQ zE0Mh`)0N2Hm+4Am*JZj=J@;IRYF!EX&^cX+?50dtBKugTD>0CpD-E)_KhN;?+ugC1 zR(h^92U_a6(xl(n+T==;w%Bu}Nn7Q)Qa|%f_m+FEG-q4yxzeO9_*`kyR(!5BX-hp< zT6J&D=Sp+7MV~88+N#f$CT-d0N|UzUbEQ@H7JjZYXIuHX(xff@Txrt3{Py2t+xw&~ z`dn$%z15#9%{R9EbEQdJ|GCnnJpj4Vq^bC4^|*&c*kY0{pATxrrCg@aGqtMI>s8L1@z literal 0 HcmV?d00001 diff --git a/computer/computer-test/data_dir1/local_001/msg/0/eb8a977f-3da7-49fe-9b71-f7d569ebc5cf/hgkv_1.hgkv b/computer/computer-test/data_dir1/local_001/msg/0/eb8a977f-3da7-49fe-9b71-f7d569ebc5cf/hgkv_1.hgkv new file mode 100644 index 0000000000000000000000000000000000000000..181b83ef21a7143b7cfd322be6f1262dfab5232b GIT binary patch literal 6651 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 diff --git a/computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b b/computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b deleted file mode 100644 index 0aa6fb546..000000000 --- a/computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b +++ /dev/null @@ -1 +0,0 @@ -test data \ No newline at end of file diff --git a/computer/computer-test/hgkv/hgkv_1.hgkv/hgkv_1.hgkv b/computer/computer-test/hgkv/hgkv_1.hgkv/hgkv_1.hgkv deleted file mode 100644 index f58347329ebd270464c88a2d6b08cc81ba58293a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88 qcmZQ%U|?Wmgb_?wSj=!S1d9bO#s+3(q-U40Gq^F>Fo3v1KnwsXaRPS$ From 61bbf7133688ee5fabf5e4852bafd7bfd2504431 Mon Sep 17 00:00:00 2001 From: Loki Date: Mon, 27 Jul 2026 19:50:01 +0800 Subject: [PATCH 07/12] chagne the exception --- .../suite/integrate/SenderIntegrateTest.java | 165 +++++++++++++++--- 1 file changed, 136 insertions(+), 29 deletions(-) diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 5e78dd723..5fe67c96e 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -91,6 +91,30 @@ public void testWaitForServicesFailsFast() { } } + @Test + public void testCleanupFailureDoesNotHideWaitFailure() { + ServiceLifecycle lifecycle = new ServiceLifecycle(); + CompletableFuture failedWorker = new CompletableFuture<>(); + IllegalStateException waitFailure = + new IllegalStateException("worker failed"); + IllegalStateException cleanupFailure = + new IllegalStateException("worker close failed"); + failedWorker.completeExceptionally(waitFailure); + lifecycle.registerWorker(() -> { + throw cleanupFailure; + }); + + try { + waitForServicesAndClose(lifecycle, Arrays.asList(failedWorker), + new ArrayList<>(), null); + Assert.fail("Expected worker failure to be preserved"); + } catch (ComputerException e) { + Assert.assertSame(waitFailure, e.getCause()); + Assert.assertEquals(1, e.getSuppressed().length); + Assert.assertSame(cleanupFailure, e.getSuppressed()[0].getCause()); + } + } + @Test public void testCiTimeoutsAllowHeavyInputStep() { Assert.assertEquals(TimeUnit.MINUTES.toMillis(5L), BSP_WAIT_TIMEOUT); @@ -173,6 +197,42 @@ public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { Assert.assertFalse(thread.isAlive()); } + @Test + public void testCloseServicesAndJoinUsesOneTimeoutBudget() + throws Exception { + long timeout = 200L; + AtomicBoolean stopping = new AtomicBoolean(); + CountDownLatch started = new CountDownLatch(3); + Thread firstWorker = newInterruptIgnoringThread(stopping, started); + Thread secondWorker = newInterruptIgnoringThread(stopping, started); + Thread master = newInterruptIgnoringThread(stopping, started); + firstWorker.start(); + secondWorker.start(); + master.start(); + Assert.assertTrue(started.await(1, TimeUnit.SECONDS)); + + long start = System.nanoTime(); + try { + closeServicesAndJoin(new ServiceLifecycle(), + Arrays.asList(firstWorker, secondWorker), + master, timeout); + Assert.fail("Expected service threads to time out"); + } catch (ComputerException ignored) { + // The timeout is expected; the assertion below verifies its budget + } finally { + stopping.set(true); + firstWorker.interrupt(); + secondWorker.interrupt(); + master.interrupt(); + firstWorker.join(TimeUnit.SECONDS.toMillis(1L)); + secondWorker.join(TimeUnit.SECONDS.toMillis(1L)); + master.join(TimeUnit.SECONDS.toMillis(1L)); + } + long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); + Assert.assertTrue("Cleanup exceeded its shared timeout budget: " + elapsed, + elapsed < timeout * 2L); + } + @Test public void testCloseServicesAndJoinStopsWorkersBeforeMaster() throws Exception { @@ -296,12 +356,9 @@ public void testOneWorker() { masterThread.start(); workerThread.start(); - try { - waitForServices(Arrays.asList(workerFuture, masterFuture)); - } finally { - closeServicesAndJoin(lifecycle, Arrays.asList(workerThread), - masterThread); - } + waitForServicesAndClose(lifecycle, + Arrays.asList(workerFuture, masterFuture), + Arrays.asList(workerThread), masterThread); } @Test @@ -393,13 +450,9 @@ public void testMultiWorkers() throws IOException { List> futures = new ArrayList<>(workers.values()); futures.add(masterFuture); - try { - waitForServices(futures); - } finally { - closeServicesAndJoin(lifecycle, - new ArrayList<>(workers.keySet()), - masterThread); - } + waitForServicesAndClose(lifecycle, futures, + new ArrayList<>(workers.keySet()), + masterThread); } @Test @@ -481,12 +534,9 @@ public void testOneWorkerWithBusyClient() { masterThread.start(); workerThread.start(); - try { - waitForServices(Arrays.asList(workerFuture, masterFuture)); - } finally { - closeServicesAndJoin(lifecycle, Arrays.asList(workerThread), - masterThread); - } + waitForServicesAndClose(lifecycle, + Arrays.asList(workerFuture, masterFuture), + Arrays.asList(workerThread), masterThread); } private void slowSendFunc(WorkerService service, int port) throws TransportException { @@ -577,15 +627,44 @@ private static void waitForServices(List> futures) { } } + private static void waitForServicesAndClose( + ServiceLifecycle lifecycle, List> futures, + List workerThreads, Thread masterThread) { + try { + waitForServices(futures); + } catch (RuntimeException | Error e) { + try { + closeServicesAndJoin(lifecycle, workerThreads, masterThread); + } catch (RuntimeException | Error closeFailure) { + e.addSuppressed(closeFailure); + } + throw e; + } + closeServicesAndJoin(lifecycle, workerThreads, masterThread); + } + private static void closeServicesAndJoin(ServiceLifecycle lifecycle, List workerThreads, Thread masterThread) { + closeServicesAndJoin(lifecycle, workerThreads, masterThread, + SERVICE_WAIT_TIMEOUT); + } + + private static void closeServicesAndJoin(ServiceLifecycle lifecycle, + List workerThreads, + Thread masterThread, + long timeout) { + long deadline = System.nanoTime() + + TimeUnit.MILLISECONDS.toNanos(timeout); Throwable closeFailure = lifecycle.closeAll(); - Throwable workerFailure = interruptAndJoinThreads(workerThreads); + Throwable workerFailure = interruptAndJoinThreads( + workerThreads, + remainingTimeout(deadline)); Throwable masterFailure = null; if (masterThread != null) { masterFailure = interruptAndJoinThreads( - Arrays.asList(masterThread)); + Arrays.asList(masterThread), + remainingTimeout(deadline)); } if (closeFailure != null) { addFailure(closeFailure, workerFailure); @@ -603,19 +682,25 @@ private static void closeServicesAndJoin(ServiceLifecycle lifecycle, } } - private static Throwable interruptAndJoinThreads(List threads) { + private static Throwable interruptAndJoinThreads(List threads, + long timeout) { + long deadline = System.nanoTime() + + TimeUnit.MILLISECONDS.toNanos(timeout); for (Thread thread : threads) { thread.interrupt(); } Throwable failure = null; for (Thread thread : threads) { - try { - thread.join(SERVICE_WAIT_TIMEOUT); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - failure = addFailure(failure, new ComputerException( - "Interrupted when waiting for service " + - "thread to stop", e)); + long remaining = remainingTimeout(deadline); + if (remaining > 0L) { + try { + thread.join(remaining); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + failure = addFailure(failure, new ComputerException( + "Interrupted when waiting for service " + + "thread to stop", e)); + } } if (thread.isAlive()) { failure = addFailure(failure, new ComputerException( @@ -626,6 +711,28 @@ private static Throwable interruptAndJoinThreads(List threads) { return failure; } + private static Thread newInterruptIgnoringThread(AtomicBoolean stopping, + CountDownLatch started) { + Thread thread = new Thread(() -> { + started.countDown(); + while (!stopping.get()) { + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException ignored) { + // Keep waiting until the test explicitly stops this thread + } + } + }); + thread.setDaemon(true); + return thread; + } + + private static long remainingTimeout(long deadline) { + long remaining = deadline - System.nanoTime(); + return remaining <= 0L ? 0L : + TimeUnit.NANOSECONDS.toMillis(remaining) + 1L; + } + private static Throwable addFailure(Throwable failure, Throwable cause) { if (cause == null) { return failure; From ca692c602269bc8a6245fadff5bc9fa338d8d071 Mon Sep 17 00:00:00 2001 From: Loki Date: Tue, 28 Jul 2026 11:22:10 +0800 Subject: [PATCH 08/12] fix: handle sender data path failures --- .../core/sender/QueuedMessageSender.java | 23 +++++--- .../core/sender/QueuedMessageSenderTest.java | 57 +++++++++++++++++++ .../suite/integrate/SenderIntegrateTest.java | 42 +++++++++----- 3 files changed, 101 insertions(+), 21 deletions(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java index c3ed4c254..aa21d5c0f 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java @@ -142,11 +142,19 @@ public void run() { ++emptyQueueCount; continue; } - if (channel.doSend(message)) { - // Only consume the message after it is sent + try { + if (channel.doSend(message)) { + // Only consume the message after it is sent + channel.queue.take(); + } else { + ++busyClientCount; + } + } catch (TransportException | RuntimeException e) { + channel.failControlFuture(e); + // Discard the failed data message to keep sending channel.queue.take(); - } else { - ++busyClientCount; + LOG.warn("Failed to send {} message to {}, " + + "discard it", message.type(), channel, e); } } int channelCount = channels.length; @@ -177,9 +185,6 @@ public void run() { "Interrupted when waiting for message " + "queue not empty"); } - } catch (TransportException e) { - // TODO: should handle this in main workflow thread - throw new ComputerException("Failed to send message", e); } } LOG.info("The send-executor is terminated"); @@ -297,6 +302,10 @@ public void sendFinishMessage(CompletableFuture future) { } public void transportExceptionCaught(TransportException cause) { + this.failControlFuture(cause); + } + + public void failControlFuture(Throwable cause) { CompletableFuture future = this.controlFutureRef.getAndSet(null); if (future != null) { future.completeExceptionally(cause); diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index 621964b81..ee0dfac43 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -269,6 +269,20 @@ public void testSynchronousTransportFailureKeepsExecutorAliveForOtherClients() } } + @Test + public void testSynchronousDataTransportFailureCompletesQueuedFinish() + throws Exception { + this.assertSynchronousDataFailureCompletesQueuedFinish( + new TransportException("data send failed")); + } + + @Test + public void testSynchronousDataRuntimeFailureCompletesQueuedFinish() + throws Exception { + this.assertSynchronousDataFailureCompletesQueuedFinish( + new IllegalStateException("data send failed")); + } + @Test public void testControlFutureConflictKeepsSendExecutorAlive() throws Exception { @@ -317,6 +331,38 @@ private static void assertFutureFailedWith(CompletableFuture future, } } + private void assertSynchronousDataFailureCompletesQueuedFinish( + Throwable cause) throws Exception { + QueuedMessageSender sender = new QueuedMessageSender(this.config); + ControlFutureClient failedClient = new ControlFutureClient(); + ControlFutureClient activeClient = new ControlFutureClient(); + sender.addWorkerClient(1, failedClient); + sender.addWorkerClient(2, activeClient); + sender.init(); + + failedClient.blockDataSend(); + try { + sender.send(1, new QueuedMessage(0, MessageType.MSG, + ByteBuffer.allocate(1))); + Assert.assertTrue(failedClient.awaitDataSend()); + + CompletableFuture finishFuture = sender.send(1, + MessageType.FINISH); + failedClient.failDataWith(cause); + failedClient.allowDataSend(); + assertFutureFailedWith(finishFuture, cause); + + CompletableFuture activeStart = sender.send(2, + MessageType.START); + Assert.assertTrue(activeClient.awaitStart()); + activeClient.completeStart(); + activeStart.get(1, TimeUnit.SECONDS); + } finally { + failedClient.allowDataSend(); + sender.close(); + } + } + private static void assertFutureFailedWithMessage(CompletableFuture future, String message) throws InterruptedException, TimeoutException { @@ -340,6 +386,7 @@ private static class ControlFutureClient extends MockTransportClient { private RuntimeException finishFailure; private TransportException startTransportFailure; private TransportException finishTransportFailure; + private Throwable dataFailure; private boolean blockDataSend; public ControlFutureClient() { @@ -389,6 +436,12 @@ public boolean send(MessageType messageType, int partition, throw new TransportException("Interrupted data send", e); } } + if (this.dataFailure instanceof TransportException) { + throw (TransportException) this.dataFailure; + } + if (this.dataFailure instanceof RuntimeException) { + throw (RuntimeException) this.dataFailure; + } return true; } @@ -445,5 +498,9 @@ public void failFinishWith(RuntimeException failure) { public void failFinishWithTransportException(TransportException failure) { this.finishTransportFailure = failure; } + + public void failDataWith(Throwable failure) { + this.dataFailure = failure; + } } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 5fe67c96e..250cbb880 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -65,6 +65,8 @@ public class SenderIntegrateTest { private static final long BSP_WAIT_TIMEOUT = TimeUnit.MINUTES.toMillis(5L); private static final long SERVICE_WAIT_TIMEOUT = BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L); + private static final long TEST_THREAD_JOIN_TIMEOUT = + TimeUnit.SECONDS.toMillis(5L); @BeforeClass public static void init() { @@ -188,13 +190,19 @@ public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { } }); lifecycle.registerWorker(() -> closed.set(true)); - thread.start(); - Assert.assertTrue(started.await(1, TimeUnit.SECONDS)); + try { + thread.start(); + Assert.assertTrue(started.await(1, TimeUnit.SECONDS)); - closeServicesAndJoin(lifecycle, Arrays.asList(thread), null); + closeServicesAndJoin(lifecycle, Arrays.asList(thread), null); - Assert.assertTrue(closed.get()); - Assert.assertFalse(thread.isAlive()); + Assert.assertTrue(closed.get()); + Assert.assertFalse(thread.isAlive()); + } finally { + lifecycle.closeAll(); + interruptAndJoinThreads(Arrays.asList(thread), + TEST_THREAD_JOIN_TIMEOUT); + } } @Test @@ -266,17 +274,23 @@ public void testCloseServicesAndJoinStopsWorkersBeforeMaster() Thread.currentThread().interrupt(); } }); - workerThread.start(); - masterThread.start(); - Assert.assertTrue(workerStarted.await(1, TimeUnit.SECONDS)); - Assert.assertTrue(masterStarted.await(1, TimeUnit.SECONDS)); + try { + workerThread.start(); + masterThread.start(); + Assert.assertTrue(workerStarted.await(1, TimeUnit.SECONDS)); + Assert.assertTrue(masterStarted.await(1, TimeUnit.SECONDS)); - closeServicesAndJoin(lifecycle, Arrays.asList(workerThread), - masterThread); + closeServicesAndJoin(lifecycle, Arrays.asList(workerThread), + masterThread); - Assert.assertFalse(masterInterruptedBeforeWorkerStopped.get()); - Assert.assertFalse(workerThread.isAlive()); - Assert.assertFalse(masterThread.isAlive()); + Assert.assertFalse(masterInterruptedBeforeWorkerStopped.get()); + Assert.assertFalse(workerThread.isAlive()); + Assert.assertFalse(masterThread.isAlive()); + } finally { + lifecycle.closeAll(); + interruptAndJoinThreads(Arrays.asList(workerThread, masterThread), + TEST_THREAD_JOIN_TIMEOUT); + } } @Test From 99e825d43196e4b3b78b93f3bf2c24108b62ce7f Mon Sep 17 00:00:00 2001 From: Loki Date: Tue, 28 Jul 2026 19:28:02 +0800 Subject: [PATCH 09/12] fix: complete master future on errors --- .../suite/integrate/SenderIntegrateTest.java | 40 ++++++++++++++++--- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 250cbb880..7889573c6 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -117,6 +117,29 @@ public void testCleanupFailureDoesNotHideWaitFailure() { } } + @Test + public void testMasterErrorCompletesServiceFuture() throws Exception { + CompletableFuture masterFuture = new CompletableFuture<>(); + Error cause = new AssertionError("master failed"); + Thread masterThread = new Thread(() -> this.executeMasterTask( + masterFuture, () -> { + throw cause; + })); + masterThread.start(); + + try { + masterFuture.get(1, TimeUnit.SECONDS); + Assert.fail("Expected master error to fail the service future"); + } catch (ExecutionException e) { + Assert.assertSame(cause, e.getCause()); + } catch (TimeoutException e) { + Assert.fail("Timed out to wait for master error"); + } finally { + interruptAndJoinThreads(Arrays.asList(masterThread), + TEST_THREAD_JOIN_TIMEOUT); + } + } + @Test public void testCiTimeoutsAllowHeavyInputStep() { Assert.assertEquals(TimeUnit.MINUTES.toMillis(5L), BSP_WAIT_TIMEOUT); @@ -314,7 +337,7 @@ public void testOneWorker() { .withRpcServerPort(8611) .withRpcServerPort(0) .build(); - try { + this.executeMasterTask(masterFuture, () -> { MasterService service = initMaster(args); try { if (!lifecycle.registerMaster(service::close)) { @@ -326,10 +349,7 @@ public void testOneWorker() { } finally { closeMaster(service); } - } catch (Exception e) { - LOG.error("Failed to execute master service", e); - masterFuture.completeExceptionally(e); - } + }); }); masterThread.setDaemon(true); @@ -578,6 +598,16 @@ private void slowSendFunc(WorkerService service, int port) throws TransportExcep Whitebox.setInternalState(clientSession, "sendFunction", sendFunc); } + private void executeMasterTask(CompletableFuture future, + Runnable task) { + try { + task.run(); + } catch (Throwable e) { + LOG.error("Failed to execute master service", e); + future.completeExceptionally(e); + } + } + private MasterService initMaster(String[] args) { Config config = ComputerContextUtil.initContext( ComputerContextUtil.convertToMap(args)); From e60d48d51e7c36884b934fe0fe2cd62334bbddca Mon Sep 17 00:00:00 2001 From: Loki Date: Wed, 29 Jul 2026 12:19:24 +0800 Subject: [PATCH 10/12] fix: handle sender failures and simplify tests --- .../core/sender/QueuedMessageSender.java | 28 +- .../core/sender/QueuedMessageSenderTest.java | 425 ++++++++-------- .../suite/integrate/SenderIntegrateTest.java | 465 ++++++------------ 3 files changed, 378 insertions(+), 540 deletions(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java index aa21d5c0f..6f452074f 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java @@ -150,7 +150,7 @@ public void run() { ++busyClientCount; } } catch (TransportException | RuntimeException e) { - channel.failControlFuture(e); + channel.failDataSend(e); // Discard the failed data message to keep sending channel.queue.take(); LOG.warn("Failed to send {} message to {}, " + @@ -238,6 +238,7 @@ private static class WorkerChannel { // Each target worker has a TransportClient private final TransportClient client; private final AtomicReference> controlFutureRef; + private final AtomicReference dataFailureRef; public WorkerChannel(int workerId, MessageQueue queue, TransportClient client) { @@ -245,6 +246,7 @@ public WorkerChannel(int workerId, MessageQueue queue, this.queue = queue; this.client = client; this.controlFutureRef = new AtomicReference<>(); + this.dataFailureRef = new AtomicReference<>(); } public boolean doSend(QueuedMessage message) @@ -302,7 +304,12 @@ public void sendFinishMessage(CompletableFuture future) { } public void transportExceptionCaught(TransportException cause) { - this.failControlFuture(cause); + CompletableFuture future = this.controlFutureRef.get(); + if (future == null) { + this.failDataSend(cause); + } else { + this.completeControlFuture(future, cause); + } } public void failControlFuture(Throwable cause) { @@ -312,9 +319,24 @@ public void failControlFuture(Throwable cause) { } } + public void failDataSend(Throwable cause) { + this.dataFailureRef.compareAndSet(null, cause); + this.failControlFuture(this.dataFailureRef.get()); + } + private boolean setControlFuture(CompletableFuture future) { + Throwable failure = this.dataFailureRef.get(); + if (failure != null) { + future.completeExceptionally(failure); + return false; + } if (this.controlFutureRef.compareAndSet(null, future)) { - return true; + failure = this.dataFailureRef.get(); + if (failure == null) { + return true; + } + this.completeControlFuture(future, failure); + return false; } ComputerException e = new ComputerException( "The origin future must be null"); diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index ee0dfac43..a86e62a3f 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -28,6 +28,7 @@ import org.apache.hugegraph.computer.core.common.exception.TransportException; import org.apache.hugegraph.computer.core.config.ComputerOptions; import org.apache.hugegraph.computer.core.config.Config; +import org.apache.hugegraph.computer.core.network.TransportClient; import org.apache.hugegraph.computer.core.network.message.MessageType; import org.apache.hugegraph.computer.core.worker.MockComputation2; import org.apache.hugegraph.computer.suite.unit.UnitTestBase; @@ -57,12 +58,18 @@ public void setup() { ); } - @Test - public void testInitAndClose() { + private QueuedMessageSender newSender(TransportClient first, TransportClient second) { QueuedMessageSender sender = new QueuedMessageSender(this.config); - sender.addWorkerClient(1, new MockTransportClient()); - sender.addWorkerClient(2, new MockTransportClient()); + sender.addWorkerClient(1, first); + sender.addWorkerClient(2, second); sender.init(); + return sender; + } + + @Test + public void testInitAndClose() { + QueuedMessageSender sender = this.newSender(new MockTransportClient(), + new MockTransportClient()); Thread sendExecutor = Whitebox.getInternalState(sender, "sendExecutor"); Assert.assertTrue(ImmutableSet.of(Thread.State.NEW, @@ -76,21 +83,16 @@ public void testInitAndClose() { } @Test - public void testControlFutureCanQueueNextControlBeforeCompletionDependentFinishes() - throws Exception { - QueuedMessageSender sender = new QueuedMessageSender(this.config); + public void testControlBeforeCompletionFinishes() throws Exception { ControlFutureClient client = new ControlFutureClient(); - sender.addWorkerClient(1, client); - sender.addWorkerClient(2, new MockTransportClient()); - sender.init(); + QueuedMessageSender sender = this.newSender(client, new MockTransportClient()); CountDownLatch completionStarted = new CountDownLatch(1); CountDownLatch allowCompletion = new CountDownLatch(1); Thread completionThread = null; try { - CompletableFuture startFuture = sender.send(1, - MessageType.START); - Assert.assertTrue(client.awaitStart()); + CompletableFuture startFuture = sender.send(1, MessageType.START); + Assert.assertTrue(await(client.startCalled)); startFuture.whenComplete((r, e) -> { completionStarted.countDown(); try { @@ -101,17 +103,17 @@ public void testControlFutureCanQueueNextControlBeforeCompletionDependentFinishe } }); - completionThread = new Thread(client::completeStart); + completionThread = new Thread( + () -> client.startFuture.complete(null)); completionThread.start(); Assert.assertTrue(completionStarted.await(1, TimeUnit.SECONDS)); - CompletableFuture finishFuture = sender.send(1, - MessageType.FINISH); - Assert.assertTrue(client.awaitFinish()); + CompletableFuture finishFuture = sender.send(1, MessageType.FINISH); + Assert.assertTrue(await(client.finishCalled)); allowCompletion.countDown(); completionThread.join(TimeUnit.SECONDS.toMillis(1)); Assert.assertFalse(completionThread.isAlive()); - client.completeFinish(); + client.finishFuture.complete(null); finishFuture.get(1, TimeUnit.SECONDS); } finally { allowCompletion.countDown(); @@ -123,31 +125,24 @@ public void testControlFutureCanQueueNextControlBeforeCompletionDependentFinishe } @Test - public void testTransportExceptionCompletesInFlightControlFuture() - throws Exception { - QueuedMessageSender sender = new QueuedMessageSender(this.config); + public void testTransportExceptionControlFuture() throws Exception { ControlFutureClient client = new ControlFutureClient(); - sender.addWorkerClient(1, client); - sender.addWorkerClient(2, new MockTransportClient()); - sender.init(); + QueuedMessageSender sender = this.newSender(client, new MockTransportClient()); try { - CompletableFuture startFuture = sender.send(1, - MessageType.START); - Assert.assertTrue(client.awaitStart()); + CompletableFuture startFuture = sender.send(1, MessageType.START); + Assert.assertTrue(await(client.startCalled)); - TransportException cause = - new TransportException("connection failed"); + TransportException cause = new TransportException("connection failed"); sender.transportExceptionCaught(cause, client.connectionId()); assertFutureFailedWith(startFuture, cause); - CompletableFuture finishFuture = sender.send(1, - MessageType.FINISH); - Assert.assertTrue(client.awaitFinish()); - client.completeStart(); + CompletableFuture finishFuture = sender.send(1, MessageType.FINISH); + Assert.assertTrue(await(client.finishCalled)); + client.startFuture.complete(null); assertFutureFailedWith(startFuture, cause); - client.completeFinish(); + client.finishFuture.complete(null); finishFuture.get(1, TimeUnit.SECONDS); } finally { sender.close(); @@ -155,69 +150,52 @@ public void testTransportExceptionCompletesInFlightControlFuture() } @Test - public void testTransportExceptionCompletesQueuedControlFutureBeforeDispatch() - throws Exception { - QueuedMessageSender sender = new QueuedMessageSender(this.config); + public void testTransportExceptionDispatch() throws Exception { ControlFutureClient client = new ControlFutureClient(); - sender.addWorkerClient(1, client); - sender.addWorkerClient(2, new MockTransportClient()); - sender.init(); + QueuedMessageSender sender = this.newSender(client, new MockTransportClient()); - client.blockDataSend(); + client.blockDataSend = true; try { - sender.send(1, new QueuedMessage(0, MessageType.MSG, - ByteBuffer.allocate(1))); - Assert.assertTrue(client.awaitDataSend()); + sender.send(1, new QueuedMessage(0, MessageType.MSG, ByteBuffer.allocate(1))); + Assert.assertTrue(await(client.dataSendCalled)); - CompletableFuture startFuture = sender.send(1, - MessageType.START); - TransportException cause = - new TransportException("connection failed before start"); + CompletableFuture startFuture = sender.send(1, MessageType.START); + TransportException cause = new TransportException("connection failed before start"); sender.transportExceptionCaught(cause, client.connectionId()); assertFutureFailedWith(startFuture, cause); - client.allowDataSend(); - Assert.assertFalse(client.awaitStart()); + client.allowDataSend.countDown(); + Assert.assertFalse(await(client.startCalled)); } finally { - client.allowDataSend(); + client.allowDataSend.countDown(); sender.close(); } } @Test - public void testSynchronousControlFailureCompletesFutureAndKeepsExecutorAlive() - throws Exception { - QueuedMessageSender sender = new QueuedMessageSender(this.config); + public void testExecutorAlive() throws Exception { ControlFutureClient client = new ControlFutureClient(); - sender.addWorkerClient(1, client); - sender.addWorkerClient(2, new MockTransportClient()); - sender.init(); + QueuedMessageSender sender = this.newSender(client, new MockTransportClient()); try { - RuntimeException startCause = - new IllegalArgumentException("start session failed"); - client.failStartWith(startCause); - CompletableFuture startFuture = sender.send(1, - MessageType.START); + RuntimeException startCause = new IllegalArgumentException("start session failed"); + client.startFailure = startCause; + CompletableFuture startFuture = sender.send(1, MessageType.START); assertFutureFailedWith(startFuture, startCause); - RuntimeException finishCause = - new IllegalArgumentException("finish session failed"); - client.failFinishWith(finishCause); - CompletableFuture finishFuture = sender.send(1, - MessageType.FINISH); + RuntimeException finishCause = new IllegalArgumentException("finish session failed"); + client.finishFailure = finishCause; + CompletableFuture finishFuture = sender.send(1, MessageType.FINISH); assertFutureFailedWith(finishFuture, finishCause); - Thread sendExecutor = Whitebox.getInternalState(sender, - "sendExecutor"); + Thread sendExecutor = Whitebox.getInternalState(sender, "sendExecutor"); sendExecutor.join(TimeUnit.SECONDS.toMillis(1)); Assert.assertTrue(sendExecutor.isAlive()); - client.failStartWith(null); - CompletableFuture nextStartFuture = sender.send(1, - MessageType.START); - Assert.assertTrue(client.awaitStart()); - client.completeStart(); + client.startFailure = null; + CompletableFuture nextStartFuture = sender.send(1, MessageType.START); + Assert.assertTrue(await(client.startCalled)); + client.startFuture.complete(null); nextStartFuture.get(1, TimeUnit.SECONDS); } finally { sender.close(); @@ -225,44 +203,34 @@ public void testSynchronousControlFailureCompletesFutureAndKeepsExecutorAlive() } @Test - public void testSynchronousTransportFailureKeepsExecutorAliveForOtherClients() - throws Exception { - QueuedMessageSender sender = new QueuedMessageSender(this.config); + public void testOtherClients() throws Exception { ControlFutureClient failedClient = new ControlFutureClient(); ControlFutureClient activeClient = new ControlFutureClient(); - sender.addWorkerClient(1, failedClient); - sender.addWorkerClient(2, activeClient); - sender.init(); + QueuedMessageSender sender = this.newSender(failedClient, activeClient); try { TransportException startCause = new TransportException("start session failed"); - failedClient.failStartWithTransportException(startCause); - CompletableFuture failedStart = sender.send(1, - MessageType.START); + failedClient.startFailure = startCause; + CompletableFuture failedStart = sender.send(1, MessageType.START); assertFutureFailedWith(failedStart, startCause); - CompletableFuture activeStart = sender.send(2, - MessageType.START); - Assert.assertTrue(activeClient.awaitStart()); - activeClient.completeStart(); + CompletableFuture activeStart = sender.send(2, MessageType.START); + Assert.assertTrue(await(activeClient.startCalled)); + activeClient.startFuture.complete(null); activeStart.get(1, TimeUnit.SECONDS); - TransportException finishCause = - new TransportException("finish session failed"); - failedClient.failFinishWithTransportException(finishCause); - CompletableFuture failedFinish = sender.send(1, - MessageType.FINISH); + TransportException finishCause = new TransportException("finish session failed"); + failedClient.finishFailure = finishCause; + CompletableFuture failedFinish = sender.send(1, MessageType.FINISH); assertFutureFailedWith(failedFinish, finishCause); - CompletableFuture activeFinish = sender.send(2, - MessageType.FINISH); - Assert.assertTrue(activeClient.awaitFinish()); - activeClient.completeFinish(); + CompletableFuture activeFinish = sender.send(2, MessageType.FINISH); + Assert.assertTrue(await(activeClient.finishCalled)); + activeClient.finishFuture.complete(null); activeFinish.get(1, TimeUnit.SECONDS); - Thread sendExecutor = Whitebox.getInternalState(sender, - "sendExecutor"); + Thread sendExecutor = Whitebox.getInternalState(sender, "sendExecutor"); Assert.assertTrue(sendExecutor.isAlive()); } finally { sender.close(); @@ -270,58 +238,56 @@ public void testSynchronousTransportFailureKeepsExecutorAliveForOtherClients() } @Test - public void testSynchronousDataTransportFailureCompletesQueuedFinish() - throws Exception { - this.assertSynchronousDataFailureCompletesQueuedFinish( - new TransportException("data send failed")); + public void testQueuedFinish() throws Exception { + this.assertSynchronousDataFailureCompletesQueuedFinish(new TransportException("data send failed")); } @Test - public void testSynchronousDataRuntimeFailureCompletesQueuedFinish() - throws Exception { - this.assertSynchronousDataFailureCompletesQueuedFinish( - new IllegalStateException("data send failed")); + public void testCompletesQueuedFinish() throws Exception { + this.assertSynchronousDataFailureCompletesQueuedFinish(new IllegalStateException("data send failed")); } @Test - public void testControlFutureConflictKeepsSendExecutorAlive() - throws Exception { - QueuedMessageSender sender = new QueuedMessageSender(this.config); + public void testFinishFailsFinish() throws Exception { + this.assertSynchronousDataFailureBeforeFinishFailsFinish( + new TransportException("data send failed before finish")); + } + + @Test + public void testDataRuntimeFinish() throws Exception { + this.assertSynchronousDataFailureBeforeFinishFailsFinish( + new IllegalStateException("data send failed before finish")); + } + + @Test + public void testConflictKeepsSendExecutorAlive() throws Exception { ControlFutureClient client = new ControlFutureClient(); - sender.addWorkerClient(1, client); - sender.addWorkerClient(2, new MockTransportClient()); - sender.init(); + QueuedMessageSender sender = this.newSender(client, new MockTransportClient()); try { - CompletableFuture startFuture = sender.send(1, - MessageType.START); - Assert.assertTrue(client.awaitStart()); + CompletableFuture startFuture = sender.send(1, MessageType.START); + Assert.assertTrue(await(client.startCalled)); - CompletableFuture conflictingFinishFuture = sender.send( - 1, MessageType.FINISH); - assertFutureFailedWithMessage(conflictingFinishFuture, - "The origin future must be null"); + CompletableFuture conflictingFinishFuture = sender.send(1, MessageType.FINISH); + assertFutureFailedWithMessage(conflictingFinishFuture, "The origin future must be null"); - Thread sendExecutor = Whitebox.getInternalState(sender, - "sendExecutor"); + Thread sendExecutor = Whitebox.getInternalState(sender, "sendExecutor"); sendExecutor.join(TimeUnit.SECONDS.toMillis(1)); Assert.assertTrue(sendExecutor.isAlive()); - client.completeStart(); + client.startFuture.complete(null); startFuture.get(1, TimeUnit.SECONDS); - CompletableFuture finishFuture = sender.send(1, - MessageType.FINISH); - Assert.assertTrue(client.awaitFinish()); - client.completeFinish(); + CompletableFuture finishFuture = sender.send(1, MessageType.FINISH); + Assert.assertTrue(await(client.finishCalled)); + client.finishFuture.complete(null); finishFuture.get(1, TimeUnit.SECONDS); } finally { sender.close(); } } - private static void assertFutureFailedWith(CompletableFuture future, - Throwable cause) + private static void assertFutureFailedWith(CompletableFuture future, Throwable cause) throws InterruptedException, TimeoutException { try { future.get(1, TimeUnit.SECONDS); @@ -331,38 +297,99 @@ private static void assertFutureFailedWith(CompletableFuture future, } } - private void assertSynchronousDataFailureCompletesQueuedFinish( - Throwable cause) throws Exception { - QueuedMessageSender sender = new QueuedMessageSender(this.config); + private static boolean await(CountDownLatch latch) throws InterruptedException { + return latch.await(1, TimeUnit.SECONDS); + } + + private void assertSynchronousDataFailureCompletesQueuedFinish(Throwable cause) throws Exception { ControlFutureClient failedClient = new ControlFutureClient(); ControlFutureClient activeClient = new ControlFutureClient(); - sender.addWorkerClient(1, failedClient); - sender.addWorkerClient(2, activeClient); - sender.init(); + QueuedMessageSender sender = this.newSender(failedClient, activeClient); - failedClient.blockDataSend(); + failedClient.blockDataSend = true; try { sender.send(1, new QueuedMessage(0, MessageType.MSG, ByteBuffer.allocate(1))); - Assert.assertTrue(failedClient.awaitDataSend()); + Assert.assertTrue(await(failedClient.dataSendCalled)); - CompletableFuture finishFuture = sender.send(1, - MessageType.FINISH); - failedClient.failDataWith(cause); - failedClient.allowDataSend(); + CompletableFuture finishFuture = sender.send(1, MessageType.FINISH); + failedClient.dataFailure = cause; + failedClient.allowDataSend.countDown(); assertFutureFailedWith(finishFuture, cause); - CompletableFuture activeStart = sender.send(2, - MessageType.START); - Assert.assertTrue(activeClient.awaitStart()); - activeClient.completeStart(); + CompletableFuture activeStart = sender.send(2, MessageType.START); + Assert.assertTrue(await(activeClient.startCalled)); + activeClient.startFuture.complete(null); activeStart.get(1, TimeUnit.SECONDS); } finally { - failedClient.allowDataSend(); + failedClient.allowDataSend.countDown(); sender.close(); } } + @Test + public void testTransportExceptionDuringDataSendFailsLaterFinish() + throws Exception { + ControlFutureClient client = new ControlFutureClient(); + QueuedMessageSender sender = this.newSender( + client, new MockTransportClient()); + + client.blockDataSend = true; + try { + sender.send(1, new QueuedMessage(0, MessageType.MSG, + ByteBuffer.allocate(1))); + Assert.assertTrue(await(client.dataSendCalled)); + + TransportException cause = + new TransportException("connection failed during data"); + sender.transportExceptionCaught(cause, client.connectionId()); + client.allowDataSend.countDown(); + waitForQueueEmpty(sender, 1); + + CompletableFuture finishFuture = sender.send( + 1, MessageType.FINISH); + assertFutureFailedWith(finishFuture, cause); + Assert.assertFalse(await(client.finishCalled)); + } finally { + client.allowDataSend.countDown(); + sender.close(); + } + } + + private void assertSynchronousDataFailureBeforeFinishFailsFinish( + Throwable cause) throws Exception { + ControlFutureClient failedClient = new ControlFutureClient(); + QueuedMessageSender sender = this.newSender( + failedClient, new MockTransportClient()); + + failedClient.dataFailure = cause; + try { + sender.send(1, new QueuedMessage(0, MessageType.MSG, + ByteBuffer.allocate(1))); + waitForQueueEmpty(sender, 1); + + CompletableFuture finishFuture = sender.send(1, MessageType.FINISH); + assertFutureFailedWith(finishFuture, cause); + Assert.assertFalse(await(failedClient.finishCalled)); + } finally { + sender.close(); + } + } + + private static void waitForQueueEmpty(QueuedMessageSender sender, + int workerId) + throws InterruptedException { + Object[] channels = Whitebox.getInternalState(sender, "channels"); + MessageQueue queue = Whitebox.getInternalState(channels[workerId - 1], + "queue"); + long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(1L); + while (queue.peek() != null && System.nanoTime() < deadline) { + Thread.sleep(10L); + } + Assert.assertTrue("Timed out to wait for sender queue to be empty", + queue.peek() == null); + } + private static void assertFutureFailedWithMessage(CompletableFuture future, String message) throws InterruptedException, TimeoutException { @@ -376,50 +403,27 @@ private static void assertFutureFailedWithMessage(CompletableFuture future private static class ControlFutureClient extends MockTransportClient { - private final CountDownLatch startCalled; - private final CountDownLatch finishCalled; - private final CountDownLatch dataSendCalled; - private final CountDownLatch allowDataSend; - private final CompletableFuture startFuture; - private final CompletableFuture finishFuture; - private RuntimeException startFailure; - private RuntimeException finishFailure; - private TransportException startTransportFailure; - private TransportException finishTransportFailure; + private final CountDownLatch startCalled = new CountDownLatch(1); + private final CountDownLatch finishCalled = new CountDownLatch(1); + private final CountDownLatch dataSendCalled = new CountDownLatch(1); + private final CountDownLatch allowDataSend = new CountDownLatch(1); + private final CompletableFuture startFuture = new CompletableFuture<>(); + private final CompletableFuture finishFuture = new CompletableFuture<>(); + private Throwable startFailure; + private Throwable finishFailure; private Throwable dataFailure; private boolean blockDataSend; - public ControlFutureClient() { - this.startCalled = new CountDownLatch(1); - this.finishCalled = new CountDownLatch(1); - this.dataSendCalled = new CountDownLatch(1); - this.allowDataSend = new CountDownLatch(1); - this.startFuture = new CompletableFuture<>(); - this.finishFuture = new CompletableFuture<>(); - } - @Override - public CompletableFuture startSessionAsync() - throws TransportException { - if (this.startTransportFailure != null) { - throw this.startTransportFailure; - } - if (this.startFailure != null) { - throw this.startFailure; - } + public CompletableFuture startSessionAsync() throws TransportException { + throwFailure(this.startFailure); this.startCalled.countDown(); return this.startFuture; } @Override - public CompletableFuture finishSessionAsync() - throws TransportException { - if (this.finishTransportFailure != null) { - throw this.finishTransportFailure; - } - if (this.finishFailure != null) { - throw this.finishFailure; - } + public CompletableFuture finishSessionAsync() throws TransportException { + throwFailure(this.finishFailure); this.finishCalled.countDown(); return this.finishFuture; } @@ -436,13 +440,17 @@ public boolean send(MessageType messageType, int partition, throw new TransportException("Interrupted data send", e); } } - if (this.dataFailure instanceof TransportException) { - throw (TransportException) this.dataFailure; + throwFailure(this.dataFailure); + return true; + } + + private static void throwFailure(Throwable failure) throws TransportException { + if (failure instanceof TransportException) { + throw (TransportException) failure; } - if (this.dataFailure instanceof RuntimeException) { - throw (RuntimeException) this.dataFailure; + if (failure instanceof RuntimeException) { + throw (RuntimeException) failure; } - return true; } @Override @@ -455,52 +463,5 @@ public InetSocketAddress remoteAddress() { return new InetSocketAddress("127.0.0.1", 8080); } - public boolean awaitStart() throws InterruptedException { - return this.startCalled.await(1, TimeUnit.SECONDS); - } - - public boolean awaitFinish() throws InterruptedException { - return this.finishCalled.await(1, TimeUnit.SECONDS); - } - - public void blockDataSend() { - this.blockDataSend = true; - } - - public boolean awaitDataSend() throws InterruptedException { - return this.dataSendCalled.await(1, TimeUnit.SECONDS); - } - - public void allowDataSend() { - this.allowDataSend.countDown(); - } - - public void completeStart() { - this.startFuture.complete(null); - } - - public void completeFinish() { - this.finishFuture.complete(null); - } - - public void failStartWith(RuntimeException failure) { - this.startFailure = failure; - } - - public void failStartWithTransportException(TransportException failure) { - this.startTransportFailure = failure; - } - - public void failFinishWith(RuntimeException failure) { - this.finishFailure = failure; - } - - public void failFinishWithTransportException(TransportException failure) { - this.finishTransportFailure = failure; - } - - public void failDataWith(Throwable failure) { - this.dataFailure = failure; - } } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 7889573c6..511a2f8b6 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -17,12 +17,9 @@ package org.apache.hugegraph.computer.suite.integrate; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; @@ -32,6 +29,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Function; +import java.util.function.Supplier; import org.apache.hugegraph.computer.algorithm.centrality.pagerank.PageRankParams; import org.apache.hugegraph.computer.core.common.exception.ComputerException; @@ -63,10 +61,8 @@ public class SenderIntegrateTest { private static final Class COMPUTATION = MockComputation.class; private static final long BSP_WAIT_TIMEOUT = TimeUnit.MINUTES.toMillis(5L); - private static final long SERVICE_WAIT_TIMEOUT = - BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L); - private static final long TEST_THREAD_JOIN_TIMEOUT = - TimeUnit.SECONDS.toMillis(5L); + private static final long SERVICE_WAIT_TIMEOUT = BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L); + private static final long TEST_THREAD_JOIN_TIMEOUT = TimeUnit.SECONDS.toMillis(5L); @BeforeClass public static void init() { @@ -119,34 +115,30 @@ public void testCleanupFailureDoesNotHideWaitFailure() { @Test public void testMasterErrorCompletesServiceFuture() throws Exception { - CompletableFuture masterFuture = new CompletableFuture<>(); + ServiceLifecycle lifecycle = new ServiceLifecycle(); Error cause = new AssertionError("master failed"); - Thread masterThread = new Thread(() -> this.executeMasterTask( - masterFuture, () -> { - throw cause; - })); - masterThread.start(); + ServiceTask master = newServiceTask( + Object::new, lifecycle::registerMaster, + service -> { + throw cause; + }, service -> { + }); + master.thread.start(); try { - masterFuture.get(1, TimeUnit.SECONDS); + master.future.get(1, TimeUnit.SECONDS); Assert.fail("Expected master error to fail the service future"); } catch (ExecutionException e) { Assert.assertSame(cause, e.getCause()); } catch (TimeoutException e) { Assert.fail("Timed out to wait for master error"); } finally { - interruptAndJoinThreads(Arrays.asList(masterThread), + lifecycle.closeAll(); + interruptAndJoinThreads(Arrays.asList(master.thread), TEST_THREAD_JOIN_TIMEOUT); } } - @Test - public void testCiTimeoutsAllowHeavyInputStep() { - Assert.assertEquals(TimeUnit.MINUTES.toMillis(5L), BSP_WAIT_TIMEOUT); - Assert.assertEquals(BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L), - SERVICE_WAIT_TIMEOUT); - } - @Test public void testServiceLifecycleClosesLateRegisteredService() { ServiceLifecycle lifecycle = new ServiceLifecycle(); @@ -229,9 +221,9 @@ public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { } @Test - public void testCloseServicesAndJoinUsesOneTimeoutBudget() - throws Exception { - long timeout = 200L; + public void testCloseServicesAndJoinUsesOneTimeoutBudget() throws Exception { + long timeout = TimeUnit.SECONDS.toMillis(1L); + long maxElapsed = timeout + timeout / 2L; AtomicBoolean stopping = new AtomicBoolean(); CountDownLatch started = new CountDownLatch(3); Thread firstWorker = newInterruptIgnoringThread(stopping, started); @@ -243,13 +235,14 @@ public void testCloseServicesAndJoinUsesOneTimeoutBudget() Assert.assertTrue(started.await(1, TimeUnit.SECONDS)); long start = System.nanoTime(); + long elapsed = -1L; try { closeServicesAndJoin(new ServiceLifecycle(), Arrays.asList(firstWorker, secondWorker), master, timeout); Assert.fail("Expected service threads to time out"); } catch (ComputerException ignored) { - // The timeout is expected; the assertion below verifies its budget + elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); } finally { stopping.set(true); firstWorker.interrupt(); @@ -259,20 +252,17 @@ public void testCloseServicesAndJoinUsesOneTimeoutBudget() secondWorker.join(TimeUnit.SECONDS.toMillis(1L)); master.join(TimeUnit.SECONDS.toMillis(1L)); } - long elapsed = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start); Assert.assertTrue("Cleanup exceeded its shared timeout budget: " + elapsed, - elapsed < timeout * 2L); + elapsed < maxElapsed); } @Test - public void testCloseServicesAndJoinStopsWorkersBeforeMaster() - throws Exception { + public void testCloseBeforeMaster() throws Exception { ServiceLifecycle lifecycle = new ServiceLifecycle(); CountDownLatch workerStarted = new CountDownLatch(1); CountDownLatch workerStopped = new CountDownLatch(1); CountDownLatch masterStarted = new CountDownLatch(1); - AtomicBoolean masterInterruptedBeforeWorkerStopped = - new AtomicBoolean(); + AtomicBoolean masterInterruptedBeforeWorkerStopped = new AtomicBoolean(); Thread workerThread = new Thread(() -> { workerStarted.countDown(); try { @@ -319,258 +309,69 @@ public void testCloseServicesAndJoinStopsWorkersBeforeMaster() @Test public void testOneWorker() { ServiceLifecycle lifecycle = new ServiceLifecycle(); - CompletableFuture masterFuture = new CompletableFuture<>(); - Thread masterThread = new Thread(() -> { - String[] args = OptionsBuilder.newInstance() - .withJobId("local_002") - .withAlgorithm(PageRankParams.class) - .withResultName("rank") - .withResultClass(DoubleValue.class) - .withMessageClass(DoubleValue.class) - .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withTestBspTimeouts() - .withBufferThreshold(50) - .withBufferCapacity(60) - .withRpcServerHost("127.0.0.1") - .withRpcServerPort(8611) - .withRpcServerPort(0) - .build(); - this.executeMasterTask(masterFuture, () -> { - MasterService service = initMaster(args); - try { - if (!lifecycle.registerMaster(service::close)) { - masterFuture.cancel(false); - return; - } - service.execute(); - masterFuture.complete(null); - } finally { - closeMaster(service); - } - }); - }); - masterThread.setDaemon(true); - - CompletableFuture workerFuture = new CompletableFuture<>(); - Thread workerThread = new Thread(() -> { - String[] args = OptionsBuilder.newInstance() - .withJobId("local_002") - .withAlgorithm(PageRankParams.class) - .withResultName("rank") - .withResultClass(DoubleValue.class) - .withMessageClass(DoubleValue.class) - .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withTestBspTimeouts() - .withBufferThreshold(50) - .withBufferCapacity(60) - .withTransoprtServerPort(0) - .build(); - try { - WorkerService service = initWorker(args); - try { - if (!lifecycle.registerWorker(service::close)) { - workerFuture.cancel(false); - return; - } - service.execute(); - workerFuture.complete(null); - } finally { - closeWorker(service); - } - } catch (Throwable e) { - LOG.error("Failed to execute worker service", e); - workerFuture.completeExceptionally(e); - } - }); - workerThread.setDaemon(true); - masterThread.start(); - workerThread.start(); - - waitForServicesAndClose(lifecycle, - Arrays.asList(workerFuture, masterFuture), - Arrays.asList(workerThread), masterThread); + String[] masterArgs = commonOptions("local_002", 1) + .withBufferThreshold(50) + .withBufferCapacity(60) + .withRpcServerHost("127.0.0.1") + .withRpcServerPort(0) + .build(); + String[] workerArgs = commonOptions("local_002", 1) + .withBufferThreshold(50) + .withBufferCapacity(60) + .withTransoprtServerPort(0) + .build(); + ServiceTask master = masterTask(lifecycle, masterArgs); + ServiceTask worker = workerTask(lifecycle, workerArgs, + WorkerService::execute); + runServices(lifecycle, Arrays.asList(worker), master); } @Test - public void testMultiWorkers() throws IOException { + public void testMultiWorkers() { int workerCount = 3; int partitionCount = 3; ServiceLifecycle lifecycle = new ServiceLifecycle(); - CompletableFuture masterFuture = new CompletableFuture<>(); - Thread masterThread = new Thread(() -> { - String[] args = OptionsBuilder.newInstance() - .withJobId("local_003") - .withAlgorithm(PageRankParams.class) - .withResultName("rank") - .withResultClass(DoubleValue.class) - .withMessageClass(DoubleValue.class) - .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(workerCount) - .withPartitionCount(partitionCount) - .withTestBspTimeouts() - .withRpcServerHost("127.0.0.1") - .withRpcServerPort(0) - .build(); - try { - MasterService service = initMaster(args); - try { - if (!lifecycle.registerMaster(service::close)) { - masterFuture.cancel(false); - return; - } - service.execute(); - masterFuture.complete(null); - } finally { - closeMaster(service); - } - } catch (Throwable e) { - LOG.error("Failed to execute master service", e); - masterFuture.completeExceptionally(e); - } - }); - masterThread.setDaemon(true); - - Map> workers = new HashMap<>(workerCount); + String[] masterArgs = commonOptions("local_003", workerCount) + .withPartitionCount(partitionCount) + .withRpcServerHost("127.0.0.1") + .withRpcServerPort(0) + .build(); + ServiceTask master = masterTask(lifecycle, masterArgs); + List workers = new ArrayList<>(workerCount); for (int i = 1; i <= workerCount; i++) { - String dir = "[jobs-" + i + "]"; - - CompletableFuture workerFuture = new CompletableFuture<>(); - Thread thread = new Thread(() -> { - String[] args; - args = OptionsBuilder.newInstance() - .withJobId("local_003") - .withAlgorithm(PageRankParams.class) - .withResultName("rank") - .withResultClass(DoubleValue.class) - .withMessageClass(DoubleValue.class) - .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(workerCount) - .withPartitionCount(partitionCount) - .withTestBspTimeouts() - .withTransoprtServerPort(0) - .withDataDirs(dir) - .build(); - try { - WorkerService service = initWorker(args); - try { - if (!lifecycle.registerWorker(service::close)) { - workerFuture.cancel(false); - return; - } - service.execute(); - workerFuture.complete(null); - } finally { - closeWorker(service); - } - } catch (Throwable e) { - LOG.error("Failed to execute worker service", e); - workerFuture.completeExceptionally(e); - } - }); - thread.setDaemon(true); - workers.put(thread, workerFuture); + String[] workerArgs = commonOptions("local_003", workerCount) + .withPartitionCount(partitionCount) + .withTransoprtServerPort(0) + .withDataDirs("[jobs-" + i + "]") + .build(); + workers.add(workerTask(lifecycle, workerArgs, + WorkerService::execute)); } - - masterThread.start(); - for (Thread worker : workers.keySet()) { - worker.start(); - } - - List> futures = new ArrayList<>(workers.values()); - futures.add(masterFuture); - waitForServicesAndClose(lifecycle, futures, - new ArrayList<>(workers.keySet()), - masterThread); + runServices(lifecycle, workers, master); } @Test public void testOneWorkerWithBusyClient() { ServiceLifecycle lifecycle = new ServiceLifecycle(); - CompletableFuture masterFuture = new CompletableFuture<>(); - Thread masterThread = new Thread(() -> { - String[] args = OptionsBuilder.newInstance() - .withJobId("local_002") - .withAlgorithm(PageRankParams.class) - .withResultName("rank") - .withResultClass(DoubleValue.class) - .withMessageClass(DoubleValue.class) - .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withTestBspTimeouts() - .withWriteBufferHighMark(10) - .withWriteBufferLowMark(5) - .withRpcServerHost("127.0.0.1") - .withRpcServerPort(0) - .build(); - try { - MasterService service = initMaster(args); - try { - if (!lifecycle.registerMaster(service::close)) { - masterFuture.cancel(false); - return; - } - service.execute(); - masterFuture.complete(null); - } finally { - closeMaster(service); - } - } catch (Throwable e) { - LOG.error("Failed to execute master service", e); - masterFuture.completeExceptionally(e); - } - }); - masterThread.setDaemon(true); - - CompletableFuture workerFuture = new CompletableFuture<>(); int transoprtServerPort = 8998; - Thread workerThread = new Thread(() -> { - String[] args = OptionsBuilder.newInstance() - .withJobId("local_002") - .withAlgorithm(PageRankParams.class) - .withResultName("rank") - .withResultClass(DoubleValue.class) - .withMessageClass(DoubleValue.class) - .withMaxSuperStep(3) - .withComputationClass(COMPUTATION) - .withWorkerCount(1) - .withTestBspTimeouts() - .withWriteBufferHighMark(20) - .withWriteBufferLowMark(10) - .withTransoprtServerPort(transoprtServerPort) - .build(); - try { - WorkerService service = initWorker(args); - try { - if (!lifecycle.registerWorker(service::close)) { - workerFuture.cancel(false); - return; - } - // Let send rate slowly - this.slowSendFunc(service, transoprtServerPort); - service.execute(); - workerFuture.complete(null); - } finally { - closeWorker(service); - } - } catch (Throwable e) { - LOG.error("Failed to execute worker service", e); - workerFuture.completeExceptionally(e); - } + String[] masterArgs = commonOptions("local_002", 1) + .withWriteBufferHighMark(10) + .withWriteBufferLowMark(5) + .withRpcServerHost("127.0.0.1") + .withRpcServerPort(0) + .build(); + String[] workerArgs = commonOptions("local_002", 1) + .withWriteBufferHighMark(20) + .withWriteBufferLowMark(10) + .withTransoprtServerPort(transoprtServerPort) + .build(); + ServiceTask master = masterTask(lifecycle, masterArgs); + ServiceTask worker = workerTask(lifecycle, workerArgs, service -> { + // Let send rate slowly + this.slowSendFunc(service, transoprtServerPort); + service.execute(); }); - workerThread.setDaemon(true); - masterThread.start(); - workerThread.start(); - - waitForServicesAndClose(lifecycle, - Arrays.asList(workerFuture, masterFuture), - Arrays.asList(workerThread), masterThread); + runServices(lifecycle, Arrays.asList(worker), master); } private void slowSendFunc(WorkerService service, int port) throws TransportException { @@ -598,14 +399,75 @@ private void slowSendFunc(WorkerService service, int port) throws TransportExcep Whitebox.setInternalState(clientSession, "sendFunction", sendFunc); } - private void executeMasterTask(CompletableFuture future, - Runnable task) { - try { - task.run(); - } catch (Throwable e) { - LOG.error("Failed to execute master service", e); - future.completeExceptionally(e); + private static OptionsBuilder commonOptions(String jobId, + int workerCount) { + return OptionsBuilder.newInstance() + .withJobId(jobId) + .withAlgorithm(PageRankParams.class) + .withResultName("rank") + .withResultClass(DoubleValue.class) + .withMessageClass(DoubleValue.class) + .withMaxSuperStep(3) + .withComputationClass(COMPUTATION) + .withWorkerCount(workerCount) + .withTestBspTimeouts(); + } + + private ServiceTask masterTask(ServiceLifecycle lifecycle, String[] args) { + return newServiceTask(() -> this.initMaster(args), + lifecycle::registerMaster, + MasterService::execute, + MasterService::close); + } + + private ServiceTask workerTask(ServiceLifecycle lifecycle, String[] args, + ServiceExecutor executor) { + return newServiceTask(() -> this.initWorker(args), + lifecycle::registerWorker, executor, + WorkerService::close); + } + + private static ServiceTask newServiceTask( + Supplier initializer, Function registrar, + ServiceExecutor executor, Consumer closer) { + CompletableFuture future = new CompletableFuture<>(); + Thread thread = new Thread(() -> { + try { + T service = initializer.get(); + try { + if (!registrar.apply(() -> closer.accept(service))) { + future.cancel(false); + return; + } + executor.execute(service); + future.complete(null); + } finally { + closer.accept(service); + } + } catch (Throwable e) { + LOG.error("Failed to execute service", e); + future.completeExceptionally(e); + } + }); + thread.setDaemon(true); + return new ServiceTask(thread, future); + } + + private static void runServices(ServiceLifecycle lifecycle, + List workers, + ServiceTask master) { + master.thread.start(); + List> futures = + new ArrayList<>(workers.size() + 1); + List workerThreads = new ArrayList<>(workers.size()); + for (ServiceTask worker : workers) { + worker.thread.start(); + futures.add(worker.future); + workerThreads.add(worker.thread); } + futures.add(master.future); + waitForServicesAndClose(lifecycle, futures, workerThreads, + master.thread); } private MasterService initMaster(String[] args) { @@ -613,7 +475,7 @@ private MasterService initMaster(String[] args) { ComputerContextUtil.convertToMap(args)); MasterService service = new MasterService(); return initializeService(service, s -> s.init(config), - SenderIntegrateTest::closeMaster); + MasterService::close); } private WorkerService initWorker(String[] args) { @@ -621,7 +483,7 @@ private WorkerService initWorker(String[] args) { ComputerContextUtil.convertToMap(args)); WorkerService service = new WorkerService(); return initializeService(service, s -> s.init(config), - SenderIntegrateTest::closeWorker); + WorkerService::close); } private static T initializeService(T service, Consumer initializer, @@ -649,13 +511,7 @@ private static void waitForServices(List> futures) { }); } CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) - .whenComplete((r, e) -> { - if (e == null) { - result.complete(null); - } else { - result.completeExceptionally(e); - } - }); + .thenRun(() -> result.complete(null)); try { result.get(SERVICE_WAIT_TIMEOUT, TimeUnit.MILLISECONDS); } catch (TimeoutException e) { @@ -788,15 +644,20 @@ private static Throwable addFailure(Throwable failure, Throwable cause) { return failure; } - private static void closeWorker(WorkerService service) { - if (service != null) { - service.close(); - } + @FunctionalInterface + private interface ServiceExecutor { + + void execute(T service) throws Throwable; } - private static void closeMaster(MasterService service) { - if (service != null) { - service.close(); + private static class ServiceTask { + + private final Thread thread; + private final CompletableFuture future; + + public ServiceTask(Thread thread, CompletableFuture future) { + this.thread = thread; + this.future = future; } } @@ -815,17 +676,14 @@ public boolean registerMaster(Runnable closer) { } private boolean register(List closers, Runnable closer) { - boolean closeImmediately; synchronized (this) { - closeImmediately = this.closing; - if (!closeImmediately) { + if (!this.closing) { closers.add(closer); + return true; } } - if (closeImmediately) { - closer.run(); - } - return !closeImmediately; + closer.run(); + return false; } public Throwable closeAll() { @@ -838,8 +696,9 @@ public Throwable closeAll() { this.workerClosers.clear(); this.masterClosers.clear(); } + workerClosers.addAll(masterClosers); Throwable failure = closeAll(workerClosers, null); - return closeAll(masterClosers, failure); + return failure; } private static Throwable closeAll(List closers, @@ -848,11 +707,7 @@ private static Throwable closeAll(List closers, try { closer.run(); } catch (Throwable e) { - if (failure == null) { - failure = e; - } else { - failure.addSuppressed(e); - } + failure = addFailure(failure, e); } } return failure; From f82527a0043b8034278971eb60636b461ed2fbe7 Mon Sep 17 00:00:00 2001 From: Loki Date: Wed, 29 Jul 2026 12:39:37 +0800 Subject: [PATCH 11/12] fix checkstyle --- .../computer/core/sender/QueuedMessageSenderTest.java | 9 ++++++--- .../computer/suite/integrate/SenderIntegrateTest.java | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index a86e62a3f..d2bda26fa 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -239,12 +239,14 @@ public void testOtherClients() throws Exception { @Test public void testQueuedFinish() throws Exception { - this.assertSynchronousDataFailureCompletesQueuedFinish(new TransportException("data send failed")); + this.assertSynchronousDataFailureCompletesQueuedFinish( + new TransportException("data send failed")); } @Test public void testCompletesQueuedFinish() throws Exception { - this.assertSynchronousDataFailureCompletesQueuedFinish(new IllegalStateException("data send failed")); + this.assertSynchronousDataFailureCompletesQueuedFinish( + new IllegalStateException("data send failed")); } @Test @@ -301,7 +303,8 @@ private static boolean await(CountDownLatch latch) throws InterruptedException { return latch.await(1, TimeUnit.SECONDS); } - private void assertSynchronousDataFailureCompletesQueuedFinish(Throwable cause) throws Exception { + private void assertSynchronousDataFailureCompletesQueuedFinish( + Throwable cause) throws Exception { ControlFutureClient failedClient = new ControlFutureClient(); ControlFutureClient activeClient = new ControlFutureClient(); QueuedMessageSender sender = this.newSender(failedClient, activeClient); diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 511a2f8b6..85d7b1a93 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -61,7 +61,8 @@ public class SenderIntegrateTest { private static final Class COMPUTATION = MockComputation.class; private static final long BSP_WAIT_TIMEOUT = TimeUnit.MINUTES.toMillis(5L); - private static final long SERVICE_WAIT_TIMEOUT = BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L); + private static final long SERVICE_WAIT_TIMEOUT = + BSP_WAIT_TIMEOUT + TimeUnit.SECONDS.toMillis(10L); private static final long TEST_THREAD_JOIN_TIMEOUT = TimeUnit.SECONDS.toMillis(5L); @BeforeClass From d95a78d6a4e4bdd664d917e5a5b325ffe9000c81 Mon Sep 17 00:00:00 2001 From: Loki Date: Wed, 29 Jul 2026 20:52:39 +0800 Subject: [PATCH 12/12] fix: preserve sender and cleanup failures --- .../core/sender/QueuedMessageSender.java | 3 + .../core/sender/QueuedMessageSenderTest.java | 60 ++++++++ .../suite/integrate/SenderIntegrateTest.java | 137 +++++++++++++++++- 3 files changed, 197 insertions(+), 3 deletions(-) diff --git a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java index 6f452074f..e289d269f 100644 --- a/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java +++ b/computer/computer-core/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSender.java @@ -351,6 +351,9 @@ private boolean controlFutureInFlight(CompletableFuture future) { private void completeControlFuture(CompletableFuture future, Throwable cause) { if (!this.controlFutureRef.compareAndSet(future, null)) { + if (cause != null) { + this.failDataSend(cause); + } return; } if (cause == null) { diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index d2bda26fa..cb66c29ec 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -24,6 +24,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; import org.apache.hugegraph.computer.core.common.exception.TransportException; import org.apache.hugegraph.computer.core.config.ComputerOptions; @@ -149,6 +150,65 @@ public void testTransportExceptionControlFuture() throws Exception { } } + @Test + public void testExceptionalCompletionCasLossFailsNextControl() + throws Exception { + ControlFutureClient client = new ControlFutureClient(); + QueuedMessageSender sender = this.newSender( + client, new MockTransportClient()); + CountDownLatch failureObserved = new CountDownLatch(1); + CountDownLatch resumeFailure = new CountDownLatch(1); + Thread failureThread = null; + + try { + CompletableFuture startFuture = sender.send( + 1, MessageType.START); + Assert.assertTrue(await(client.startCalled)); + + Object[] channels = Whitebox.getInternalState(sender, "channels"); + Object channel = channels[0]; + AtomicReference> controlFutureRef = + Whitebox.getInternalState(channel, "controlFutureRef"); + AtomicReference> observedFuture = + new AtomicReference<>(); + TransportException cause = + new TransportException("connection failed"); + failureThread = new Thread(() -> { + observedFuture.set(controlFutureRef.get()); + failureObserved.countDown(); + try { + resumeFailure.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new AssertionError(e); + } + Whitebox.invoke(channel.getClass(), new Class[] { + CompletableFuture.class, + Throwable.class}, + "completeControlFuture", channel, + observedFuture.get(), cause); + }); + failureThread.start(); + Assert.assertTrue(await(failureObserved)); + + client.startFuture.complete(null); + startFuture.get(1, TimeUnit.SECONDS); + CompletableFuture finishFuture = sender.send( + 1, MessageType.FINISH); + Assert.assertTrue(await(client.finishCalled)); + + resumeFailure.countDown(); + assertFutureFailedWith(finishFuture, cause); + client.finishFuture.complete(null); + } finally { + resumeFailure.countDown(); + if (failureThread != null) { + failureThread.join(TimeUnit.SECONDS.toMillis(1L)); + } + sender.close(); + } + } + @Test public void testTransportExceptionDispatch() throws Exception { ControlFutureClient client = new ControlFutureClient(); diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index 85d7b1a93..b69ac0c67 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -27,6 +27,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; @@ -140,6 +141,100 @@ public void testMasterErrorCompletesServiceFuture() throws Exception { } } + @Test + public void testServiceTaskPreservesExecutionFailure() throws Exception { + RuntimeException executeFailure = + new IllegalStateException("service execution failed"); + RuntimeException closeFailure = + new IllegalStateException("service close failed"); + ServiceTask task = newServiceTask( + Object::new, closer -> true, + service -> { + throw executeFailure; + }, service -> { + throw closeFailure; + }); + task.thread.start(); + + try { + task.future.get(1, TimeUnit.SECONDS); + Assert.fail("Expected service task to fail"); + } catch (ExecutionException e) { + Assert.assertSame(executeFailure, e.getCause()); + Assert.assertArrayEquals(new Throwable[]{closeFailure}, + e.getCause().getSuppressed()); + } finally { + interruptAndJoinThreads(Arrays.asList(task.thread), + TEST_THREAD_JOIN_TIMEOUT); + } + } + + @Test + public void testServiceCleanupFailureFailsTaskWithoutDoubleClose() + throws Exception { + ServiceLifecycle lifecycle = new ServiceLifecycle(); + AtomicInteger closeCount = new AtomicInteger(); + CountDownLatch executeStarted = new CountDownLatch(1); + CountDownLatch allowExecuteReturn = new CountDownLatch(1); + CountDownLatch closeStarted = new CountDownLatch(1); + CountDownLatch allowCloseReturn = new CountDownLatch(1); + RuntimeException cause = + new IllegalStateException("service close failed"); + ServiceTask task = newServiceTask( + Object::new, lifecycle::registerWorker, + service -> { + executeStarted.countDown(); + allowExecuteReturn.await(); + }, service -> { + closeCount.incrementAndGet(); + closeStarted.countDown(); + try { + allowCloseReturn.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new AssertionError(e); + } + throw cause; + }); + CompletableFuture lifecycleResult = + new CompletableFuture<>(); + Thread lifecycleThread = new Thread( + () -> lifecycleResult.complete(lifecycle.closeAll())); + task.thread.start(); + + Throwable taskFailure = null; + try { + Assert.assertTrue(executeStarted.await(1, TimeUnit.SECONDS)); + lifecycleThread.start(); + Assert.assertTrue(closeStarted.await(1, TimeUnit.SECONDS)); + allowExecuteReturn.countDown(); + task.thread.join(TimeUnit.SECONDS.toMillis(1L)); + Assert.assertFalse("Service future completed before cleanup", + task.future.isDone()); + + allowCloseReturn.countDown(); + try { + task.future.get(1, TimeUnit.SECONDS); + } catch (ExecutionException e) { + taskFailure = e.getCause(); + } + task.thread.join(TEST_THREAD_JOIN_TIMEOUT); + lifecycleThread.join(TEST_THREAD_JOIN_TIMEOUT); + Assert.assertSame(cause, lifecycleResult.get( + 1, TimeUnit.SECONDS)); + } finally { + allowExecuteReturn.countDown(); + allowCloseReturn.countDown(); + lifecycle.closeAll(); + interruptAndJoinThreads(Arrays.asList(task.thread, + lifecycleThread), + TEST_THREAD_JOIN_TIMEOUT); + } + + Assert.assertSame(cause, taskFailure); + Assert.assertEquals(1, closeCount.get()); + } + @Test public void testServiceLifecycleClosesLateRegisteredService() { ServiceLifecycle lifecycle = new ServiceLifecycle(); @@ -435,16 +530,52 @@ private static ServiceTask newServiceTask( Thread thread = new Thread(() -> { try { T service = initializer.get(); + Runnable closeService = new Runnable() { + + private boolean closed; + private Throwable failure; + + @Override + public synchronized void run() { + if (!this.closed) { + this.closed = true; + try { + closer.accept(service); + } catch (RuntimeException | Error e) { + this.failure = e; + } + } + if (this.failure instanceof RuntimeException) { + throw (RuntimeException) this.failure; + } + if (this.failure != null) { + throw (Error) this.failure; + } + } + }; + Throwable failure = null; try { - if (!registrar.apply(() -> closer.accept(service))) { + if (!registrar.apply(closeService)) { future.cancel(false); return; } executor.execute(service); - future.complete(null); + } catch (Throwable e) { + failure = e; + throw e; } finally { - closer.accept(service); + try { + closeService.run(); + } catch (Throwable closeFailure) { + if (failure == null) { + throw closeFailure; + } + if (closeFailure != failure) { + failure.addSuppressed(closeFailure); + } + } } + future.complete(null); } catch (Throwable e) { LOG.error("Failed to execute service", e); future.completeExceptionally(e);

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 literal 0 HcmV?d00001 diff --git a/computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b b/computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b new file mode 100644 index 000000000..0aa6fb546 --- /dev/null +++ b/computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b @@ -0,0 +1 @@ +test data \ No newline at end of file diff --git a/computer/computer-test/hgkv/hgkv_1.hgkv/hgkv_1.hgkv b/computer/computer-test/hgkv/hgkv_1.hgkv/hgkv_1.hgkv new file mode 100644 index 0000000000000000000000000000000000000000..f58347329ebd270464c88a2d6b08cc81ba58293a GIT binary patch literal 88 qcmZQ%U|?Wmgb_?wSj=!S1d9bO#s+3(q-U40Gq^F>Fo3v1KnwsXaRPS$ literal 0 HcmV?d00001 diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/network/netty/NettyTransportClientTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/network/netty/NettyTransportClientTest.java index fac4046b6..6f254bdad 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/network/netty/NettyTransportClientTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/network/netty/NettyTransportClientTest.java @@ -127,7 +127,6 @@ public void testSend() throws IOException { @Test public void testDataUniformity() throws IOException { - NettyTransportClient client = (NettyTransportClient) this.oneClient(); byte[] sourceBytes1 = StringEncodeUtil.encode("test data message"); byte[] sourceBytes2 = StringEncodeUtil.encode("test data edge"); byte[] sourceBytes3 = StringEncodeUtil.encode("test data vertex"); @@ -165,6 +164,7 @@ public void testDataUniformity() throws IOException { return null; }).when(serverHandler).handle(Mockito.any(), Mockito.eq(1), Mockito.any()); + NettyTransportClient client = (NettyTransportClient) this.oneClient(); client.startSession(); client.send(MessageType.MSG, 1, ByteBuffer.wrap(sourceBytes1)); client.send(MessageType.EDGE, 1, ByteBuffer.wrap(sourceBytes2)); @@ -274,12 +274,12 @@ public void testFlowControl() throws IOException { @Test public void testHandlerException() throws IOException { - NettyTransportClient client = (NettyTransportClient) this.oneClient(); - client.startSession(); - Mockito.doThrow(new RuntimeException("test exception")).when(serverHandler) .handle(Mockito.any(), Mockito.anyInt(), Mockito.any()); + NettyTransportClient client = (NettyTransportClient) this.oneClient(); + client.startSession(); + ByteBuffer buffer = ByteBuffer.wrap(StringEncodeUtil.encode("test data")); boolean send = client.send(MessageType.MSG, 1, buffer); Assert.assertTrue(send); diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java index ffd3ff1ea..621964b81 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/core/sender/QueuedMessageSenderTest.java @@ -154,6 +154,36 @@ public void testTransportExceptionCompletesInFlightControlFuture() } } + @Test + public void testTransportExceptionCompletesQueuedControlFutureBeforeDispatch() + throws Exception { + QueuedMessageSender sender = new QueuedMessageSender(this.config); + ControlFutureClient client = new ControlFutureClient(); + sender.addWorkerClient(1, client); + sender.addWorkerClient(2, new MockTransportClient()); + sender.init(); + + client.blockDataSend(); + try { + sender.send(1, new QueuedMessage(0, MessageType.MSG, + ByteBuffer.allocate(1))); + Assert.assertTrue(client.awaitDataSend()); + + CompletableFuture startFuture = sender.send(1, + MessageType.START); + TransportException cause = + new TransportException("connection failed before start"); + sender.transportExceptionCaught(cause, client.connectionId()); + assertFutureFailedWith(startFuture, cause); + + client.allowDataSend(); + Assert.assertFalse(client.awaitStart()); + } finally { + client.allowDataSend(); + sender.close(); + } + } + @Test public void testSynchronousControlFailureCompletesFutureAndKeepsExecutorAlive() throws Exception { @@ -194,6 +224,51 @@ public void testSynchronousControlFailureCompletesFutureAndKeepsExecutorAlive() } } + @Test + public void testSynchronousTransportFailureKeepsExecutorAliveForOtherClients() + throws Exception { + QueuedMessageSender sender = new QueuedMessageSender(this.config); + ControlFutureClient failedClient = new ControlFutureClient(); + ControlFutureClient activeClient = new ControlFutureClient(); + sender.addWorkerClient(1, failedClient); + sender.addWorkerClient(2, activeClient); + sender.init(); + + try { + TransportException startCause = + new TransportException("start session failed"); + failedClient.failStartWithTransportException(startCause); + CompletableFuture failedStart = sender.send(1, + MessageType.START); + assertFutureFailedWith(failedStart, startCause); + + CompletableFuture activeStart = sender.send(2, + MessageType.START); + Assert.assertTrue(activeClient.awaitStart()); + activeClient.completeStart(); + activeStart.get(1, TimeUnit.SECONDS); + + TransportException finishCause = + new TransportException("finish session failed"); + failedClient.failFinishWithTransportException(finishCause); + CompletableFuture failedFinish = sender.send(1, + MessageType.FINISH); + assertFutureFailedWith(failedFinish, finishCause); + + CompletableFuture activeFinish = sender.send(2, + MessageType.FINISH); + Assert.assertTrue(activeClient.awaitFinish()); + activeClient.completeFinish(); + activeFinish.get(1, TimeUnit.SECONDS); + + Thread sendExecutor = Whitebox.getInternalState(sender, + "sendExecutor"); + Assert.assertTrue(sendExecutor.isAlive()); + } finally { + sender.close(); + } + } + @Test public void testControlFutureConflictKeepsSendExecutorAlive() throws Exception { @@ -257,20 +332,31 @@ private static class ControlFutureClient extends MockTransportClient { private final CountDownLatch startCalled; private final CountDownLatch finishCalled; + private final CountDownLatch dataSendCalled; + private final CountDownLatch allowDataSend; private final CompletableFuture startFuture; private final CompletableFuture finishFuture; private RuntimeException startFailure; private RuntimeException finishFailure; + private TransportException startTransportFailure; + private TransportException finishTransportFailure; + private boolean blockDataSend; public ControlFutureClient() { this.startCalled = new CountDownLatch(1); this.finishCalled = new CountDownLatch(1); + this.dataSendCalled = new CountDownLatch(1); + this.allowDataSend = new CountDownLatch(1); this.startFuture = new CompletableFuture<>(); this.finishFuture = new CompletableFuture<>(); } @Override - public CompletableFuture startSessionAsync() { + public CompletableFuture startSessionAsync() + throws TransportException { + if (this.startTransportFailure != null) { + throw this.startTransportFailure; + } if (this.startFailure != null) { throw this.startFailure; } @@ -279,7 +365,11 @@ public CompletableFuture startSessionAsync() { } @Override - public CompletableFuture finishSessionAsync() { + public CompletableFuture finishSessionAsync() + throws TransportException { + if (this.finishTransportFailure != null) { + throw this.finishTransportFailure; + } if (this.finishFailure != null) { throw this.finishFailure; } @@ -289,7 +379,16 @@ public CompletableFuture finishSessionAsync() { @Override public boolean send(MessageType messageType, int partition, - ByteBuffer buffer) { + ByteBuffer buffer) throws TransportException { + if (this.blockDataSend) { + this.dataSendCalled.countDown(); + try { + this.allowDataSend.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new TransportException("Interrupted data send", e); + } + } return true; } @@ -311,6 +410,18 @@ public boolean awaitFinish() throws InterruptedException { return this.finishCalled.await(1, TimeUnit.SECONDS); } + public void blockDataSend() { + this.blockDataSend = true; + } + + public boolean awaitDataSend() throws InterruptedException { + return this.dataSendCalled.await(1, TimeUnit.SECONDS); + } + + public void allowDataSend() { + this.allowDataSend.countDown(); + } + public void completeStart() { this.startFuture.complete(null); } @@ -323,8 +434,16 @@ public void failStartWith(RuntimeException failure) { this.startFailure = failure; } + public void failStartWithTransportException(TransportException failure) { + this.startTransportFailure = failure; + } + public void failFinishWith(RuntimeException failure) { this.finishFailure = failure; } + + public void failFinishWithTransportException(TransportException failure) { + this.finishTransportFailure = failure; + } } } diff --git a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java index c7f8696cf..5e78dd723 100644 --- a/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java +++ b/computer/computer-test/src/main/java/org/apache/hugegraph/computer/suite/integrate/SenderIntegrateTest.java @@ -30,6 +30,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import java.util.function.Function; import org.apache.hugegraph.computer.algorithm.centrality.pagerank.PageRankParams; @@ -132,6 +133,23 @@ public void testServiceLifecycleClosesWorkersBeforeMasterAfterFailure() { Assert.assertTrue(masterClosed.get()); } + @Test + public void testInitializeServiceClosesPartiallyInitializedService() { + AtomicBoolean closed = new AtomicBoolean(); + RuntimeException cause = new IllegalStateException("init failed"); + + try { + initializeService(new Object(), service -> { + throw cause; + }, service -> closed.set(true)); + Assert.fail("Expected initialization to fail"); + } catch (RuntimeException e) { + Assert.assertSame(cause, e); + } + + Assert.assertTrue(closed.get()); + } + @Test public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { ServiceLifecycle lifecycle = new ServiceLifecycle(); @@ -149,12 +167,58 @@ public void testCloseServicesAndJoinStopsSpawnedThreads() throws Exception { thread.start(); Assert.assertTrue(started.await(1, TimeUnit.SECONDS)); - closeServicesAndJoin(lifecycle, Arrays.asList(thread)); + closeServicesAndJoin(lifecycle, Arrays.asList(thread), null); Assert.assertTrue(closed.get()); Assert.assertFalse(thread.isAlive()); } + @Test + public void testCloseServicesAndJoinStopsWorkersBeforeMaster() + throws Exception { + ServiceLifecycle lifecycle = new ServiceLifecycle(); + CountDownLatch workerStarted = new CountDownLatch(1); + CountDownLatch workerStopped = new CountDownLatch(1); + CountDownLatch masterStarted = new CountDownLatch(1); + AtomicBoolean masterInterruptedBeforeWorkerStopped = + new AtomicBoolean(); + Thread workerThread = new Thread(() -> { + workerStarted.countDown(); + try { + Thread.sleep(Long.MAX_VALUE); + } catch (InterruptedException e) { + try { + Thread.sleep(200L); + } catch (InterruptedException ignored) { + Thread.currentThread().interrupt(); + } + } finally { + workerStopped.countDown(); + } + }); + Thread masterThread = new Thread(() -> { + masterStarted.countDown(); + try { + workerStopped.await(); + } catch (InterruptedException e) { + masterInterruptedBeforeWorkerStopped.set( + workerStopped.getCount() != 0L); + Thread.currentThread().interrupt(); + } + }); + workerThread.start(); + masterThread.start(); + Assert.assertTrue(workerStarted.await(1, TimeUnit.SECONDS)); + Assert.assertTrue(masterStarted.await(1, TimeUnit.SECONDS)); + + closeServicesAndJoin(lifecycle, Arrays.asList(workerThread), + masterThread); + + Assert.assertFalse(masterInterruptedBeforeWorkerStopped.get()); + Assert.assertFalse(workerThread.isAlive()); + Assert.assertFalse(masterThread.isAlive()); + } + @Test public void testOneWorker() { ServiceLifecycle lifecycle = new ServiceLifecycle(); @@ -235,8 +299,8 @@ public void testOneWorker() { try { waitForServices(Arrays.asList(workerFuture, masterFuture)); } finally { - closeServicesAndJoin(lifecycle, - Arrays.asList(masterThread, workerThread)); + closeServicesAndJoin(lifecycle, Arrays.asList(workerThread), + masterThread); } } @@ -332,9 +396,9 @@ public void testMultiWorkers() throws IOException { try { waitForServices(futures); } finally { - List threads = new ArrayList<>(workers.keySet()); - threads.add(masterThread); - closeServicesAndJoin(lifecycle, threads); + closeServicesAndJoin(lifecycle, + new ArrayList<>(workers.keySet()), + masterThread); } } @@ -420,8 +484,8 @@ public void testOneWorkerWithBusyClient() { try { waitForServices(Arrays.asList(workerFuture, masterFuture)); } finally { - closeServicesAndJoin(lifecycle, - Arrays.asList(masterThread, workerThread)); + closeServicesAndJoin(lifecycle, Arrays.asList(workerThread), + masterThread); } } @@ -454,16 +518,31 @@ private MasterService initMaster(String[] args) { Config config = ComputerContextUtil.initContext( ComputerContextUtil.convertToMap(args)); MasterService service = new MasterService(); - service.init(config); - return service; + return initializeService(service, s -> s.init(config), + SenderIntegrateTest::closeMaster); } private WorkerService initWorker(String[] args) { Config config = ComputerContextUtil.initContext( ComputerContextUtil.convertToMap(args)); WorkerService service = new WorkerService(); - service.init(config); - return service; + return initializeService(service, s -> s.init(config), + SenderIntegrateTest::closeWorker); + } + + private static T initializeService(T service, Consumer initializer, + Consumer closer) { + try { + initializer.accept(service); + return service; + } catch (RuntimeException | Error e) { + try { + closer.accept(service); + } catch (RuntimeException | Error closeFailure) { + e.addSuppressed(closeFailure); + } + throw e; + } } private static void waitForServices(List> futures) { @@ -499,27 +578,63 @@ private static void waitForServices(List> futures) { } private static void closeServicesAndJoin(ServiceLifecycle lifecycle, - List threads) { + List workerThreads, + Thread masterThread) { Throwable closeFailure = lifecycle.closeAll(); + Throwable workerFailure = interruptAndJoinThreads(workerThreads); + Throwable masterFailure = null; + if (masterThread != null) { + masterFailure = interruptAndJoinThreads( + Arrays.asList(masterThread)); + } + if (closeFailure != null) { + addFailure(closeFailure, workerFailure); + addFailure(closeFailure, masterFailure); + throw new ComputerException("Failed to close service", closeFailure); + } + if (workerFailure != null) { + addFailure(workerFailure, masterFailure); + throw new ComputerException("Failed to close worker service thread", + workerFailure); + } + if (masterFailure != null) { + throw new ComputerException("Failed to close master service thread", + masterFailure); + } + } + + private static Throwable interruptAndJoinThreads(List threads) { for (Thread thread : threads) { thread.interrupt(); } + Throwable failure = null; for (Thread thread : threads) { try { thread.join(SERVICE_WAIT_TIMEOUT); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - throw new ComputerException("Interrupted when waiting for " + - "service thread to stop", e); + failure = addFailure(failure, new ComputerException( + "Interrupted when waiting for service " + + "thread to stop", e)); } if (thread.isAlive()) { - throw new ComputerException("Timed out to wait for service " + - "thread to stop"); + failure = addFailure(failure, new ComputerException( + "Timed out to wait for service thread " + + "to stop")); } } - if (closeFailure != null) { - throw new ComputerException("Failed to close service", closeFailure); + return failure; + } + + private static Throwable addFailure(Throwable failure, Throwable cause) { + if (cause == null) { + return failure; + } + if (failure == null) { + return cause; } + failure.addSuppressed(cause); + return failure; } private static void closeWorker(WorkerService service) { From ff765122cabcc3c6b2118ee4546016b43486b396 Mon Sep 17 00:00:00 2001 From: Loki Date: Mon, 27 Jul 2026 09:28:55 +0800 Subject: [PATCH 06/12] delete irrelavant test --- .../2798d820-e45e-4b0a-9440-5b9a3035333b | 1 - .../9eee6074-26ca-4a24-bb6e-4cf9e2a93220 | 1 - .../value_file_3 | Bin 32 -> 0 bytes .../hgkv_1.hgkv | Bin 385101 -> 0 bytes .../edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 | Bin 112279 -> 0 bytes .../hgkv_1.hgkv | Bin 6651 -> 0 bytes .../hgkv_1.hgkv | Bin 1356 -> 0 bytes .../hgkv_1.hgkv | Bin 510526 -> 0 bytes .../hgkv_1.hgkv | Bin 1356 -> 0 bytes .../e35b2a4a-1fe3-4583-a44e-0102ad0c780f | Bin 1336 -> 0 bytes .../f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b | 1 - .../computer-test/hgkv/hgkv_1.hgkv/hgkv_1.hgkv | Bin 88 -> 0 bytes 12 files changed, 3 deletions(-) delete mode 100644 computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b delete mode 100644 computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 delete mode 100644 computer/computer-test/b0b0da9a-f337-43af-8750-49c838504f1c/value_file_3 delete mode 100644 computer/computer-test/data_dir1/local_001/edge/-1/a27aa466-b5ee-48c9-91ef-7b6ea2fc70dc/hgkv_1.hgkv delete mode 100644 computer/computer-test/data_dir1/local_001/edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 delete mode 100644 computer/computer-test/data_dir1/local_001/msg/0/eb8a977f-3da7-49fe-9b71-f7d569ebc5cf/hgkv_1.hgkv delete mode 100644 computer/computer-test/data_dir1/local_001/vertex/-1/a03d03d8-7a76-4d9c-80ca-939649f04492/hgkv_1.hgkv delete mode 100644 computer/computer-test/data_dir2/local_001/edge/-1/71126e9c-c8fe-495c-bfa2-7d4d7f6f70c8/hgkv_1.hgkv delete mode 100644 computer/computer-test/data_dir2/local_001/vertex/-1/313192a6-de7b-46e4-9525-ccd7907c07db/hgkv_1.hgkv delete mode 100644 computer/computer-test/data_dir2/local_001/vertex/e35b2a4a-1fe3-4583-a44e-0102ad0c780f delete mode 100644 computer/computer-test/f3102b70-fd9e-4c16-be6f-7ebcc04c9c0b delete mode 100644 computer/computer-test/hgkv/hgkv_1.hgkv/hgkv_1.hgkv diff --git a/computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b b/computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b deleted file mode 100644 index 0aa6fb546..000000000 --- a/computer/computer-test/2798d820-e45e-4b0a-9440-5b9a3035333b +++ /dev/null @@ -1 +0,0 @@ -test data \ No newline at end of file diff --git a/computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 b/computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 deleted file mode 100644 index 0aa6fb546..000000000 --- a/computer/computer-test/9eee6074-26ca-4a24-bb6e-4cf9e2a93220 +++ /dev/null @@ -1 +0,0 @@ -test data \ No newline at end of file diff --git a/computer/computer-test/b0b0da9a-f337-43af-8750-49c838504f1c/value_file_3 b/computer/computer-test/b0b0da9a-f337-43af-8750-49c838504f1c/value_file_3 deleted file mode 100644 index 2fa63a9853c4f880f84e02ca14594d09ff6103e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32 ccmb1OU|^60Vksb&24Wc?mIY!tAeIMW01of~-2eap diff --git a/computer/computer-test/data_dir1/local_001/edge/-1/a27aa466-b5ee-48c9-91ef-7b6ea2fc70dc/hgkv_1.hgkv b/computer/computer-test/data_dir1/local_001/edge/-1/a27aa466-b5ee-48c9-91ef-7b6ea2fc70dc/hgkv_1.hgkv deleted file mode 100644 index a7702ab97f25a013d92b08e9375c97096d0ba2b3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 385101 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­oQ+o+64kjs#(kn50}kXuP>hsJMdlHpEos;%xr9zq^N zoL9l|$h8h~uY+9dphB~Am1D|X4(h3G<8sG{ z+a2V32f5!tE_jd|9^{G#6*`_v9aC;~P<+qm#C;>HKL@5Cgy8JQa_6PO+{l|CoztWF? zb{&M=2ch=NOE*HMTnQm}Ldc~M>TUeI?ydfCP&gyXVnk7lD2WjTF`^ts6vK#87*PoK zmUmDl^G1=3D1i|LFrxfL6u*el7g6{k%3eg#+pvR@m^TVyM7fJ7b`hm6qR>T@xribc zQQ{&B+=d;Lzr0cWB1&6CVT&kh5k)Pcq(v08h;kND%r@+x)a8vr7g5F{idaMmizr|b zmeHp)mHZ*4b$fXZ*>w{eTphE9+(PPR@52|nD>c@z?ALQ}}x&1+|e~|kh z2TkV_#{XoY=^U)+7wpBKt&MDdI$oe_mIqHIPK&4`j2Q7|LQ zC?m>bM3Iarkr4$lqC7?v$B5FnVF!gXZ{jj&?3rNL@|pfWgB)-=<-IHi?qF# zO+*QcC}0ugE24Nsl&*-v6;ZY}?9dxOUtdUn$Uw+o$WX{|$VkX&$e5&@t>c=g{(P7S znGBf`5rPaDethLiE4+%kfo62kd=_tkhPHYkd2T{NqL7YO;kHcRk2u4=S`h z*E^=%@1XiNE_{r*@j a%YXg9|Ms_E{_Fov{`>!8`hWab_5TA~_=ZgY diff --git a/computer/computer-test/data_dir1/local_001/edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 b/computer/computer-test/data_dir1/local_001/edge/c8891a4c-eb1f-4c80-9df6-8a435cd86328 deleted file mode 100644 index 132932123169c1111daaa3e73f5ccf4cec641c8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 112279 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 diff --git a/computer/computer-test/data_dir1/local_001/msg/0/eb8a977f-3da7-49fe-9b71-f7d569ebc5cf/hgkv_1.hgkv b/computer/computer-test/data_dir1/local_001/msg/0/eb8a977f-3da7-49fe-9b71-f7d569ebc5cf/hgkv_1.hgkv deleted file mode 100644 index 181b83ef21a7143b7cfd322be6f1262dfab5232b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6651 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