Skip to content

Commit

Permalink
Allow users to configure instance identifiers
Browse files Browse the repository at this point in the history
Right now, upon connection to AxonIQ Console, a random 4-letter string is assigned to make each client unique. Because the hostname can be the same for many clients (Especially in kubernetes). This works.

However, it's better if the clients themselves define this identifier randomly. As statistics are saved under the instance name, they will duplicate if an instance disconnects and reconnects. By moving this random generation to the client, we will solve this problem.
  • Loading branch information
CodeDrivenMitch committed Dec 13, 2024
1 parent 1bf5bd6 commit 463ce65
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
Expand Down Expand Up @@ -86,6 +87,7 @@ public class AxoniqConsoleConfigurerModule implements ConfigurerModule {
private final SpanMatcherPredicateMap spanMatcherPredicateMap;
private final EventScheduler eventScheduler;
private final MeterRegistry meterRegistry = new SimpleMeterRegistry();
private final String instanceName;

/**
* Creates the {@link AxoniqConsoleConfigurerModule} with the given {@code builder}.
Expand All @@ -96,6 +98,7 @@ protected AxoniqConsoleConfigurerModule(Builder builder) {
this.environmentId = builder.environmentId;
this.accessToken = builder.accessToken;
this.applicationName = builder.applicationName.replaceAll("([\\[\\]])", "-");
this.instanceName = builder.hostname + "-" + builder.nodeId;
this.host = builder.host;
this.port = builder.port;
this.secure = builder.secure;
Expand Down Expand Up @@ -182,7 +185,7 @@ public void configureModule(@NotNull Configurer configurer) {
c.getComponent(RSocketPayloadEncodingStrategy.class),
c.getComponent(ClientSettingsService.class),
reportingTaskExecutor,
ManagementFactory.getRuntimeMXBean().getName()
instanceName
)
)
.registerComponent(ServerProcessorReporter.class,
Expand Down Expand Up @@ -282,6 +285,8 @@ public static class Builder {
private String host = "framework.console.axoniq.io";
private Boolean secure = true;
private Integer port = 7000;
private String hostname = ManagementFactory.getRuntimeMXBean().getName();
private String nodeId = randomNodeId();
private AxoniqConsoleDlqMode dlqMode = AxoniqConsoleDlqMode.NONE;
private final List<String> dlqDiagnosticsWhitelist = new ArrayList<>();
private Long initialDelay = 0L;
Expand Down Expand Up @@ -314,6 +319,30 @@ public Builder(String environmentId, String accessToken, String applicationName)
this.applicationName = applicationName;
}

/**
* The hostname of the application. Defaults to the runtime name of the JVM.
* Needs to be unique in combination with the {@code nodeId}.
* @param hostname The hostname of the application
* @return The builder for fluent interfacing
*/
public Builder hostname(String hostname) {
BuilderUtils.assertNonEmpty(hostname, "Hostname may not be null or empty");
this.hostname = hostname;
return this;
}

/**
* The node id of the application. Defaults to a random four character string.
* This is to prevent conflicts when multiple instances of the same application are running on the same host.
* @param nodeId The node id of the application
* @return The builder for fluent interfacing
*/
public Builder nodeId(String nodeId) {
BuilderUtils.assertNonEmpty(nodeId, "Node id may not be null or empty");
this.nodeId = nodeId;
return this;
}

/**
* The host to connect to. Defaults to {@code framework.console.axoniq.io}.
*
Expand Down Expand Up @@ -504,5 +533,10 @@ public AxoniqConsoleConfigurerModule build() {
}
return new AxoniqConsoleConfigurerModule(this);
}

private String randomNodeId() {
String uuid = UUID.randomUUID().toString();
return uuid.substring(uuid.length() - 4);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import reactor.core.publisher.Mono
import reactor.netty.tcp.TcpClient
import java.time.Instant
import java.time.temporal.ChronoUnit
import java.util.*
import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.ScheduledFuture
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -68,7 +69,7 @@ class AxoniqConsoleRSocketClient(
private val encodingStrategy: RSocketPayloadEncodingStrategy,
private val clientSettingsService: ClientSettingsService,
private val executor: ScheduledExecutorService,
private val nodeName: String,
private val instanceName: String,
) : Lifecycle {
private val heartbeatOrchestrator = HeartbeatOrchestrator()
private var maintenanceTask: ScheduledFuture<*>? = null
Expand Down Expand Up @@ -167,7 +168,7 @@ class AxoniqConsoleRSocketClient(
val settings = retrieveSettings().block()
?: throw IllegalStateException("Could not receive the settings from AxonIQ console!")
clientSettingsService.updateSettings(settings)
logger.info("Connection to AxonIQ Console set up successfully! Settings: $settings")
logger.info("Connection to AxonIQ Console set up successfully! This instance's name: $instanceName, settings: $settings")
connectionRetryCount = 0
} catch (e: Exception) {
if (connectionRetryCount == 5) {
Expand All @@ -183,7 +184,7 @@ class AxoniqConsoleRSocketClient(
identification = io.axoniq.console.framework.api.ConsoleClientIdentifier(
environmentId = environmentId,
applicationName = applicationName,
nodeName = nodeName
nodeName = instanceName
),
accessToken = accessToken
)
Expand Down

0 comments on commit 463ce65

Please sign in to comment.