From f3d128bc2d63bc15c6b5af2b1774e65cdff47e82 Mon Sep 17 00:00:00 2001 From: Eric Kerwin Date: Tue, 25 May 2021 11:10:35 -0400 Subject: [PATCH] reworking wait job --- build.gradle | 2 +- .../IntegrationTimeoutException.java | 30 ++++++++ .../wait/BooleanWaitJobCompleter.java | 24 ++++++ .../synopsys/integration/wait/WaitJob.java | 76 +++++++++---------- .../integration/wait/WaitJobCompleter.java | 18 +++++ ...WaitJobTask.java => WaitJobCondition.java} | 3 +- .../integration/wait/WaitJobConfig.java | 53 ++++++------- .../integration/wait/WaitJobTest.java | 59 +++++++++----- 8 files changed, 175 insertions(+), 90 deletions(-) create mode 100644 src/main/java/com/synopsys/integration/exception/IntegrationTimeoutException.java create mode 100644 src/main/java/com/synopsys/integration/wait/BooleanWaitJobCompleter.java create mode 100644 src/main/java/com/synopsys/integration/wait/WaitJobCompleter.java rename src/main/java/com/synopsys/integration/wait/{WaitJobTask.java => WaitJobCondition.java} (86%) diff --git a/build.gradle b/build.gradle index 015eeb5..e554693 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { project.ext.moduleName = 'com.synopsys.integration.integration-common' project.ext.javaUseAutoModuleName = 'true' -version = '24.3.1-SNAPSHOT' +version = '25.0.0-SNAPSHOT' description = 'The base library for all other integration libraries to encompass and export common dependencies and code.' apply plugin: 'com.synopsys.integration.library' diff --git a/src/main/java/com/synopsys/integration/exception/IntegrationTimeoutException.java b/src/main/java/com/synopsys/integration/exception/IntegrationTimeoutException.java new file mode 100644 index 0000000..05ebeb0 --- /dev/null +++ b/src/main/java/com/synopsys/integration/exception/IntegrationTimeoutException.java @@ -0,0 +1,30 @@ +/* + * integration-common + * + * Copyright (c) 2021 Synopsys, Inc. + * + * Use subject to the terms and conditions of the Synopsys End User Software License and Maintenance Agreement. All rights reserved worldwide. + */ +package com.synopsys.integration.exception; + +public class IntegrationTimeoutException extends IntegrationException { + public IntegrationTimeoutException() { + } + + public IntegrationTimeoutException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public IntegrationTimeoutException(String message, Throwable cause) { + super(message, cause); + } + + public IntegrationTimeoutException(String message) { + super(message); + } + + public IntegrationTimeoutException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/com/synopsys/integration/wait/BooleanWaitJobCompleter.java b/src/main/java/com/synopsys/integration/wait/BooleanWaitJobCompleter.java new file mode 100644 index 0000000..9230c36 --- /dev/null +++ b/src/main/java/com/synopsys/integration/wait/BooleanWaitJobCompleter.java @@ -0,0 +1,24 @@ +/* + * integration-common + * + * Copyright (c) 2021 Synopsys, Inc. + * + * Use subject to the terms and conditions of the Synopsys End User Software License and Maintenance Agreement. All rights reserved worldwide. + */ +package com.synopsys.integration.wait; + +import com.synopsys.integration.exception.IntegrationException; +import com.synopsys.integration.exception.IntegrationTimeoutException; + +public class BooleanWaitJobCompleter implements WaitJobCompleter { + @Override + public Boolean complete() throws IntegrationException { + return true; + } + + @Override + public Boolean handleTimeout() throws IntegrationTimeoutException { + return false; + } + +} diff --git a/src/main/java/com/synopsys/integration/wait/WaitJob.java b/src/main/java/com/synopsys/integration/wait/WaitJob.java index 3349693..c7ad232 100644 --- a/src/main/java/com/synopsys/integration/wait/WaitJob.java +++ b/src/main/java/com/synopsys/integration/wait/WaitJob.java @@ -7,68 +7,66 @@ */ package com.synopsys.integration.wait; -import com.synopsys.integration.exception.IntegrationException; -import com.synopsys.integration.log.IntLogger; -import org.apache.commons.lang3.time.DurationFormatUtils; - import java.time.Duration; -import java.util.function.Supplier; - -public class WaitJob { - private WaitJobConfig waitJobConfig; - public static WaitJob create(IntLogger intLogger, long timeoutInSeconds, long startTime, int waitIntervalInSeconds, WaitJobTask waitJobTask) { - return new WaitJob(new WaitJobConfig(intLogger, timeoutInSeconds, startTime, waitIntervalInSeconds, waitJobTask)); - } - - public static WaitJob create(IntLogger intLogger, long timeoutInSeconds, Supplier startTimeSupplier, int waitIntervalInSeconds, WaitJobTask waitJobTask) { - return new WaitJob(new WaitJobConfig(intLogger, timeoutInSeconds, startTimeSupplier, waitIntervalInSeconds, waitJobTask)); - } +import org.apache.commons.lang3.time.DurationFormatUtils; - public static WaitJob createUsingSystemTimeWhenInvoked(IntLogger intLogger, long timeoutInSeconds, int waitIntervalInSeconds, WaitJobTask waitJobTask) { - return new WaitJob(new WaitJobConfig(intLogger, timeoutInSeconds, WaitJobConfig.CURRENT_TIME_SUPPLIER, waitIntervalInSeconds, waitJobTask)); - } +import com.synopsys.integration.exception.IntegrationException; +import com.synopsys.integration.log.IntLogger; - public static WaitJob create(IntLogger intLogger, long timeoutInSeconds, long startTime, int waitIntervalInSeconds, String taskName, WaitJobTask waitJobTask) { - return new WaitJob(new WaitJobConfig(intLogger, timeoutInSeconds, startTime, waitIntervalInSeconds, taskName, waitJobTask)); - } +public class WaitJob { + public static final BooleanWaitJobCompleter BOOLEAN_COMPLETER = new BooleanWaitJobCompleter(); - public static WaitJob create(IntLogger intLogger, long timeoutInSeconds, Supplier startTimeSupplier, int waitIntervalInSeconds, String taskName, WaitJobTask waitJobTask) { - return new WaitJob(new WaitJobConfig(intLogger, timeoutInSeconds, startTimeSupplier, waitIntervalInSeconds, taskName, waitJobTask)); + public static final WaitJob createSimpleWait(WaitJobConfig waitJobConfig, WaitJobCondition waitJobCondition) { + return new WaitJob<>(waitJobConfig, waitJobCondition, BOOLEAN_COMPLETER); } - public static WaitJob createUsingSystemTimeWhenInvoked(IntLogger intLogger, long timeoutInSeconds, int waitIntervalInSeconds, String taskName, WaitJobTask waitJobTask) { - return new WaitJob(new WaitJobConfig(intLogger, timeoutInSeconds, WaitJobConfig.CURRENT_TIME_SUPPLIER, waitIntervalInSeconds, taskName, waitJobTask)); - } + private final WaitJobConfig waitJobConfig; + private final WaitJobCondition waitJobCondition; + private final WaitJobCompleter waitJobCompleter; - public WaitJob(WaitJobConfig waitJobConfig) { + public WaitJob(WaitJobConfig waitJobConfig, WaitJobCondition waitJobCondition, WaitJobCompleter waitJobCompleter) { this.waitJobConfig = waitJobConfig; + this.waitJobCondition = waitJobCondition; + this.waitJobCompleter = waitJobCompleter; } - public boolean waitFor() throws InterruptedException, IntegrationException { + public T waitFor() throws InterruptedException, IntegrationException { int attempts = 0; + IntLogger intLogger = waitJobConfig.getIntLogger(); long startTime = waitJobConfig.getStartTime(); Duration currentDuration = Duration.ZERO; Duration maximumDuration = Duration.ofMillis(waitJobConfig.getTimeoutInSeconds() * 1000); - IntLogger intLogger = waitJobConfig.getIntLogger(); + String taskDescription = waitJobConfig.getTaskDescription(); + + boolean allCompleted = waitJobCondition.isComplete(); + if (allCompleted) { + String attemptPrefix = createAttemptPrefix(attempts, currentDuration, taskDescription); + return complete(intLogger, attemptPrefix); + } - String taskDescription = waitJobConfig - .getTaskName() - .map(s -> String.format("for task %s ", s)) - .orElse(""); while (currentDuration.compareTo(maximumDuration) <= 0) { - String attemptMessagePrefix = String.format("Try #%s %s(elapsed: %s)...", ++attempts, taskDescription, DurationFormatUtils.formatDurationHMS(currentDuration.toMillis())); - if (waitJobConfig.getWaitJobTask().isComplete()) { - intLogger.info(String.format("%scomplete!", attemptMessagePrefix)); - return true; + attempts++; + String attemptPrefix = createAttemptPrefix(attempts, currentDuration, taskDescription); + if (waitJobCondition.isComplete()) { + return complete(intLogger, attemptPrefix); } else { - intLogger.info(String.format("%snot done yet, waiting %s seconds and trying again...", attemptMessagePrefix, waitJobConfig.getWaitIntervalInSeconds())); + intLogger.info(String.format("%snot done yet, waiting %s seconds and trying again...", attemptPrefix, waitJobConfig.getWaitIntervalInSeconds())); Thread.sleep(waitJobConfig.getWaitIntervalInSeconds() * 1000); currentDuration = Duration.ofMillis(System.currentTimeMillis() - startTime); } } - return false; + return waitJobCompleter.handleTimeout(); + } + + private T complete(IntLogger intLogger, String attemptPrefix) throws IntegrationException { + intLogger.info(String.format("%scomplete!", attemptPrefix)); + return waitJobCompleter.complete(); + } + + private String createAttemptPrefix(int attempts, Duration currentDuration, String taskDescription) { + return String.format("Try #%s %s(elapsed: %s)...", attempts, taskDescription, DurationFormatUtils.formatDurationHMS(currentDuration.toMillis())); } } diff --git a/src/main/java/com/synopsys/integration/wait/WaitJobCompleter.java b/src/main/java/com/synopsys/integration/wait/WaitJobCompleter.java new file mode 100644 index 0000000..b705caa --- /dev/null +++ b/src/main/java/com/synopsys/integration/wait/WaitJobCompleter.java @@ -0,0 +1,18 @@ +/* + * integration-common + * + * Copyright (c) 2021 Synopsys, Inc. + * + * Use subject to the terms and conditions of the Synopsys End User Software License and Maintenance Agreement. All rights reserved worldwide. + */ +package com.synopsys.integration.wait; + +import com.synopsys.integration.exception.IntegrationException; +import com.synopsys.integration.exception.IntegrationTimeoutException; + +public interface WaitJobCompleter { + T complete() throws IntegrationException; + + T handleTimeout() throws IntegrationTimeoutException; + +} diff --git a/src/main/java/com/synopsys/integration/wait/WaitJobTask.java b/src/main/java/com/synopsys/integration/wait/WaitJobCondition.java similarity index 86% rename from src/main/java/com/synopsys/integration/wait/WaitJobTask.java rename to src/main/java/com/synopsys/integration/wait/WaitJobCondition.java index 04c000d..6fb0807 100644 --- a/src/main/java/com/synopsys/integration/wait/WaitJobTask.java +++ b/src/main/java/com/synopsys/integration/wait/WaitJobCondition.java @@ -9,7 +9,8 @@ import com.synopsys.integration.exception.IntegrationException; -public interface WaitJobTask { +@FunctionalInterface +public interface WaitJobCondition { boolean isComplete() throws IntegrationException; } diff --git a/src/main/java/com/synopsys/integration/wait/WaitJobConfig.java b/src/main/java/com/synopsys/integration/wait/WaitJobConfig.java index 751df7f..0c1536d 100644 --- a/src/main/java/com/synopsys/integration/wait/WaitJobConfig.java +++ b/src/main/java/com/synopsys/integration/wait/WaitJobConfig.java @@ -7,68 +7,59 @@ */ package com.synopsys.integration.wait; -import com.synopsys.integration.log.IntLogger; - -import java.util.Optional; import java.util.function.Supplier; +import com.synopsys.integration.log.IntLogger; + public class WaitJobConfig { public static final Supplier CURRENT_TIME_SUPPLIER = System::currentTimeMillis; private final IntLogger intLogger; + private final String taskName; private final long timeoutInSeconds; private final Supplier startTimeSupplier; private final int waitIntervalInSeconds; - private final String taskName; - private final WaitJobTask waitJobTask; - public WaitJobConfig(IntLogger intLogger, long timeoutInSeconds, long startTime, int waitIntervalInSeconds, WaitJobTask waitJobTask) { - this(intLogger, timeoutInSeconds, () -> startTime, waitIntervalInSeconds, null, waitJobTask); + public WaitJobConfig(IntLogger intLogger, String taskName, long timeoutInSeconds, long startTime, int waitIntervalInSeconds) { + this(intLogger, taskName, timeoutInSeconds, () -> startTime, waitIntervalInSeconds); } - public WaitJobConfig(IntLogger intLogger, long timeoutInSeconds, Supplier startTimeSupplier, int waitIntervalInSeconds, WaitJobTask waitJobTask) { - this(intLogger, timeoutInSeconds, startTimeSupplier, waitIntervalInSeconds, null, waitJobTask); - } - - public WaitJobConfig(IntLogger intLogger, long timeoutInSeconds, long startTime, int waitIntervalInSeconds, String taskName, WaitJobTask waitJobTask) { - this(intLogger, timeoutInSeconds, () -> startTime, waitIntervalInSeconds, taskName, waitJobTask); - } - - public WaitJobConfig(IntLogger intLogger, long timeoutInSeconds, Supplier startTimeSupplier, int waitIntervalInSeconds, String taskName, WaitJobTask waitJobTask) { + public WaitJobConfig(IntLogger intLogger, String taskName, long timeoutInSeconds, Supplier startTimeSupplier, int waitIntervalInSeconds) { this.intLogger = intLogger; + this.taskName = taskName; this.timeoutInSeconds = timeoutInSeconds; this.startTimeSupplier = startTimeSupplier; - this.waitIntervalInSeconds = waitIntervalInSeconds; - this.taskName = taskName; - this.waitJobTask = waitJobTask; + + // waitInterval needs to be less than the timeout + if (waitIntervalInSeconds > timeoutInSeconds) { + this.waitIntervalInSeconds = (int) timeoutInSeconds; + } else { + this.waitIntervalInSeconds = waitIntervalInSeconds; + } } - public long getStartTime() { - return startTimeSupplier.get(); + public IntLogger getIntLogger() { + return intLogger; } - public Optional getTaskName() { - return Optional.ofNullable(taskName); + public String getTaskName() { + return taskName; } - public IntLogger getIntLogger() { - return intLogger; + public String getTaskDescription() { + return String.format("for task %s ", taskName); } public long getTimeoutInSeconds() { return timeoutInSeconds; } - public Supplier getStartTimeSupplier() { - return startTimeSupplier; + public long getStartTime() { + return startTimeSupplier.get(); } public int getWaitIntervalInSeconds() { return waitIntervalInSeconds; } - public WaitJobTask getWaitJobTask() { - return waitJobTask; - } - } diff --git a/src/test/java/com/synopsys/integration/wait/WaitJobTest.java b/src/test/java/com/synopsys/integration/wait/WaitJobTest.java index 0be0282..d4f9a9d 100644 --- a/src/test/java/com/synopsys/integration/wait/WaitJobTest.java +++ b/src/test/java/com/synopsys/integration/wait/WaitJobTest.java @@ -1,43 +1,66 @@ package com.synopsys.integration.wait; +import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + import com.synopsys.integration.exception.IntegrationException; import com.synopsys.integration.log.BufferedIntLogger; import com.synopsys.integration.log.LogLevel; + import org.junit.Assert; import org.junit.jupiter.api.Test; public class WaitJobTest { + private final BufferedIntLogger testingLogger = new BufferedIntLogger(); + private final WaitJobConfig waitJobConfig = new WaitJobConfig(testingLogger, "holypants", 5, WaitJobConfig.CURRENT_TIME_SUPPLIER, 1); + @Test - public void testTaskNameLogged() throws IntegrationException, InterruptedException { - BufferedIntLogger testingLogger = new BufferedIntLogger(); + public void testTaskCompletesImmediately() throws IntegrationException, InterruptedException { + WaitJobCondition waitJobCondition = () -> true; + WaitJob waitJob = new WaitJob(waitJobConfig, waitJobCondition, WaitJob.BOOLEAN_COMPLETER); + boolean completed = waitJob.waitFor(); - WaitJob waitJob = WaitJob.createUsingSystemTimeWhenInvoked(testingLogger, 5, 1, "holypants", createTask()); - waitJob.waitFor(); + assertTrue(completed); String output = testingLogger.getOutputString(LogLevel.INFO); - Assert.assertTrue(output.contains("holypants")); + assertTrue(output.contains("holypants")); + assertTrue(output.contains("complete!")); + assertFalse(output.contains("not done yet")); } @Test - public void testTaskNameNotLogged() throws IntegrationException, InterruptedException { - BufferedIntLogger testingLogger = new BufferedIntLogger(); + public void testTaskCompletesEventually() throws IntegrationException, InterruptedException { + WaitJobCondition waitJobCondition = new WaitJobCondition() { + private int count = 0; + + @Override + public boolean isComplete() { + return ++count > 2; + } + }; + WaitJob waitJob = new WaitJob(waitJobConfig, waitJobCondition, WaitJob.BOOLEAN_COMPLETER); + boolean completed = waitJob.waitFor(); - WaitJob waitJob = WaitJob.createUsingSystemTimeWhenInvoked(testingLogger, 5, 1, createTask()); - waitJob.waitFor(); + assertTrue(completed); String output = testingLogger.getOutputString(LogLevel.INFO); - Assert.assertFalse(output.contains("holypants")); + assertTrue(output.contains("holypants")); + assertTrue(output.contains("complete!")); + assertTrue(output.contains("not done yet")); } - private WaitJobTask createTask() { - return new WaitJobTask() { - private int count = 0; + @Test + public void testTaskCompletesNever() throws IntegrationException, InterruptedException { + WaitJobCondition waitJobCondition = () -> false; + WaitJob waitJob = new WaitJob(waitJobConfig, waitJobCondition, WaitJob.BOOLEAN_COMPLETER); + boolean completed = waitJob.waitFor(); - @Override - public boolean isComplete() throws IntegrationException { - return ++count > 1; - } - }; + assertFalse(completed); + + String output = testingLogger.getOutputString(LogLevel.INFO); + assertTrue(output.contains("holypants")); + assertFalse(output.contains("complete!")); + assertTrue(output.contains("not done yet")); } }