44import static io .neonbee .internal .deploy .DeployableVerticle .fromClass ;
55import static io .neonbee .internal .deploy .DeployableVerticle .fromVerticle ;
66import static io .neonbee .internal .deploy .Deployables .allTo ;
7+ import static io .neonbee .config .NeonBeeConfig .BootDeploymentHandling .*;
78import static io .neonbee .internal .deploy .Deployables .anyTo ;
89import static io .neonbee .internal .deploy .Deployables .fromDeployables ;
910import static io .neonbee .internal .helper .ConfigHelper .notFound ;
4546import io .neonbee .config .HealthConfig ;
4647import io .neonbee .config .NeonBeeConfig ;
4748import io .neonbee .config .ServerConfig ;
49+ import io .neonbee .config .NeonBeeConfig .BootDeploymentHandling ;
4850import io .neonbee .data .DataException ;
4951import io .neonbee .data .DataQuery ;
5052import io .neonbee .entity .EntityModelManager ;
@@ -566,21 +568,25 @@ private Future<Void> deploySystemVerticles() {
566568 List <Future <? extends Deployable >> requiredVerticles = new ArrayList <>();
567569 requiredVerticles .add (fromClass (vertx , ConsolidationVerticle .class , new JsonObject ().put ("instances" , 1 )));
568570 requiredVerticles .add (fromClass (vertx , LoggerManagerVerticle .class ));
569-
570- List <Future <Optional <? extends Deployable >>> optionalVerticles = new ArrayList <>();
571571 if (Optional .ofNullable (config .getHealthConfig ()).map (HealthConfig ::isEnabled ).orElse (true )) {
572572 requiredVerticles .add (fromClass (vertx , HealthCheckVerticle .class ));
573573 }
574+
575+ List <Future <Optional <? extends Deployable >>> optionalVerticles = new ArrayList <>();
574576 optionalVerticles .add (deployableWatchVerticle (options .getModelsDirectory (), ModelRefreshVerticle ::new ));
575577 optionalVerticles .add (deployableWatchVerticle (options .getModulesDirectory (), DeployerVerticle ::new ));
576578 optionalVerticles .add (deployableRedeployEntitiesJobVerticle (options ));
577579
578580 LOGGER .info ("Deploying system verticles ..." );
579- return all (List .of (fromDeployables (requiredVerticles ).compose (allTo (this )),
580- all (optionalVerticles ).map (CompositeFuture ::list ).map (optionals -> {
581- return optionals .stream ().map (Optional .class ::cast ).filter (Optional ::isPresent ).map (Optional ::get )
582- .map (Deployable .class ::cast ).toList ();
583- }).map (Deployables ::new ).compose (anyTo (this )))).mapEmpty ();
581+ return all (fromDeployables (requiredVerticles ).compose (allTo (this )).onFailure (throwable -> {
582+ LOGGER .error ("Failed to deploy (some / all) required system verticle(s)" , throwable );
583+ }), all (optionalVerticles ).map (CompositeFuture ::list ).map (optionals -> {
584+ return optionals .stream ().map (Optional .class ::cast ).filter (Optional ::isPresent ).map (Optional ::get )
585+ .map (Deployable .class ::cast ).toList ();
586+ }).map (Deployables ::new ).compose (anyTo (this )).onFailure (throwable -> {
587+ LOGGER .error ("Failed to deploy (some / all) optional system verticle(s), bootstrap will continue" ,
588+ throwable );
589+ }).otherwiseEmpty ()).mapEmpty ();
584590 }
585591
586592 private Future <Optional <? extends Deployable >> deployableWatchVerticle (
@@ -621,7 +627,9 @@ private Future<Optional<? extends Deployable>> deployableRedeployEntitiesJobVert
621627 private Future <Void > deployServerVerticle () {
622628 LOGGER .info ("Deploying server verticle ..." );
623629 return fromClass (vertx , ServerVerticle .class , new JsonObject ().put ("instances" , NUMBER_DEFAULT_INSTANCES ))
624- .compose (deployable -> deployable .deploy (this )).mapEmpty ();
630+ .compose (deployable -> deployable .deploy (this )).onFailure (throwable -> {
631+ LOGGER .error ("Failed to deploy server verticle" , throwable );
632+ }).mapEmpty ();
625633 }
626634
627635 /**
@@ -638,11 +646,7 @@ private Future<Void> deployClassPathVerticles() {
638646 return scanForDeployableClasses (vertx ).compose (deployableClasses -> fromDeployables (deployableClasses .stream ()
639647 .filter (verticleClass -> filterByAutoDeployAndProfiles (verticleClass , options .getActiveProfiles ()))
640648 .map (verticleClass -> fromClass (vertx , verticleClass )).collect (Collectors .toList ())))
641- .onSuccess (deployables -> {
642- if (LOGGER .isInfoEnabled ()) {
643- LOGGER .info ("Deploy class path verticle(s) {}." , deployables .getIdentifier ());
644- }
645- }).compose (allTo (this )).mapEmpty ();
649+ .compose (handleBootDeployment ("class path verticle(s)" ));
646650 }
647651
648652 @ VisibleForTesting
@@ -665,7 +669,39 @@ private Future<Void> deployModules() {
665669
666670 LOGGER .info ("Deploying module(s) ..." );
667671 return fromDeployables (moduleJarPaths .stream ().map (moduleJarPath -> fromJar (vertx , moduleJarPath ))
668- .collect (Collectors .toList ())).compose (allTo (this )).mapEmpty ();
672+ .collect (Collectors .toList ())).compose (handleBootDeployment ("module(s)" ));
673+ }
674+
675+ private Function <Deployables , Future <Void >> handleBootDeployment (String deploymentType ) {
676+ BootDeploymentHandling handling = config .getBootDeploymentHandling ();
677+ return deployables -> {
678+ // in case we should keep partial deployments, for every deployable that we are about to deploy
679+ // set the keep partial deployment flag, so that in case there is an error we don't undeploy
680+ if (handling == KEEP_PARTIAL ) {
681+ for (Deployable deployable : deployables .getDeployables ()) {
682+ if (deployable instanceof Deployables ) {
683+ ((Deployables ) deployable ).keepPartialDeployment ();
684+ }
685+ }
686+ }
687+
688+ return (handling == FAIL_ON_ERROR ? allTo (this ) : anyTo (this )).apply (deployables )
689+ .onSuccess (deployments -> {
690+ if (LOGGER .isInfoEnabled ()) {
691+ LOGGER .info ("Successfully deployed all {} {}" ,
692+ deploymentType , deployments .getDeploymentId ());
693+ }
694+ }).recover (throwable -> {
695+ if (LOGGER .isErrorEnabled ()) {
696+ LOGGER .error ("Failed to deploy (some / all) {}{}" ,
697+ deploymentType , handling == FAIL_ON_ERROR ? "" : ", bootstrap will continue" ,
698+ throwable );
699+ }
700+
701+ // abort the boot process if any class path verticle failed to deploy
702+ return handling == FAIL_ON_ERROR ? failedFuture (throwable ) : succeededFuture ();
703+ }).mapEmpty ();
704+ };
669705 }
670706
671707 @ VisibleForTesting
0 commit comments