Skip to content
This repository has been archived by the owner on May 26, 2020. It is now read-only.

Do not exit client until the command has either completed or failed #12

Merged
merged 1 commit into from
Oct 14, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
<cpp.repo.name>framework-jmx-command-client</cpp.repo.name>

<framework-api.version>4.1.0</framework-api.version>
<framework.version>6.1.1</framework.version>
<framework.version>6.2.0-M5</framework.version>
<utilities.version>1.20.1</utilities.version>
<maven-common-bom.version>2.4.0</maven-common-bom.version>
</properties>

Expand Down Expand Up @@ -72,6 +73,11 @@
<groupId>org.wildfly</groupId>
<artifactId>wildfly-client-all</artifactId>
</dependency>
<dependency>
<groupId>uk.gov.justice.utils</groupId>
<artifactId>utilities-core</artifactId>
<version>${utilities.version}</version>
</dependency>


<!-- Test Dependencies -->
Expand Down
2 changes: 1 addition & 1 deletion runSystemCommand.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#
################################################

FRAMEWORK_JMX_COMMAND_CLIENT_VERSION=2.1.0-SNAPSHOT
FRAMEWORK_JMX_COMMAND_CLIENT_VERSION=2.2.0-SNAPSHOT
CONTEXT_NAME="people"
USER_NAME="admin"
PASSWORD="admin"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package uk.gov.justice.framework.command.client.jmx;

import static java.lang.String.format;
import static java.time.Duration.between;
import static org.apache.commons.lang3.time.DurationFormatUtils.formatDurationHMS;
import static uk.gov.justice.services.jmx.api.domain.CommandState.COMMAND_COMPLETE;
import static uk.gov.justice.services.jmx.api.domain.CommandState.COMMAND_FAILED;

import uk.gov.justice.framework.command.client.io.ToConsolePrinter;
import uk.gov.justice.services.common.util.UtcClock;
import uk.gov.justice.services.jmx.api.domain.CommandState;
import uk.gov.justice.services.jmx.api.domain.SystemCommandStatus;
import uk.gov.justice.services.jmx.api.mbean.SystemCommanderMBean;

import java.time.ZonedDateTime;
import java.util.UUID;

import javax.inject.Inject;

public class CommandChecker {

@Inject
private ToConsolePrinter toConsolePrinter;

@Inject
private UtcClock clock;

public boolean commandComplete(final SystemCommanderMBean systemCommanderMBean, final UUID commandId, final ZonedDateTime startTime) {

final SystemCommandStatus commandStatus = systemCommanderMBean.getCommandStatus(commandId);


final CommandState commandState = commandStatus.getCommandState();
if (commandState == COMMAND_COMPLETE ) {

final ZonedDateTime endTime = clock.now();
final long durationMillis = between(startTime, endTime).toMillis();

final String duration = formatDurationHMS(durationMillis);
toConsolePrinter.println(format("Command %s complete", commandStatus.getSystemCommandName()));
toConsolePrinter.println(format("%s duration %s (hours:minutes:seconds:milliseconds)", commandStatus.getSystemCommandName(), duration));
return true;
}

if(commandState == COMMAND_FAILED) {
final long durationMillis = between(startTime, clock.now()).toMillis();

final String duration = formatDurationHMS(durationMillis);
toConsolePrinter.println(format("ERROR: Command %s failed", commandStatus.getSystemCommandName()));
toConsolePrinter.println(format("ERROR: %s", commandStatus.getMessage()));
toConsolePrinter.println(format("%s duration %s (hours:minutes:seconds:milliseconds)", commandStatus.getSystemCommandName(), duration));
return true;
}

return false;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package uk.gov.justice.framework.command.client.jmx;

import static java.lang.String.format;
import static java.time.Duration.between;

import uk.gov.justice.framework.command.client.io.ToConsolePrinter;
import uk.gov.justice.services.common.util.Sleeper;
import uk.gov.justice.services.common.util.UtcClock;
import uk.gov.justice.services.jmx.api.command.SystemCommand;
import uk.gov.justice.services.jmx.api.mbean.SystemCommanderMBean;

import java.time.ZonedDateTime;
import java.util.UUID;

import javax.inject.Inject;

public class CommandPoller {

@Inject
private CommandChecker commandChecker;

@Inject
private UtcClock clock;

@Inject
private Sleeper sleeper;

@Inject
private ToConsolePrinter toConsolePrinter;

public void runUntilComplete(final SystemCommanderMBean systemCommanderMBean, final UUID commandId, final SystemCommand systemCommand) {

final ZonedDateTime startTime = clock.now();

int count = 0;
while (! commandChecker.commandComplete(systemCommanderMBean, commandId, startTime)) {
sleeper.sleepFor(1_000);
count++;

if (count % 10 == 0) {
final long seconds = between(startTime, clock.now()).getSeconds();
toConsolePrinter.println(format("%s running for %d seconds", systemCommand.getName(), seconds));
}
}
}

}
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package uk.gov.justice.framework.command.client.jmx;

import static uk.gov.justice.services.jmx.api.domain.CommandState.COMMAND_COMPLETE;
import static uk.gov.justice.services.jmx.api.domain.CommandState.COMMAND_FAILED;

import uk.gov.justice.framework.command.client.io.ToConsolePrinter;
import uk.gov.justice.services.jmx.api.SystemCommandFailedException;
import uk.gov.justice.services.jmx.api.UnsupportedSystemCommandException;
import uk.gov.justice.services.jmx.api.command.SystemCommand;
import uk.gov.justice.services.jmx.api.domain.CommandState;
import uk.gov.justice.services.jmx.api.domain.SystemCommandStatus;
import uk.gov.justice.services.jmx.api.mbean.SystemCommanderMBean;
import uk.gov.justice.services.jmx.system.command.client.SystemCommanderClient;
import uk.gov.justice.services.jmx.system.command.client.SystemCommanderClientFactory;
import uk.gov.justice.services.jmx.system.command.client.connection.JmxParameters;

import java.util.UUID;

import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;

Expand All @@ -18,6 +25,9 @@ public class SystemCommandInvoker {
@Inject
private SystemCommanderClientFactory systemCommanderClientFactory;

@Inject
private CommandPoller commandPoller;

@Inject
private ToConsolePrinter toConsolePrinter;

Expand All @@ -32,13 +42,13 @@ public void runSystemCommand(final SystemCommand systemCommand, final JmxParamet
jmxParameters.getCredentials().ifPresent(credentials -> toConsolePrinter.printf("Connecting with credentials for user '%s'", credentials.getUsername()));

try (final SystemCommanderClient systemCommanderClient = systemCommanderClientFactory.create(jmxParameters)) {
final SystemCommanderMBean systemCommanderMBean = systemCommanderClient.getRemote(contextName);

toConsolePrinter.printf("Connected to %s context", contextName);

systemCommanderMBean.call(systemCommand);

toConsolePrinter.printf("System command '%s' successfully sent to %s", commandName, contextName);
final SystemCommanderMBean systemCommanderMBean = systemCommanderClient.getRemote(contextName);
final UUID commandId = systemCommanderMBean.call(systemCommand);
toConsolePrinter.printf("System command '%s' with id '%s' successfully sent to %s", commandName, commandId, contextName);
commandPoller.runUntilComplete(systemCommanderMBean, commandId, systemCommand);

} catch (final UnsupportedSystemCommandException e) {
toConsolePrinter.printf("The command '%s' is not supported on this %s context", commandName, contextName);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package uk.gov.justice.framework.command.client.jmx;

import static java.util.UUID.randomUUID;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static uk.gov.justice.services.jmx.api.domain.CommandState.COMMAND_COMPLETE;
import static uk.gov.justice.services.jmx.api.domain.CommandState.COMMAND_FAILED;
import static uk.gov.justice.services.jmx.api.domain.CommandState.COMMAND_IN_PROGRESS;

import uk.gov.justice.framework.command.client.io.ToConsolePrinter;
import uk.gov.justice.services.common.util.UtcClock;
import uk.gov.justice.services.jmx.api.domain.SystemCommandStatus;
import uk.gov.justice.services.jmx.api.mbean.SystemCommanderMBean;

import java.time.ZonedDateTime;
import java.util.UUID;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class CommandCheckerTest {

@Mock
private ToConsolePrinter toConsolePrinter;

@Mock
private UtcClock clock;

@InjectMocks
private CommandChecker commandChecker;

@Test
public void shouldLogAndReturnTrueIfTheCommandIsComplete() throws Exception {

final UUID commandId = randomUUID();

final ZonedDateTime startTime = new UtcClock().now();
final ZonedDateTime endedAt = startTime.plusMinutes(83);

final SystemCommanderMBean systemCommanderMBean = mock(SystemCommanderMBean.class);
final SystemCommandStatus systemCommandStatus = mock(SystemCommandStatus.class);

when(clock.now()).thenReturn(endedAt);
when(systemCommanderMBean.getCommandStatus(commandId)).thenReturn(systemCommandStatus);
when(systemCommandStatus.getCommandState()).thenReturn(COMMAND_COMPLETE);
when(systemCommandStatus.getSystemCommandName()).thenReturn("CATCHUP");

assertThat(commandChecker.commandComplete(systemCommanderMBean, commandId, startTime), is(true));

verify(toConsolePrinter).println("Command CATCHUP complete");
verify(toConsolePrinter).println("CATCHUP duration 01:23:00.000 (hours:minutes:seconds:milliseconds)");
}

@Test
public void shouldLogAndReturnTrueIfTheCommandFails() throws Exception {

final UUID commandId = randomUUID();

final String errorMessage = "CATCHUP failed with 23 errors";

final ZonedDateTime startTime = new UtcClock().now();
final ZonedDateTime endedAt = startTime.plusMinutes(83);

final SystemCommanderMBean systemCommanderMBean = mock(SystemCommanderMBean.class);
final SystemCommandStatus systemCommandStatus = mock(SystemCommandStatus.class);

when(clock.now()).thenReturn(endedAt);
when(systemCommanderMBean.getCommandStatus(commandId)).thenReturn(systemCommandStatus);
when(systemCommandStatus.getCommandState()).thenReturn(COMMAND_FAILED);
when(systemCommandStatus.getSystemCommandName()).thenReturn("CATCHUP");
when(systemCommandStatus.getMessage()).thenReturn(errorMessage);

assertThat(commandChecker.commandComplete(systemCommanderMBean, commandId, startTime), is(true));

verify(toConsolePrinter).println("ERROR: Command CATCHUP failed");
verify(toConsolePrinter).println("ERROR: CATCHUP failed with 23 errors");
verify(toConsolePrinter).println("CATCHUP duration 01:23:00.000 (hours:minutes:seconds:milliseconds)");
}

@Test
public void shouldReturnFalseIfTheCommandIsNeitherCompleteNorFailed() throws Exception {

final UUID commandId = randomUUID();

final ZonedDateTime startTime = new UtcClock().now();

final SystemCommanderMBean systemCommanderMBean = mock(SystemCommanderMBean.class);
final SystemCommandStatus systemCommandStatus = mock(SystemCommandStatus.class);

when(systemCommanderMBean.getCommandStatus(commandId)).thenReturn(systemCommandStatus);
when(systemCommandStatus.getCommandState()).thenReturn(COMMAND_IN_PROGRESS);

assertThat(commandChecker.commandComplete(systemCommanderMBean, commandId, startTime), is(false));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package uk.gov.justice.framework.command.client.jmx;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import uk.gov.justice.framework.command.client.io.ToConsolePrinter;
import uk.gov.justice.services.common.util.Sleeper;
import uk.gov.justice.services.common.util.UtcClock;
import uk.gov.justice.services.jmx.api.command.EventCatchupCommand;
import uk.gov.justice.services.jmx.api.command.SystemCommand;
import uk.gov.justice.services.jmx.api.mbean.SystemCommanderMBean;

import java.time.ZonedDateTime;
import java.util.UUID;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class CommandPollerTest {

@Mock
private CommandChecker commandChecker;

@Mock
private UtcClock clock;

@Mock
private Sleeper sleeper;

@Mock
private ToConsolePrinter toConsolePrinter;

@InjectMocks
private CommandPoller commandPoller;

@Test
public void shouldCheckCommandUntilComplete() throws Exception {

final UUID commandId = UUID.randomUUID();
final SystemCommand systemCommand = new EventCatchupCommand();

final ZonedDateTime startTime = new UtcClock().now();

final SystemCommanderMBean systemCommanderMBean = mock(SystemCommanderMBean.class);

when(clock.now()).thenReturn(startTime);
when(commandChecker.commandComplete(systemCommanderMBean, commandId, startTime)).thenReturn(false, false, true);

commandPoller.runUntilComplete(systemCommanderMBean, commandId, systemCommand);

verify(sleeper, times(2)).sleepFor(1_000);
verifyZeroInteractions(toConsolePrinter);
}

@Test
public void shouldLogProgressEveryTenthCall() throws Exception {

final UUID commandId = UUID.randomUUID();
final SystemCommand systemCommand = new EventCatchupCommand();

final ZonedDateTime startTime = new UtcClock().now();
final ZonedDateTime now = startTime.plusSeconds(10);

final SystemCommanderMBean systemCommanderMBean = mock(SystemCommanderMBean.class);

when(clock.now()).thenReturn(startTime, now);
when(commandChecker.commandComplete(systemCommanderMBean, commandId, startTime)).thenReturn(false, false, false, false, false, false, false, false, false, false, true);

commandPoller.runUntilComplete(systemCommanderMBean, commandId, systemCommand);

verify(sleeper, times(10)).sleepFor(1_000);
verify(toConsolePrinter).println("CATCHUP running for 10 seconds");
}
}
Loading