Skip to content

Commit

Permalink
[WFMP-224] Add an option to reload a server if the server-state is in…
Browse files Browse the repository at this point in the history
… reload-required. This avoids the user having to add a reload operation in CLI commands.

Signed-off-by: James R. Perkins <[email protected]>
  • Loading branch information
jamezp committed Nov 15, 2023
1 parent 1770681 commit cfe739a
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 2 deletions.
85 changes: 85 additions & 0 deletions core/src/main/java/org/wildfly/plugin/core/ServerHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

Expand Down Expand Up @@ -95,6 +97,89 @@ public static ContainerDescription getContainerDescription(final ModelController
return DefaultContainerDescription.lookup(Assert.checkNotNullParam("client", client));
}

/**
* Checks if the container status is "reload-required" and if it's the case executes reload and waits for completion.
*
* @param client the client used to execute the operation
*/
public static void reloadIfRequired(final ModelControllerClient client, final long timeout) {
final String launchType = launchType(client);
if ("STANDALONE".equals(launchType)) {
final String runningState = serverState(client);
if ("reload-required".equalsIgnoreCase(runningState)) {
executeReload(client, Operations.createOperation("reload"));
try {
waitForStandalone(client, timeout);
} catch (InterruptedException | TimeoutException e) {
throw new RuntimeException("Failed to reload the serve.", e);
}
}
} else {
LOGGER.warnf("Server type %s is not supported for a reload.", launchType);
}
}

/**
* Reloads the server and returns immediately.
*
* @param client the client used to execute the reload operation
* @param reloadOp the reload operation to execute
*/
public static void executeReload(final ModelControllerClient client, final ModelNode reloadOp) {
try {
final ModelNode result = client.execute(reloadOp);
if (!Operations.isSuccessfulOutcome(result)) {
throw new RuntimeException(String.format("Failed to reload the server with %s: %s", reloadOp,
Operations.getFailureDescription(result)));
}
} catch (IOException e) {
final Throwable cause = e.getCause();
if (!(cause instanceof ExecutionException) && !(cause instanceof CancellationException)) {
throw new RuntimeException(e);
} // else ignore, this might happen if the channel gets closed before we got the response
}
}

/**
* Determines the servers "launch-type".
*
* @param client the client used to communicate with the server
* @return the servers launch-type or "unknown" if it could not be determined
*/
public static String launchType(final ModelControllerClient client) {
try {
final ModelNode response = client.execute(Operations.createReadAttributeOperation(EMPTY_ADDRESS, "launch-type"));
if (Operations.isSuccessfulOutcome(response)) {
return Operations.readResult(response).asString();
}
} catch (RuntimeException | IOException e) {
LOGGER.trace("Interrupted determining the launch type", e);
}
return "unknown";
}

/**
* Gets the "server-state" for a standalone server.
*
* @param client the client used to communicate with the server
* @return the server-state or "failed" if an error occurred. A value of "unknown" is returned if the server is not a
* standalone server
*/
public static String serverState(final ModelControllerClient client) {
final String launchType = launchType(client);
if ("STANDALONE".equals(launchType)) {
try {
final ModelNode response = client
.execute(Operations.createReadAttributeOperation(EMPTY_ADDRESS, "server-state"));
return Operations.isSuccessfulOutcome(response) ? Operations.readResult(response).asString() : "failed";
} catch (RuntimeException | IOException e) {
LOGGER.tracef("Interrupted determining the server state", e);
}
return "failed";
}
return "unknown";
}

/**
* Waits the given amount of time in seconds for a managed domain to start. A domain is considered started when each
* of the servers in the domain are started unless the server is disabled.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,16 @@ public class CommandConfiguration extends BaseCommandConfiguration {
private final boolean fork;
private final boolean offline;

private final boolean autoReload;

protected abstract static class AbstractBuilder<T extends AbstractBuilder<T>>
extends BaseCommandConfiguration.AbstractBuilder<T> {

private final Supplier<ModelControllerClient> client;
private final Supplier<MavenModelControllerClientConfiguration> clientConfiguration;
private boolean fork;
private boolean offline;
private boolean autoReload;

AbstractBuilder(final Supplier<ModelControllerClient> clientSupplier,
final Supplier<MavenModelControllerClientConfiguration> clientConfigurationSupplier) {
Expand Down Expand Up @@ -81,6 +84,19 @@ public T setOffline(final boolean offline) {
return builderInstance();
}

/**
* Set to {@code true} if a reload should execute after the commands are complete. The reload will only execute
* if {@link #isOffline()} is {@code false} and the server state is in {@code reload-required}.
*
* @param autoReload {@code true} to enable auto-reload
*
* @return this configuration
*/
public T setAutoReload(final boolean autoReload) {
this.autoReload = autoReload;
return builderInstance();
}

@Override
public CommandConfiguration build() {
return new CommandConfiguration(this);
Expand All @@ -106,6 +122,7 @@ protected CommandConfiguration(AbstractBuilder<?> builder) {
clientConfiguration = builder.clientConfiguration;
fork = builder.fork;
offline = builder.offline;
autoReload = builder.autoReload;
}

/**
Expand Down Expand Up @@ -159,4 +176,14 @@ public boolean isFork() {
public boolean isOffline() {
return offline;
}

/**
* Indicants if the server should be reloaded if the server is in the {@code reload-required} state and
* {@link #isOffline()} is {@code false}.
*
* @return {@code true} if a reload should execute if it's required, otherwise {@code false}
*/
public boolean isAutoReload() {
return !offline && autoReload;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,10 @@ public void execute(final CommandConfiguration config, MavenRepoManager artifact
}
}
}
if (config.isAutoReload()) {
// Reload the server if required
ServerHelper.reloadIfRequired(config.getClient(), config.getTimeout());
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ public class ExecuteCommandsMojo extends AbstractServerConnection {
@Parameter(alias = "java-opts", property = PropertyNames.JAVA_OPTS)
private String[] javaOpts;

/**
* Automatically reloads the server if the commands leave the server in the "reload-required" state. Note a reload
* will not be done if {@code offline} is set to {@code true}.
*
* @since 4.2.1
*/
@Parameter(alias = "auto-reload", defaultValue = "true", property = PropertyNames.AUTO_RELOAD)
private boolean autoReload;

@Component
RepositorySystem repoSystem;

Expand Down Expand Up @@ -237,6 +246,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
.setFork(fork)
.setJBossHome(jbossHome)
.setOffline(offline)
.setAutoReload(autoReload)
.setStdout(stdout)
.setTimeout(timeout)
.setResolveExpression(resolveExpressions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ public interface PropertyNames {

String ADD_RESOURCE_FORCE = "add-resource.force";

String AUTO_RELOAD = "wildfly.auto.reload";

String BATCH = "wildfly.batch";

String CHECK_PACKAGING = "wildfly.checkPackaging";
Expand Down
1 change: 1 addition & 0 deletions plugin/src/main/java/org/wildfly/plugin/dev/DevMojo.java
Original file line number Diff line number Diff line change
Expand Up @@ -399,6 +399,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
.addCommands(commands)
.addScripts(scripts)
.setStdout("none")
.setAutoReload(true)
.setTimeout(timeout);
if (context == null) {
builder.setOffline(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
.addCommands(commands)
.addScripts(scripts)
.setJBossHome(context.jbossHome())
.setAutoReload(true)
.setFork(true)
.setStdout("none")
.setTimeout(timeout)
Expand Down
12 changes: 12 additions & 0 deletions plugin/src/site/fml/faq.fml
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,17 @@
</p>
</answer>
</faq>
<faq id="autoReload">
<question>Why is my server reloading after I execute CLI commands?</question>
<answer>
<p>
In 4.2.1 a new configuration parameter, <code>auto-reload</code>, was added which automatically
reloads the running server if <code>offline</code> is set to <code>false</code> and the command
left the server in a state of <code>reload-required</code>. If you previously had a reload operation
or command in your script or command list, you can now remove it. The other option would be to set
the <code>auto-reload</code> configuration to <code>false</code>.
</p>
</answer>
</faq>
</part>
</faqs>
3 changes: 1 addition & 2 deletions plugin/src/site/markdown/execute-commands-example.md.vm
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,8 @@ batch
# set default transaction timeout
/subsystem=transactions:write-attribute(name=default-timeout, value=600)
#...
# Execute and reload
# Execute
run-batch
:reload
```


Expand Down

0 comments on commit cfe739a

Please sign in to comment.