|
@@ -1,12 +1,11 @@
|
|
|
package cz.senslog.messaging.app;
|
|
package cz.senslog.messaging.app;
|
|
|
|
|
|
|
|
|
|
|
|
|
-import cz.senslog.messaging.domain.ServiceConfig;
|
|
|
|
|
-import cz.senslog.messaging.domain.SubscriberConfig;
|
|
|
|
|
import cz.senslog.messaging.server.HttpVertxServer;
|
|
import cz.senslog.messaging.server.HttpVertxServer;
|
|
|
-import io.vertx.core.AbstractVerticle;
|
|
|
|
|
|
|
+import cz.senslog.messaging.utils.PromiseSupport;
|
|
|
|
|
+import cz.senslog.messaging.utils.Tuple;
|
|
|
|
|
+import io.vertx.core.*;
|
|
|
import io.vertx.core.DeploymentOptions;
|
|
import io.vertx.core.DeploymentOptions;
|
|
|
-import io.vertx.core.Vertx;
|
|
|
|
|
import io.vertx.core.json.JsonArray;
|
|
import io.vertx.core.json.JsonArray;
|
|
|
import io.vertx.core.json.JsonObject;
|
|
import io.vertx.core.json.JsonObject;
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.LogManager;
|
|
@@ -16,13 +15,11 @@ import java.io.FileInputStream;
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
import java.io.InputStream;
|
|
|
import java.time.Duration;
|
|
import java.time.Duration;
|
|
|
-import java.util.ArrayList;
|
|
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
|
|
import java.util.Properties;
|
|
import java.util.Properties;
|
|
|
|
|
|
|
|
-import static cz.senslog.messaging.service.ServiceCreator.createServices;
|
|
|
|
|
-import static cz.senslog.messaging.utils.ServiceUtil.createServiceSubscriberId;
|
|
|
|
|
|
|
+import static cz.senslog.messaging.app.ChannelSubscriberDeployer.CHANNEL_PATH_TO_DEPLOY;
|
|
|
|
|
+import static cz.senslog.messaging.app.ServiceDeployer.SERVICE_PATH_TO_DEPLOY;
|
|
|
|
|
|
|
|
|
|
|
|
|
public final class Application {
|
|
public final class Application {
|
|
@@ -69,59 +66,109 @@ public final class Application {
|
|
|
public static void start() {
|
|
public static void start() {
|
|
|
logger.info("Starting app '{}', version '{}', build '{}'.", PROJECT_NAME, COMPILED_VERSION, BUILD_VERSION);
|
|
logger.info("Starting app '{}', version '{}', build '{}'.", PROJECT_NAME, COMPILED_VERSION, BUILD_VERSION);
|
|
|
|
|
|
|
|
- EnvironmentalProperty envProperties = EnvironmentalProperty.getInstance();
|
|
|
|
|
|
|
+ final EnvironmentalProperty envProperties = EnvironmentalProperty.getInstance();
|
|
|
|
|
|
|
|
- Configuration configuration;
|
|
|
|
|
|
|
+ final Configuration configuration;
|
|
|
try {
|
|
try {
|
|
|
- configuration = Configuration.createFromYaml(envProperties.getConfigPath());
|
|
|
|
|
- } catch (IOException e) {
|
|
|
|
|
|
|
+ switch (envProperties.getConfigurationType()) {
|
|
|
|
|
+ case FILE -> configuration = FileConfiguration.createFromYaml(envProperties.getConfigFilePath());
|
|
|
|
|
+ default -> throw new IllegalStateException("Configuration type not supported: " + envProperties.getConfigurationType());
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
terminate(e.getMessage()); return;
|
|
terminate(e.getMessage()); return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- JsonArray channels = new JsonArray(configuration.getChannelsById().values().stream().map(ch -> JsonObject.of(
|
|
|
|
|
- "id", ch.id(),
|
|
|
|
|
- "maxLength", ch.messageType().maxLength(),
|
|
|
|
|
- "subscribers", new JsonArray(ch.subscribers().stream()
|
|
|
|
|
- .map(s -> JsonObject.of(
|
|
|
|
|
- "id", createServiceSubscriberId(s.service().id(), s.id()),
|
|
|
|
|
- "serviceId", s.service().id(),
|
|
|
|
|
- "subscriberId", s.id()
|
|
|
|
|
- )).toList())
|
|
|
|
|
- )).toList());
|
|
|
|
|
-
|
|
|
|
|
- JsonObject services = new JsonObject();
|
|
|
|
|
- for (ServiceConfig service : configuration.getServicesById().values()) {
|
|
|
|
|
- services.put(service.id(), JsonObject.of(
|
|
|
|
|
- "config", service.config(),
|
|
|
|
|
- "subscribedRecipients", new JsonArray()
|
|
|
|
|
- ));
|
|
|
|
|
- }
|
|
|
|
|
- for (SubscriberConfig subscriber : configuration.getSubscribersById().values()) {
|
|
|
|
|
- services.getJsonObject(subscriber.service().id()).getJsonArray("subscribedRecipients").add(JsonObject.of(
|
|
|
|
|
- "id", subscriber.id(),
|
|
|
|
|
- "config", subscriber.config()
|
|
|
|
|
- ));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- DeploymentOptions opt = new DeploymentOptions()
|
|
|
|
|
- .setConfig(envProperties.asJson().mergeIn(JsonObject.of(
|
|
|
|
|
- "channels", channels,
|
|
|
|
|
- "services", services
|
|
|
|
|
- )));
|
|
|
|
|
|
|
+ Vertx vertx = Vertx.vertx();
|
|
|
|
|
+ deployServices(vertx, configuration).compose(tupleServices -> {
|
|
|
|
|
+ final String serviceDeploymentId = tupleServices.item1();
|
|
|
|
|
+ final List<JsonObject> services = tupleServices.item2();
|
|
|
|
|
+ services.forEach(r ->
|
|
|
|
|
+ logger.info("Deployment '{}#{}' was successful.", r.getString("serviceId"), r.getString("deploymentId"))
|
|
|
|
|
+ );
|
|
|
|
|
+ return deployChannelSubscribers(vertx, configuration, serviceDeploymentId).map(t -> Tuple.of(serviceDeploymentId, t));
|
|
|
|
|
+ }).compose(tuple -> {
|
|
|
|
|
+ final String serviceDeploymentId = tuple.item1();
|
|
|
|
|
+ final Tuple<String, Object> tupleChannels = tuple.item2();
|
|
|
|
|
+ final String channelDeploymentId = tupleChannels.item1();
|
|
|
|
|
+ final Object channels = tupleChannels.item2();
|
|
|
|
|
+ return deployHttpServer(vertx, envProperties.getHttpServerPort(), serviceDeploymentId, channelDeploymentId);
|
|
|
|
|
+ }).onSuccess(httpServerDeploymentId -> {
|
|
|
|
|
+ logger.info("Http Server deployment '{}'", httpServerDeploymentId);
|
|
|
|
|
+ logger.info("Started in {} second.", uptime() / 1000.0);
|
|
|
|
|
+ }).onFailure(f -> {
|
|
|
|
|
+ logger.catching(f);
|
|
|
|
|
+ terminate(f.getMessage());
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- List<AbstractVerticle> verticles = new ArrayList<>();
|
|
|
|
|
|
|
+ private static Future<String> deployHttpServer(Vertx vertx, int httpPort, String serviceDeploymentId, String channelDeploymentId) {
|
|
|
|
|
+ final Promise<String> deployPromise = Promise.promise();
|
|
|
|
|
+ vertx.deployVerticle(HttpVertxServer.class, new DeploymentOptions()
|
|
|
|
|
+ .setThreadingModel(ThreadingModel.WORKER)
|
|
|
|
|
+ .setConfig(JsonObject.of(
|
|
|
|
|
+ "server.http.port", httpPort,
|
|
|
|
|
+ "services.deploymentId", serviceDeploymentId,
|
|
|
|
|
+ "channels.deploymentId", channelDeploymentId
|
|
|
|
|
+ ))
|
|
|
|
|
+ .setInstances(1), PromiseSupport.onComplete(deployPromise));
|
|
|
|
|
+ return deployPromise.future();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- verticles.add(new HttpVertxServer());
|
|
|
|
|
- verticles.addAll(createServices(configuration.getServicesById().values()));
|
|
|
|
|
|
|
+ private static Future<Tuple<String, Object>> deployChannelSubscribers(Vertx vertx, Configuration configuration, String serviceDeploymentId) {
|
|
|
|
|
+ final Promise<Tuple<String, Object>> deployPromise = Promise.promise();
|
|
|
|
|
+ final DeploymentOptions deploymentOptions = new DeploymentOptions()
|
|
|
|
|
+ .setThreadingModel(ThreadingModel.WORKER)
|
|
|
|
|
+ .setConfig(JsonObject.of("services.deploymentId", serviceDeploymentId))
|
|
|
|
|
+ .setInstances(1);
|
|
|
|
|
+
|
|
|
|
|
+ vertx.deployVerticle(ChannelSubscriberDeployer.class, deploymentOptions, res -> {
|
|
|
|
|
+ if (res.succeeded()) {
|
|
|
|
|
+ final String channelDeploymentId = res.result();
|
|
|
|
|
+ final String channelDeployerPath = CHANNEL_PATH_TO_DEPLOY.apply(channelDeploymentId);
|
|
|
|
|
+ configuration.channelDescriptors().onFailure(deployPromise::fail)
|
|
|
|
|
+ .onSuccess(descriptors -> vertx.eventBus().<JsonArray>request(channelDeployerPath, new JsonArray(descriptors), replay -> {
|
|
|
|
|
+ if (replay.succeeded()) {
|
|
|
|
|
+ deployPromise.complete(Tuple.of(channelDeploymentId, replay.result()));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ deployPromise.fail(res.cause());
|
|
|
|
|
+ }
|
|
|
|
|
+ }));
|
|
|
|
|
+ } else {
|
|
|
|
|
+ deployPromise.fail(res.cause());
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return deployPromise.future();
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- Vertx.vertx().deployVerticle(VertxDeployer.deploy(verticles.toArray(AbstractVerticle[]::new)), opt, res -> {
|
|
|
|
|
- if(res.succeeded()) {
|
|
|
|
|
- logger.info("Deployment id is: {}", res.result());
|
|
|
|
|
- logger.info("Started in {} second.", uptime() / 1000.0);
|
|
|
|
|
|
|
+ private static Future<Tuple<String, List<JsonObject>>> deployServices(Vertx vertx, Configuration configuration) {
|
|
|
|
|
+ final Promise<Tuple<String, List<JsonObject>>> deployPromise = Promise.promise();
|
|
|
|
|
+ final DeploymentOptions deploymentOptions = new DeploymentOptions()
|
|
|
|
|
+ .setThreadingModel(ThreadingModel.WORKER)
|
|
|
|
|
+ .setInstances(1);
|
|
|
|
|
+
|
|
|
|
|
+ vertx.deployVerticle(ServiceDeployer.class, deploymentOptions, res -> {
|
|
|
|
|
+ if (res.succeeded()) {
|
|
|
|
|
+ final String serviceDeploymentId = res.result();
|
|
|
|
|
+ configuration.serviceDescriptors().onFailure(deployPromise::fail) // fail of retrieving service's descriptors
|
|
|
|
|
+ .onSuccess(descriptors -> Future.all(descriptors.stream().map(d -> {
|
|
|
|
|
+ final Promise<JsonObject> promise = Promise.promise();
|
|
|
|
|
+ final String serviceDeployerPath = SERVICE_PATH_TO_DEPLOY.apply(serviceDeploymentId);
|
|
|
|
|
+ vertx.eventBus().<JsonObject>request(serviceDeployerPath, d, replay -> {
|
|
|
|
|
+ if (replay.succeeded()) {
|
|
|
|
|
+ promise.complete(replay.result().body());
|
|
|
|
|
+ } else {
|
|
|
|
|
+ promise.fail(replay.cause()); // fail of service deploy
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ return promise.future();
|
|
|
|
|
+ }).toList())
|
|
|
|
|
+ .onSuccess(compositeRes -> deployPromise.complete(Tuple.of(serviceDeploymentId, compositeRes.list()
|
|
|
|
|
+ .stream().map(JsonObject.class::cast).toList())))
|
|
|
|
|
+ .onFailure(deployPromise::fail)); // fail of one and more services
|
|
|
} else {
|
|
} else {
|
|
|
- logger.error("Deployment failed! The reason is '{}'", res.cause().getMessage());
|
|
|
|
|
- logger.catching(res.cause());
|
|
|
|
|
|
|
+ deployPromise.fail(res.cause()); // fail of ServiceDeployer
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
|
|
+ return deployPromise.future();
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|