From 4895b96ad0a1a26348ebeda1c12db06fcef8479c Mon Sep 17 00:00:00 2001 From: zero-88 Date: Thu, 19 Mar 2020 13:23:59 +0700 Subject: [PATCH 1/6] core:installer: - Refactor Installer API service. - Add TransactionByAppService on both Bios and Edge Installer module --- .../com/nubeiot/core/dto/RequestFilter.java | 5 +- core/installer/build.gradle | 1 + .../installer/InstallerEntityHandler.java | 6 +- .../edge/installer/InstallerVerticle.java | 6 +- ...ployer.java => AppDeployerDefinition.java} | 23 ++++-- .../service/AppDeploymentService.java | 2 +- .../service/AppDeploymentTracker.java | 2 +- .../service/AppDeploymentWorkflow.java | 6 +- .../edge/installer/service/BackupService.java | 8 +++ ...java => DefaultAppDeployerDefinition.java} | 2 +- .../installer/service/DeploymentService.java | 13 ++++ .../installer/service/InstallerService.java | 53 +++++++++++--- .../service/TransactionByAppService.java | 70 +++++++++++++++++++ .../installer/service/TransactionService.java | 5 +- .../nubeiot/edge/installer/zip/ZipUtils.java | 22 ++++++ .../installer/mock/MockInstallerService.java | 2 +- .../installer/mock/MockInstallerVerticle.java | 8 +-- .../nubeiot/edge/bios/EdgeBiosVerticle.java | 9 +-- .../bios/service/BiosInstallerService.java | 4 +- .../service/BiosTransactionByAppService.java | 14 ++++ .../EdgeServiceInstallerVerticle.java | 10 +-- .../service/EdgeInstallerService.java | 4 +- .../EdgeTransactionByModuleService.java | 65 ++--------------- 23 files changed, 232 insertions(+), 108 deletions(-) rename core/installer/src/main/java/com/nubeiot/edge/installer/service/{AppDeployer.java => AppDeployerDefinition.java} (56%) create mode 100644 core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java rename core/installer/src/main/java/com/nubeiot/edge/installer/service/{DefaultAppDeployer.java => DefaultAppDeployerDefinition.java} (91%) create mode 100644 core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java create mode 100644 core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java create mode 100644 edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosTransactionByAppService.java diff --git a/core/base/src/main/java/com/nubeiot/core/dto/RequestFilter.java b/core/base/src/main/java/com/nubeiot/core/dto/RequestFilter.java index 7df95d442..2c6072507 100644 --- a/core/base/src/main/java/com/nubeiot/core/dto/RequestFilter.java +++ b/core/base/src/main/java/com/nubeiot/core/dto/RequestFilter.java @@ -10,6 +10,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; +import lombok.NonNull; /** * Represents for Request filter. @@ -80,8 +81,8 @@ public Set getIncludes() { return Arrays.stream(getString(RequestFilter.Filters.INCLUDE, "").split(",")).collect(Collectors.toSet()); } - private boolean parseBoolean(String pretty) { - return Boolean.parseBoolean(Strings.toString(this.getValue(pretty))); + public boolean parseBoolean(@NonNull String param) { + return Boolean.parseBoolean(Strings.toString(this.getValue(param))); } /** diff --git a/core/installer/build.gradle b/core/installer/build.gradle index 1b49c2a09..535f961fd 100644 --- a/core/installer/build.gradle +++ b/core/installer/build.gradle @@ -13,6 +13,7 @@ dependencies { compile project(':eventbus:edge') compile project.deps.database.h2 compile "io.vertx:vertx-maven-service-factory:$project.versions.vertx" + compile "net.lingala.zip4j:zip4j:2.5.0" testCompile project(":core:base").sourceSets.test.output } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java index 3c005f130..2a8e3ab55 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java @@ -43,7 +43,7 @@ import com.nubeiot.edge.installer.model.tables.pojos.TblModule; import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; import com.nubeiot.edge.installer.repository.InstallerRepository; -import com.nubeiot.edge.installer.service.AppDeployer; +import com.nubeiot.edge.installer.service.AppDeployerDefinition; import com.nubeiot.edge.installer.service.InstallerApiIndex; import lombok.AccessLevel; @@ -105,8 +105,8 @@ final Single> getModulesWhenBootstrap() { } final InstallerEntityHandler initDeployer() { - final AppDeployer appDeployer = sharedData(SHARED_APP_DEPLOYER_CFG); - appDeployer.register(this); + final AppDeployerDefinition definition = sharedData(SHARED_APP_DEPLOYER_CFG); + definition.register(this); return this; } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerVerticle.java b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerVerticle.java index f96435aaa..53f1f8f4e 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerVerticle.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerVerticle.java @@ -16,7 +16,7 @@ import com.nubeiot.core.sql.SqlContext; import com.nubeiot.core.sql.SqlProvider; import com.nubeiot.edge.installer.loader.ModuleTypeRule; -import com.nubeiot.edge.installer.service.AppDeployer; +import com.nubeiot.edge.installer.service.AppDeployerDefinition; import com.nubeiot.edge.installer.service.AppDeploymentWorkflow; import com.nubeiot.edge.installer.service.InstallerService; @@ -40,7 +40,7 @@ public void start() { final ModuleTypeRule moduleRule = getModuleRuleProvider().get(); this.addSharedData(InstallerEntityHandler.SHARED_INSTALLER_CFG, installerConfig) .addSharedData(InstallerEntityHandler.SHARED_MODULE_RULE, moduleRule) - .addSharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG, appDeployer()) + .addSharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG, appDeployerDefinition()) .addProvider(new SqlProvider<>(entityHandlerClass()), this::sqlHandler) .addProvider(new MicroserviceProvider(), ctx -> microContext = (MicroContext) ctx) .registerSuccessHandler(v -> publishApis(microContext).flatMap(r -> deployAppModules()).subscribe(r -> { @@ -58,7 +58,7 @@ public void start() { protected abstract Supplier getModuleRuleProvider(); @NonNull - protected abstract AppDeployer appDeployer(); + protected abstract AppDeployerDefinition appDeployerDefinition(); @NonNull protected abstract Supplier> services(@NonNull InstallerEntityHandler handler); diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeployer.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeployerDefinition.java similarity index 56% rename from core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeployer.java rename to core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeployerDefinition.java index 75b3eeac1..f39991475 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeployer.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeployerDefinition.java @@ -9,18 +9,30 @@ /** * Application service deployer definition + * + * @since 1.0.0 */ -public interface AppDeployer extends Shareable { +public interface AppDeployerDefinition extends Shareable { - static AppDeployer create(@NonNull EventModel loaderEvent, @NonNull EventModel trackerEvent, - @NonNull EventModel finisherEvent) { - return new DefaultAppDeployer(loaderEvent, trackerEvent, finisherEvent); + /** + * Create app deployer definition. + * + * @param loaderEvent the loader event + * @param trackerEvent the tracker event + * @param finisherEvent the finisher event + * @return the app deployer + * @since 1.0.0 + */ + static AppDeployerDefinition create(@NonNull EventModel loaderEvent, @NonNull EventModel trackerEvent, + @NonNull EventModel finisherEvent) { + return new DefaultAppDeployerDefinition(loaderEvent, trackerEvent, finisherEvent); } /** * Defines deployment loader event * * @return loader event + * @since 1.0.0 */ @NonNull EventModel getLoaderEvent(); @@ -28,6 +40,7 @@ static AppDeployer create(@NonNull EventModel loaderEvent, @NonNull EventModel t * Defines tracker event after finish deploying * * @return tracker event + * @since 1.0.0 */ @NonNull EventModel getTrackerEvent(); @@ -35,6 +48,7 @@ static AppDeployer create(@NonNull EventModel loaderEvent, @NonNull EventModel t * Defines finisher event after finish deploy and update database * * @return finisher event + * @since 1.0.0 */ @NonNull EventModel getFinisherEvent(); @@ -42,6 +56,7 @@ static AppDeployer create(@NonNull EventModel loaderEvent, @NonNull EventModel t * Register event service * * @param entityHandler Entity handler + * @since 1.0.0 */ void register(@NonNull InstallerEntityHandler entityHandler); diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentService.java index fe39c5293..c1354955d 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentService.java @@ -104,7 +104,7 @@ void doUnDeploy(PreDeploymentResult preResult, boolean silent, Future fu private void publishResult(PreDeploymentResult preResult, AsyncResult async) { final EventbusClient client = sharedData(SharedDataDelegate.SHARED_EVENTBUS); - final AppDeployer deployer = sharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG); + final AppDeployerDefinition deployer = sharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG); final JsonObject error = async.succeeded() ? new JsonObject() : ErrorMessage.parse(async.cause()).toJson(); final PostDeploymentResult pr = PostDeploymentResult.from(preResult, async.result(), error); client.fire(DeliveryEvent.from(deployer.getTrackerEvent(), new JsonObject().put("result", pr.toJson()))); diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java index c009a7b8c..b24b485c8 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java @@ -57,7 +57,7 @@ public Single handle(@Param("result") PostDeploymentResult ? handleError(result) : handleSuccess(result); final EventbusClient client = sharedData(SharedDataDelegate.SHARED_EVENTBUS); - final AppDeployer deployer = sharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG); + final AppDeployerDefinition deployer = sharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG); return last.doOnSuccess(res -> client.fire( DeliveryEvent.from(deployer.getFinisherEvent(), new JsonObject().put("result", res.toJson())))); } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java index a926ddbc4..d07825f6a 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java @@ -38,11 +38,11 @@ public final class AppDeploymentWorkflow { private static final Logger LOGGER = LoggerFactory.getLogger(AppDeploymentWorkflow.class); private final InstallerEntityHandler entityHandler; - private final AppDeployer deployer; + private final AppDeployerDefinition definition; public AppDeploymentWorkflow(InstallerEntityHandler entityHandler) { this.entityHandler = entityHandler; - this.deployer = entityHandler.sharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG); + this.definition = entityHandler.sharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG); } public Single process(ITblModule module, EventAction action) { @@ -103,7 +103,7 @@ private void deployModule(PreDeploymentResult preDeployResult) { LOGGER.info("INSTALLER trigger deploying for {}::::{}", action, preDeployResult.getServiceId()); preDeployResult.setSilent(EventAction.REMOVE == action && State.DISABLED == preDeployResult.getPrevState()); entityHandler.eventClient() - .fire(DeliveryEvent.from(deployer.getLoaderEvent(), action, preDeployResult.toRequestData())); + .fire(DeliveryEvent.from(definition.getLoaderEvent(), action, preDeployResult.toRequestData())); } private PreDeploymentResult createPreDeployResult(ITblModule module, String transactionId, EventAction action, diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java new file mode 100644 index 000000000..23c058f20 --- /dev/null +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java @@ -0,0 +1,8 @@ +package com.nubeiot.edge.installer.service; + +/** + * Represents Backup service. + * + * @since 1.0.0 + */ +public interface BackupService extends InstallerService {} diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/DefaultAppDeployer.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/DefaultAppDeployerDefinition.java similarity index 91% rename from core/installer/src/main/java/com/nubeiot/edge/installer/service/DefaultAppDeployer.java rename to core/installer/src/main/java/com/nubeiot/edge/installer/service/DefaultAppDeployerDefinition.java index 79fecab12..f9af152aa 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/DefaultAppDeployer.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/DefaultAppDeployerDefinition.java @@ -9,7 +9,7 @@ @Getter @RequiredArgsConstructor -final class DefaultAppDeployer implements AppDeployer { +final class DefaultAppDeployerDefinition implements AppDeployerDefinition { @NonNull private final EventModel loaderEvent; diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/DeploymentService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/DeploymentService.java index a55cf46de..1fcf1e98a 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/DeploymentService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/DeploymentService.java @@ -2,8 +2,21 @@ import com.nubeiot.core.event.EventListener; +/** + * The interface Deployment service. + * + * @since 1.0.0 + */ public interface DeploymentService extends EventListener { + /** + * Gets shared data. + * + * @param Type of {@code data} + * @param dataKey the data key + * @return the data + * @since 1.0.0 + */ D sharedData(String dataKey); } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java index f8325d886..525d189df 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java @@ -6,9 +6,6 @@ import java.util.Set; import java.util.stream.Collectors; -import io.vertx.core.http.HttpMethod; - -import com.nubeiot.core.event.EventAction; import com.nubeiot.core.http.base.EventHttpService; import com.nubeiot.core.http.base.Urls; import com.nubeiot.core.http.base.event.ActionMethodMapping; @@ -16,8 +13,22 @@ import com.nubeiot.core.utils.Reflections.ReflectionClass; import com.nubeiot.edge.installer.InstallerEntityHandler; +/** + * Represents Installer service. + * + * @since 1.0.0 + */ public interface InstallerService extends EventHttpService { + /** + * Create services. + * + * @param Type of {@code InstallerService} + * @param entityHandler the entity handler + * @param serviceClazz the service clazz + * @return set of {@code InstallerService} + * @since 1.0.0 + */ static Set createServices(InstallerEntityHandler entityHandler, Class serviceClazz) { final Map inputs = Collections.singletonMap(InstallerEntityHandler.class, entityHandler); @@ -29,17 +40,43 @@ static Set createServices(InstallerEntityHandler @Override default Set definitions() { - Map map = ActionMethodMapping.CRUD_MAP.get(); - ActionMethodMapping actionMethodMap = ActionMethodMapping.create( - getAvailableEvents().stream().filter(map::containsKey).collect(Collectors.toMap(e -> e, map::get))); + final String fullPath = Urls.combinePath(rootPath(), appPath(), servicePath()); return Collections.singleton( - EventMethodDefinition.create(Urls.combinePath(rootPath(), servicePath()), paramPath(), actionMethodMap)); + EventMethodDefinition.create(fullPath, paramPath(), ActionMethodMapping.byCRUD(getAvailableEvents()))); + } + + /** + * Defines Root path. + * + * @return Root path + * @since 1.0.0 + */ + default String rootPath() { + return "/installer"; } - String rootPath(); + /** + * Defines Application path. + * + * @return Application path + * @since 1.0.0 + */ + String appPath(); + /** + * Defines Service path. + * + * @return Service path + * @since 1.0.0 + */ String servicePath(); + /** + * Defines Param path. + * + * @return Param path + * @since 1.0.0 + */ String paramPath(); } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java new file mode 100644 index 000000000..9df671087 --- /dev/null +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java @@ -0,0 +1,70 @@ +package com.nubeiot.edge.installer.service; + +import java.util.Collection; +import java.util.Collections; + +import io.reactivex.Single; +import io.vertx.core.json.JsonArray; +import io.vertx.core.json.JsonObject; + +import com.nubeiot.core.dto.RequestData; +import com.nubeiot.core.event.EventAction; +import com.nubeiot.core.event.EventContractor; +import com.nubeiot.core.exceptions.NotFoundException; +import com.nubeiot.core.utils.Strings; +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.model.tables.interfaces.ITblTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; + +import lombok.AccessLevel; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +public abstract class TransactionByAppService implements InstallerService { + + @NonNull + private final InstallerEntityHandler entityHandler; + + @EventContractor(action = EventAction.GET_LIST, returnType = Single.class) + public Single getList(RequestData data) { + final ITblTransaction transaction = new TblTransaction().fromJson(data.body()); + if (Strings.isBlank(transaction.getModuleId())) { + throw new IllegalArgumentException("Service id is mandatory"); + } + if (data.filter().parseBoolean("last")) { + return this.entityHandler.findOneTransactionByModuleId(transaction.getModuleId()) + .map(o -> o.orElseThrow(() -> new NotFoundException( + String.format("Not found service id '%s'", transaction.getModuleId())))) + .map(this::removePrevSystemConfig) + .map(transactions -> new JsonObject().put("transactions", + new JsonArray().add(transactions))); + } + return this.entityHandler.findTransactionByModuleId(transaction.getModuleId()) + .flattenAsObservable(transactions -> transactions) + .flatMapSingle(trans -> Single.just(removePrevSystemConfig(trans.toJson()))) + .toList() + .map(transactions -> new JsonObject().put("transactions", transactions)); + } + + private JsonObject removePrevSystemConfig(JsonObject transaction) { + transaction.remove("prev_system_config"); + return transaction; + } + + @Override + public @NonNull Collection getAvailableEvents() { + return Collections.singleton(EventAction.GET_LIST); + } + + @Override + public String servicePath() { + return "/:module_id/transaction"; + } + + @Override + public String paramPath() { + return null; + } + +} diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java index 4c686b8f1..fc3d106f2 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java @@ -29,8 +29,7 @@ public abstract class TransactionService implements InstallerService { @EventContractor(action = EventAction.GET_ONE, returnType = Single.class) public Single getOne(RequestData data) { - JsonObject filter = data.filter(); - boolean systemCfg = Boolean.parseBoolean(filter.getString("system_cfg")); + boolean systemCfg = data.filter().parseBoolean("system_cfg"); ITblTransaction transaction = new TblTransaction().fromJson(data.body()); if (Strings.isBlank(transaction.getTransactionId())) { throw new NubeException(ErrorCode.INVALID_ARGUMENT, "Transaction Id cannot be blank"); @@ -50,7 +49,7 @@ private JsonObject removePrevSystemConfig(JsonObject transaction, boolean system @Override public final String servicePath() { - return "/transactions"; + return "/transaction"; } @Override diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java b/core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java new file mode 100644 index 000000000..e353941cb --- /dev/null +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java @@ -0,0 +1,22 @@ +package com.nubeiot.edge.installer.zip; + +import java.io.File; + +import io.vertx.core.Vertx; + +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import net.lingala.zip4j.model.ZipParameters; + +public class ZipUtils { + + void zipFolder(Vertx vertx, String folder) { + try { + final ZipFile zipFile = new ZipFile("filename.zip"); + zipFile.addFolder(new File(folder), new ZipParameters()); + } catch (ZipException e) { + e.printStackTrace(); + } + } + +} diff --git a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java index 7860b99a7..abb0bd17e 100644 --- a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java +++ b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java @@ -13,7 +13,7 @@ default String api() { return "mock.installer." + this.getClass().getSimpleName(); } - default String rootPath() { + default String appPath() { return "/modules"; } diff --git a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java index 2e0a07ce0..1db4dd18d 100644 --- a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java +++ b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java @@ -12,7 +12,7 @@ import com.nubeiot.edge.installer.loader.ModuleTypeRule; import com.nubeiot.edge.installer.mock.MockInstallerService.MockModuleService; import com.nubeiot.edge.installer.mock.MockInstallerService.MockTransactionService; -import com.nubeiot.edge.installer.service.AppDeployer; +import com.nubeiot.edge.installer.service.AppDeployerDefinition; import com.nubeiot.edge.installer.service.InstallerService; import lombok.AllArgsConstructor; @@ -23,7 +23,7 @@ @AllArgsConstructor public class MockInstallerVerticle extends InstallerVerticle { - private final AppDeployer appDeployer; + private final AppDeployerDefinition definition; private String configFile = "mock-installer.json"; @Override @@ -38,8 +38,8 @@ public class MockInstallerVerticle extends InstallerVerticle { } @Override - protected @NonNull AppDeployer appDeployer() { - return appDeployer; + protected @NonNull AppDeployerDefinition appDeployerDefinition() { + return definition; } @Override diff --git a/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosVerticle.java b/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosVerticle.java index 4c89a78a2..3378c0c41 100644 --- a/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosVerticle.java +++ b/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosVerticle.java @@ -7,7 +7,7 @@ import com.nubeiot.edge.installer.InstallerEntityHandler; import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleTypeRule; -import com.nubeiot.edge.installer.service.AppDeployer; +import com.nubeiot.edge.installer.service.AppDeployerDefinition; import com.nubeiot.edge.installer.service.InstallerService; import com.nubeiot.eventbus.edge.installer.InstallerEventModel; @@ -26,9 +26,10 @@ protected Supplier getModuleRuleProvider() { } @Override - protected @NonNull AppDeployer appDeployer() { - return AppDeployer.create(InstallerEventModel.BIOS_DEPLOYMENT, InstallerEventModel.BIOS_DEPLOYMENT_TRACKER, - InstallerEventModel.BIOS_DEPLOYMENT_FINISHER); + protected @NonNull AppDeployerDefinition appDeployerDefinition() { + return AppDeployerDefinition.create(InstallerEventModel.BIOS_DEPLOYMENT, + InstallerEventModel.BIOS_DEPLOYMENT_TRACKER, + InstallerEventModel.BIOS_DEPLOYMENT_FINISHER); } @Override diff --git a/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosInstallerService.java b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosInstallerService.java index 20bf14208..ddb478a5c 100644 --- a/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosInstallerService.java +++ b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosInstallerService.java @@ -8,8 +8,8 @@ default String api() { return "bios.installer." + this.getClass().getSimpleName(); } - default String rootPath() { - return "/modules"; + default String appPath() { + return "/app"; } } diff --git a/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosTransactionByAppService.java b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosTransactionByAppService.java new file mode 100644 index 000000000..a15257fbf --- /dev/null +++ b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosTransactionByAppService.java @@ -0,0 +1,14 @@ +package com.nubeiot.edge.bios.service; + +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.service.TransactionByAppService; + +import lombok.NonNull; + +public final class BiosTransactionByAppService extends TransactionByAppService implements BiosInstallerService { + + public BiosTransactionByAppService(@NonNull InstallerEntityHandler entityHandler) { + super(entityHandler); + } + +} diff --git a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/EdgeServiceInstallerVerticle.java b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/EdgeServiceInstallerVerticle.java index c5819c4b1..df0259382 100644 --- a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/EdgeServiceInstallerVerticle.java +++ b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/EdgeServiceInstallerVerticle.java @@ -6,7 +6,7 @@ import com.nubeiot.edge.installer.InstallerEntityHandler; import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleTypeRule; -import com.nubeiot.edge.installer.service.AppDeployer; +import com.nubeiot.edge.installer.service.AppDeployerDefinition; import com.nubeiot.edge.installer.service.InstallerService; import com.nubeiot.edge.module.installer.service.EdgeInstallerService; import com.nubeiot.eventbus.edge.installer.InstallerEventModel; @@ -26,10 +26,10 @@ protected Supplier getModuleRuleProvider() { } @Override - protected @NonNull AppDeployer appDeployer() { - return AppDeployer.create(InstallerEventModel.SERVICE_DEPLOYMENT, - InstallerEventModel.SERVICE_DEPLOYMENT_TRACKER, - InstallerEventModel.SERVICE_DEPLOYMENT_FINISHER); + protected @NonNull AppDeployerDefinition appDeployerDefinition() { + return AppDeployerDefinition.create(InstallerEventModel.SERVICE_DEPLOYMENT, + InstallerEventModel.SERVICE_DEPLOYMENT_TRACKER, + InstallerEventModel.SERVICE_DEPLOYMENT_FINISHER); } @Override diff --git a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeInstallerService.java b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeInstallerService.java index c8304b1fe..df3219af4 100644 --- a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeInstallerService.java +++ b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeInstallerService.java @@ -9,8 +9,8 @@ default String api() { } @Override - default String rootPath() { - return "/services"; + default String appPath() { + return "/service"; } } diff --git a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByModuleService.java b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByModuleService.java index 0ec6e39a9..53fe25177 100644 --- a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByModuleService.java +++ b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByModuleService.java @@ -1,71 +1,14 @@ package com.nubeiot.edge.module.installer.service; -import java.util.Collection; -import java.util.Collections; - -import io.reactivex.Single; -import io.vertx.core.json.JsonArray; -import io.vertx.core.json.JsonObject; - -import com.nubeiot.core.dto.RequestData; -import com.nubeiot.core.event.EventAction; -import com.nubeiot.core.event.EventContractor; -import com.nubeiot.core.exceptions.NotFoundException; -import com.nubeiot.core.utils.Strings; import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblTransaction; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.service.TransactionByAppService; import lombok.NonNull; -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public final class EdgeTransactionByModuleService implements EdgeInstallerService { - - @NonNull - private final InstallerEntityHandler entityHandler; - - @EventContractor(action = EventAction.GET_LIST, returnType = Single.class) - public Single getList(RequestData data) { - JsonObject filter = data.filter(); - boolean lastTransaction = Boolean.parseBoolean(filter.getString("last")); - ITblTransaction transaction = new TblTransaction().fromJson(data.body()); - if (Strings.isBlank(transaction.getModuleId())) { - throw new IllegalArgumentException("Service id is mandatory"); - } - if (lastTransaction) { - return this.entityHandler.findOneTransactionByModuleId(transaction.getModuleId()) - .map(o -> o.orElseThrow(() -> new NotFoundException( - String.format("Not found service id '%s'", transaction.getModuleId())))) - .map(this::removePrevSystemConfig) - .map(transactions -> new JsonObject().put("transactions", - new JsonArray().add(transactions))); - } - return this.entityHandler.findTransactionByModuleId(transaction.getModuleId()) - .flattenAsObservable(transactions -> transactions) - .flatMapSingle(trans -> Single.just(removePrevSystemConfig(trans.toJson()))) - .toList() - .map(transactions -> new JsonObject().put("transactions", transactions)); - } - private JsonObject removePrevSystemConfig(JsonObject transaction) { - transaction.remove("prev_system_config"); - return transaction; - } - - @Override - public @NonNull Collection getAvailableEvents() { - return Collections.singleton(EventAction.GET_LIST); - } - - @Override - public String servicePath() { - return "/:module_id/transactions"; - } +public final class EdgeTransactionByModuleService extends TransactionByAppService implements EdgeInstallerService { - @Override - public String paramPath() { - return null; + public EdgeTransactionByModuleService(@NonNull InstallerEntityHandler entityHandler) { + super(entityHandler); } } From f5c0a10c06b1b4782b514ee03960880856e2b95d Mon Sep 17 00:00:00 2001 From: zero-88 Date: Sat, 21 Mar 2020 08:11:12 +0700 Subject: [PATCH 2/6] core:archiver Add archiver module --- core/archiver/build.gradle | 6 ++ .../com/nubeiot/core/archiver/AsyncZip.java | 49 ++++++++++ .../nubeiot/core/archiver/AsyncZipFolder.java | 86 ++++++++++++++++++ .../nubeiot/core/archiver/ZipArgument.java | 58 ++++++++++++ .../core/archiver/ZipNotificationHandler.java | 28 ++++++ .../com/nubeiot/core/archiver/ZipOutput.java | 41 +++++++++ .../core/archiver/AsyncZipFolderTest.java | 53 +++++++++++ .../core/archiver/TestZipNotifier.java | 39 ++++++++ .../com/nubeiot/core/utils/DateTimes.java | 91 ++++++++++--------- .../nubeiot/core/utils/ExecutorHelpers.java | 12 +++ core/installer/build.gradle | 2 +- .../nubeiot/edge/installer/zip/ZipUtils.java | 22 ----- settings.gradle | 1 + 13 files changed, 421 insertions(+), 67 deletions(-) create mode 100644 core/archiver/build.gradle create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java create mode 100644 core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java create mode 100644 core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java delete mode 100644 core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java diff --git a/core/archiver/build.gradle b/core/archiver/build.gradle new file mode 100644 index 000000000..cf260aa83 --- /dev/null +++ b/core/archiver/build.gradle @@ -0,0 +1,6 @@ +dependencies { + compile project(':core:base') + compile "net.lingala.zip4j:zip4j:2.5.0" + + testCompile project(":core:base").sourceSets.test.output +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java new file mode 100644 index 000000000..f2e3e5bea --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java @@ -0,0 +1,49 @@ +package com.nubeiot.core.archiver; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.nubeiot.core.component.EventClientProxy; +import com.nubeiot.core.event.EventAction; +import com.nubeiot.core.event.EventMessage; + +import lombok.NonNull; + +public interface AsyncZip extends EventClientProxy { + + String EXT_ZIP_FILE = ".zip"; + + @NonNull + static String ext(@NonNull String fileName) { + return fileName + EXT_ZIP_FILE; + } + + @NonNull + static String ext(@NonNull Path fileName) { + return ext(fileName.toString()); + } + + @NonNull String notifiedAddress(); + + @NonNull ZipArgument zipArgument(); + + default void run(@NonNull String destFolder, @NonNull String tobeZipped) { + run(Paths.get(destFolder), Paths.get(tobeZipped)); + } + + default void run(@NonNull Path destFolder, @NonNull Path tobeZipped) { + run(destFolder.toFile(), tobeZipped.toFile()); + } + + void run(@NonNull File destFolder, @NonNull File tobeZipped); + + default void onSuccess(@NonNull ZipOutput information) { + transporter().publish(notifiedAddress(), EventMessage.success(EventAction.NOTIFY, information.toJson())); + } + + default void onError(@NonNull Throwable throwable) { + transporter().publish(notifiedAddress(), EventMessage.error(EventAction.NOTIFY_ERROR, throwable)); + } + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java new file mode 100644 index 000000000..cf5f37f56 --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java @@ -0,0 +1,86 @@ +package com.nubeiot.core.archiver; + +import java.io.File; +import java.nio.file.Path; + +import io.vertx.core.logging.Logger; +import io.vertx.core.logging.LoggerFactory; + +import com.nubeiot.core.event.EventbusClient; +import com.nubeiot.core.utils.ExecutorHelpers; +import com.nubeiot.core.utils.Strings; + +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.experimental.Accessors; +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import net.lingala.zip4j.progress.ProgressMonitor; +import net.lingala.zip4j.progress.ProgressMonitor.Result; +import net.lingala.zip4j.progress.ProgressMonitor.State; + +@Getter +@Accessors(fluent = true) +@Builder(builderClassName = "Builder") +public final class AsyncZipFolder implements AsyncZip { + + private static final Logger LOGGER = LoggerFactory.getLogger(AsyncZipFolder.class); + + @NonNull + private final EventbusClient transporter; + @NonNull + private final String notifiedAddress; + @NonNull + private final ZipArgument zipArgument; + + @Override + public void run(@NonNull File destFolder, @NonNull File tobeZipped) { + ExecutorHelpers.blocking(transporter.getVertx(), () -> doRun(destFolder, tobeZipped)); + } + + private void doRun(@NonNull File destFolder, @NonNull File tobeZipped) { + try { + final ZipFile zipFile = createZipFile(destFolder, tobeZipped); + final ProgressMonitor progressMonitor = zipFile.getProgressMonitor(); + zipFile.addFolder(tobeZipped, zipArgument().zipParameters()); + transporter.getVertx() + .setPeriodic(zipArgument().watcherDelayInMilli(), + id -> watch(id, progressMonitor, zipFile.getFile())); + } catch (ZipException e) { + onError(e); + } + } + + private ZipFile createZipFile(@NonNull File destinationFolder, @NonNull File origin) { + final String destination = destinationFolder.toPath().resolve(zipArgument().getZipFileName(origin)).toString(); + final String password = zipArgument().password(); + final ZipFile zipFile = new ZipFile(AsyncZip.ext(destination), + Strings.isBlank(password) ? null : password.toCharArray()); + zipFile.setRunInThread(true); + return zipFile; + } + + private void watch(long timerId, @NonNull ProgressMonitor progressMonitor, @NonNull File archiveFile) { + final Path path = archiveFile.toPath(); + if (progressMonitor.getState().equals(State.BUSY)) { + LOGGER.info("Zipping: {} | Progress: {}% | Current file: {} | Current task: {}", path, + progressMonitor.getPercentDone(), progressMonitor.getFileName(), + progressMonitor.getCurrentTask()); + return; + } + transporter.getVertx().cancelTimer(timerId); + final Result result = progressMonitor.getResult(); + if (result == Result.SUCCESS) { + onSuccess(ZipOutput.builder() + .originFile(progressMonitor.getFileName()) + .zipFile(path.toString()) + .size(archiveFile.length()) + .lastModified(archiveFile.lastModified()) + .build()); + return; + } + onError(progressMonitor.getException()); + } + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java new file mode 100644 index 000000000..2c2b376a3 --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java @@ -0,0 +1,58 @@ +package com.nubeiot.core.archiver; + +import java.io.File; +import java.nio.file.Path; + +import com.nubeiot.core.dto.JsonData; +import com.nubeiot.core.utils.DateTimes; +import com.nubeiot.core.utils.Strings; + +import lombok.Builder; +import lombok.Getter; +import lombok.NonNull; +import lombok.experimental.Accessors; +import net.lingala.zip4j.model.ZipParameters; + +@Getter +@Accessors(fluent = true) +@Builder(builderClassName = "Builder") +public final class ZipArgument implements JsonData { + + private final boolean appendTimestamp; + private final String overriddenDestFileName; + private final String password; + private final long watcherDelayInMilli; + @NonNull + private final ZipParameters zipParameters; + + public static ZipArgument createDefault() { + return ZipArgument.builder() + .appendTimestamp(true) + .watcherDelayInMilli(100) + .zipParameters(defaultZipParameters()) + .build(); + } + + public static ZipArgument noTimestamp() { + return ZipArgument.builder() + .appendTimestamp(false) + .watcherDelayInMilli(100) + .zipParameters(defaultZipParameters()) + .build(); + } + + static @NonNull ZipParameters defaultZipParameters() { + ZipParameters parameters = new ZipParameters(); + parameters.setIncludeRootFolder(true); + return parameters; + } + + public String getZipFileName(@NonNull File toZippedFile) { + if (Strings.isNotBlank(overriddenDestFileName)) { + return overriddenDestFileName; + } + final Path fileName = toZippedFile.toPath().getFileName(); + return appendTimestamp ? fileName.toString() + "-" + DateTimes.nowMilli() : fileName.toString(); + } + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java new file mode 100644 index 000000000..0b75ea1dd --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java @@ -0,0 +1,28 @@ +package com.nubeiot.core.archiver; + +import java.util.Arrays; +import java.util.Collection; + +import io.vertx.core.json.JsonObject; + +import com.nubeiot.core.event.EventAction; +import com.nubeiot.core.event.EventContractor; +import com.nubeiot.core.event.EventListener; +import com.nubeiot.core.exceptions.ErrorData; + +import lombok.NonNull; + +public interface ZipNotificationHandler extends EventListener { + + @Override + default @NonNull Collection getAvailableEvents() { + return Arrays.asList(EventAction.NOTIFY, EventAction.NOTIFY_ERROR); + } + + @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) + boolean success(@NonNull JsonObject requestData); + + @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) + boolean error(@NonNull ErrorData error); + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java new file mode 100644 index 000000000..0ef1f63b6 --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java @@ -0,0 +1,41 @@ +package com.nubeiot.core.archiver; + +import java.time.OffsetDateTime; + +import com.nubeiot.core.dto.JsonData; +import com.nubeiot.core.utils.DateTimes; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder(builderClassName = "Builder") +public final class ZipOutput implements JsonData { + + private final String originFile; + private final String zipFile; + private final long size; + private final OffsetDateTime lastModified; + + ZipOutput(String originFile, String zipFile, long size, OffsetDateTime lastModified) { + this.originFile = originFile; + this.zipFile = zipFile; + this.size = size; + this.lastModified = lastModified; + } + + public static class Builder { + + public Builder lastModified(OffsetDateTime lastModified) { + this.lastModified = lastModified; + return this; + } + + public Builder lastModified(long lastModified) { + this.lastModified = DateTimes.from(lastModified); + return this; + } + + } + +} diff --git a/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java b/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java new file mode 100644 index 000000000..914afcc97 --- /dev/null +++ b/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java @@ -0,0 +1,53 @@ +package com.nubeiot.core.archiver; + +import java.io.File; +import java.io.IOException; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.junit.runner.RunWith; + +import io.vertx.core.Vertx; +import io.vertx.core.eventbus.DeliveryOptions; +import io.vertx.ext.unit.TestContext; +import io.vertx.ext.unit.junit.VertxUnitRunner; + +import com.nubeiot.core.component.EventClientProxy; +import com.nubeiot.core.event.EventbusClient; + +@RunWith(VertxUnitRunner.class) +public class AsyncZipFolderTest { + + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + private EventbusClient client; + + @Before + public void setup() { + final Vertx vertx = Vertx.vertx(); + client = EventClientProxy.create(vertx, new DeliveryOptions()).transporter(); + } + + @Test + public void test(TestContext context) throws IOException { + final File dest = folder.newFolder("destination"); + final File origin = folder.newFolder("origin"); + folder.newFile(folder.getRoot().toPath().relativize(origin.toPath().resolve("abc.txt")).toString()); + final ZipOutput expected = ZipOutput.builder() + .originFile(origin.toString()) + .zipFile(AsyncZip.ext(dest.toPath().resolve(origin.toPath().getFileName()))) + .size(216) + .build(); + final TestZipNotifier notifier = new TestZipNotifier(context, context.async(), expected.toJson()); + client.register("xxx", notifier); + AsyncZipFolder.builder() + .transporter(client) + .notifiedAddress("xxx") + .zipArgument(ZipArgument.noTimestamp()) + .build() + .run(dest, origin); + } + +} diff --git a/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java new file mode 100644 index 000000000..a1a5396e6 --- /dev/null +++ b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java @@ -0,0 +1,39 @@ +package com.nubeiot.core.archiver; + +import io.vertx.core.json.JsonObject; +import io.vertx.ext.unit.Async; +import io.vertx.ext.unit.TestContext; + +import com.nubeiot.core.TestHelper.JsonHelper; +import com.nubeiot.core.event.EventAction; +import com.nubeiot.core.event.EventContractor; +import com.nubeiot.core.exceptions.ErrorData; + +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public final class TestZipNotifier implements ZipNotificationHandler { + + @NonNull + private final TestContext testContext; + @NonNull + private final Async async; + @NonNull + private final JsonObject expected; + + @Override + @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) + public boolean success(@NonNull JsonObject response) { + JsonHelper.assertJson(testContext, async, expected, response, JsonHelper.ignore("lastModified")); + return true; + } + + @Override + @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) + public boolean error(@NonNull ErrorData error) { + JsonHelper.assertJson(testContext, async, expected, error.toJson()); + return true; + } + +} diff --git a/core/base/src/main/java/com/nubeiot/core/utils/DateTimes.java b/core/base/src/main/java/com/nubeiot/core/utils/DateTimes.java index 0654c6d9d..aa73f43e6 100644 --- a/core/base/src/main/java/com/nubeiot/core/utils/DateTimes.java +++ b/core/base/src/main/java/com/nubeiot/core/utils/DateTimes.java @@ -30,6 +30,53 @@ public final class DateTimes { private static final Logger logger = LoggerFactory.getLogger(DateTimes.class); + public static LocalDateTime nowUTC() { + return fromUTC(Instant.now()); + } + + public static LocalDateTime fromUTC(@NonNull Instant instant) { + return LocalDateTime.ofInstant(instant, ZoneOffset.UTC); + } + + public static ZonedDateTime toUTC(@NonNull Date date) { + return DateTimes.toUTC(date.toInstant()); + } + + public static ZonedDateTime toUTC(@NonNull Instant date) { + return DateTimes.toUTC(date.atZone(ZoneId.systemDefault())); + } + + public static ZonedDateTime toUTC(@NonNull LocalDateTime time) { + return DateTimes.toUTC(time, ZoneId.systemDefault()); + } + + public static ZonedDateTime toUTC(@NonNull LocalDateTime time, @NonNull ZoneId zoneId) { + return DateTimes.toUTC(time.atZone(zoneId)); + } + + public static ZonedDateTime toUTC(@NonNull ZonedDateTime dateTime) { + return DateTimes.toZone(dateTime, ZoneOffset.UTC); + } + + public static ZonedDateTime toZone(@NonNull ZonedDateTime dateTime, @NonNull ZoneId toZone) { + return dateTime.withZoneSameInstant(toZone); + } + + public static OffsetDateTime now() { + return from(Instant.now()); + } + + public static long nowMilli() { + return Instant.now().toEpochMilli(); + } + + public static OffsetDateTime from(@NonNull Instant instant) { + return OffsetDateTime.ofInstant(instant, ZoneOffset.UTC); + } + + public static OffsetDateTime from(long milliseconds) { + return from(Instant.ofEpochMilli(milliseconds)); + } /** * Utilities class for parsing {@code date/time/datetime} in {@code iso8601} to appropriate {@code java data type} @@ -110,48 +157,4 @@ public static JsonObject format(@NonNull Date date, TimeZone timeZone) { } - public static LocalDateTime nowUTC() { - return fromUTC(Instant.now()); - } - - public static LocalDateTime fromUTC(@NonNull Instant instant) { - return LocalDateTime.ofInstant(instant, ZoneOffset.UTC); - } - - public static ZonedDateTime toUTC(@NonNull Date date) { - return DateTimes.toUTC(date.toInstant()); - } - - public static ZonedDateTime toUTC(@NonNull Instant date) { - return DateTimes.toUTC(date.atZone(ZoneId.systemDefault())); - } - - public static ZonedDateTime toUTC(@NonNull LocalDateTime time) { - return DateTimes.toUTC(time, ZoneId.systemDefault()); - } - - public static ZonedDateTime toUTC(@NonNull LocalDateTime time, @NonNull ZoneId zoneId) { - return DateTimes.toUTC(time.atZone(zoneId)); - } - - public static ZonedDateTime toUTC(@NonNull ZonedDateTime dateTime) { - return DateTimes.toZone(dateTime, ZoneOffset.UTC); - } - - public static ZonedDateTime toZone(@NonNull ZonedDateTime dateTime, @NonNull ZoneId toZone) { - return dateTime.withZoneSameInstant(toZone); - } - - public static OffsetDateTime now() { - return from(Instant.now()); - } - - public static long nowMilli() { - return Instant.now().toEpochMilli(); - } - - public static OffsetDateTime from(@NonNull Instant instant) { - return OffsetDateTime.ofInstant(instant, ZoneOffset.UTC); - } - } diff --git a/core/base/src/main/java/com/nubeiot/core/utils/ExecutorHelpers.java b/core/base/src/main/java/com/nubeiot/core/utils/ExecutorHelpers.java index 56efdce42..41fb10091 100644 --- a/core/base/src/main/java/com/nubeiot/core/utils/ExecutorHelpers.java +++ b/core/base/src/main/java/com/nubeiot/core/utils/ExecutorHelpers.java @@ -16,6 +16,18 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public final class ExecutorHelpers { + public static void blocking(@NonNull Vertx vertx, @NonNull Runnable callable) { + vertx.executeBlocking(future -> { + try { + callable.run(); + } catch (RuntimeException e) { + future.fail(e); + } finally { + future.complete(); + } + }, res -> {}); + } + public static Single blocking(@NonNull Vertx vertx, @NonNull Callable callable) { return Single.fromCallable(callable).subscribeOn(RxHelper.blockingScheduler(vertx)); } diff --git a/core/installer/build.gradle b/core/installer/build.gradle index 535f961fd..ee5f9f96e 100644 --- a/core/installer/build.gradle +++ b/core/installer/build.gradle @@ -10,10 +10,10 @@ dependencies { compile project(':core:auth') compile project(':core:sql') compile project(':core:micro') + compile project(':core:archiver') compile project(':eventbus:edge') compile project.deps.database.h2 compile "io.vertx:vertx-maven-service-factory:$project.versions.vertx" - compile "net.lingala.zip4j:zip4j:2.5.0" testCompile project(":core:base").sourceSets.test.output } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java b/core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java deleted file mode 100644 index e353941cb..000000000 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/zip/ZipUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.nubeiot.edge.installer.zip; - -import java.io.File; - -import io.vertx.core.Vertx; - -import net.lingala.zip4j.ZipFile; -import net.lingala.zip4j.exception.ZipException; -import net.lingala.zip4j.model.ZipParameters; - -public class ZipUtils { - - void zipFolder(Vertx vertx, String folder) { - try { - final ZipFile zipFile = new ZipFile("filename.zip"); - zipFile.addFolder(new File(folder), new ZipParameters()); - } catch (ZipException e) { - e.printStackTrace(); - } - } - -} diff --git a/settings.gradle b/settings.gradle index 39b8762e2..8bd2ec2c7 100644 --- a/settings.gradle +++ b/settings.gradle @@ -14,6 +14,7 @@ include ':core:httpclient' include ':core:httpserver' include ':core:protocol' include ':core:auth' +include ':core:archiver' include ':core:kafka' include ':core:scheduler' include ':core:scheduler:model' From 8b68a92b5936c6c1fb0243a1fedf48df03ca011b Mon Sep 17 00:00:00 2001 From: zero-88 Date: Sat, 21 Mar 2020 16:21:32 +0700 Subject: [PATCH 3/6] core:archiver: Update AsyncZip JavaAPI core:installer: Add BackupService --- .../com/nubeiot/core/archiver/AsyncZip.java | 12 +- .../nubeiot/core/archiver/AsyncZipFolder.java | 28 ++--- .../nubeiot/core/archiver/ZipArgument.java | 11 +- .../core/archiver/ZipNotificationHandler.java | 4 +- .../com/nubeiot/core/archiver/ZipOutput.java | 23 ++-- .../core/archiver/AsyncZipFolderTest.java | 3 +- .../core/archiver/TestZipNotifier.java | 4 +- .../com/nubeiot/core/event/EventAction.java | 1 + .../edge/installer/service/BackupService.java | 105 +++++++++++++++++- .../installer/service/InstallerApiIndex.java | 8 +- .../installer/service/InstallerService.java | 25 +++-- .../edge/installer/service/ModuleService.java | 3 +- .../service/TransactionByAppService.java | 30 ++--- .../installer/service/TransactionService.java | 40 +++---- 14 files changed, 210 insertions(+), 87 deletions(-) diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java index f2e3e5bea..bac413e87 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java @@ -26,17 +26,15 @@ static String ext(@NonNull Path fileName) { @NonNull String notifiedAddress(); - @NonNull ZipArgument zipArgument(); - - default void run(@NonNull String destFolder, @NonNull String tobeZipped) { - run(Paths.get(destFolder), Paths.get(tobeZipped)); + default void run(@NonNull ZipArgument argument, @NonNull String destFolder, @NonNull String tobeZipped) { + run(argument, Paths.get(destFolder), Paths.get(tobeZipped)); } - default void run(@NonNull Path destFolder, @NonNull Path tobeZipped) { - run(destFolder.toFile(), tobeZipped.toFile()); + default void run(@NonNull ZipArgument argument, @NonNull Path destFolder, @NonNull Path tobeZipped) { + run(argument, destFolder.toFile(), tobeZipped.toFile()); } - void run(@NonNull File destFolder, @NonNull File tobeZipped); + void run(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped); default void onSuccess(@NonNull ZipOutput information) { transporter().publish(notifiedAddress(), EventMessage.success(EventAction.NOTIFY, information.toJson())); diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java index cf5f37f56..d42a4856b 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java @@ -31,37 +31,36 @@ public final class AsyncZipFolder implements AsyncZip { private final EventbusClient transporter; @NonNull private final String notifiedAddress; - @NonNull - private final ZipArgument zipArgument; @Override - public void run(@NonNull File destFolder, @NonNull File tobeZipped) { - ExecutorHelpers.blocking(transporter.getVertx(), () -> doRun(destFolder, tobeZipped)); + public void run(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped) { + ExecutorHelpers.blocking(transporter.getVertx(), () -> doRun(argument, destFolder, tobeZipped)); } - private void doRun(@NonNull File destFolder, @NonNull File tobeZipped) { + private void doRun(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped) { try { - final ZipFile zipFile = createZipFile(destFolder, tobeZipped); + final ZipFile zipFile = createZipFile(argument, destFolder, tobeZipped); final ProgressMonitor progressMonitor = zipFile.getProgressMonitor(); - zipFile.addFolder(tobeZipped, zipArgument().zipParameters()); + zipFile.addFolder(tobeZipped, argument.zipParameters()); transporter.getVertx() - .setPeriodic(zipArgument().watcherDelayInMilli(), - id -> watch(id, progressMonitor, zipFile.getFile())); + .setPeriodic(argument.watcherDelayInMilli(), + id -> watch(id, argument, progressMonitor, zipFile.getFile())); } catch (ZipException e) { onError(e); } } - private ZipFile createZipFile(@NonNull File destinationFolder, @NonNull File origin) { - final String destination = destinationFolder.toPath().resolve(zipArgument().getZipFileName(origin)).toString(); - final String password = zipArgument().password(); - final ZipFile zipFile = new ZipFile(AsyncZip.ext(destination), + private ZipFile createZipFile(@NonNull ZipArgument argument, @NonNull File destination, @NonNull File origin) { + final String dest = destination.toPath().resolve(argument.getZipFileName(origin)).toString(); + final String password = argument.password(); + final ZipFile zipFile = new ZipFile(AsyncZip.ext(dest), Strings.isBlank(password) ? null : password.toCharArray()); zipFile.setRunInThread(true); return zipFile; } - private void watch(long timerId, @NonNull ProgressMonitor progressMonitor, @NonNull File archiveFile) { + private void watch(long timerId, @NonNull ZipArgument argument, @NonNull ProgressMonitor progressMonitor, + @NonNull File archiveFile) { final Path path = archiveFile.toPath(); if (progressMonitor.getState().equals(State.BUSY)) { LOGGER.info("Zipping: {} | Progress: {}% | Current file: {} | Current task: {}", path, @@ -77,6 +76,7 @@ private void watch(long timerId, @NonNull ProgressMonitor progressMonitor, @NonN .zipFile(path.toString()) .size(archiveFile.length()) .lastModified(archiveFile.lastModified()) + .trackingInfo(argument.trackingInfo()) .build()); return; } diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java index 2c2b376a3..67c355bbf 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java @@ -3,6 +3,8 @@ import java.io.File; import java.nio.file.Path; +import io.vertx.core.json.JsonObject; + import com.nubeiot.core.dto.JsonData; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.core.utils.Strings; @@ -18,6 +20,7 @@ @Builder(builderClassName = "Builder") public final class ZipArgument implements JsonData { + private final JsonObject trackingInfo; private final boolean appendTimestamp; private final String overriddenDestFileName; private final String password; @@ -25,8 +28,9 @@ public final class ZipArgument implements JsonData { @NonNull private final ZipParameters zipParameters; - public static ZipArgument createDefault() { + public static ZipArgument createDefault(JsonObject trackingInfo) { return ZipArgument.builder() + .trackingInfo(trackingInfo) .appendTimestamp(true) .watcherDelayInMilli(100) .zipParameters(defaultZipParameters()) @@ -34,7 +38,12 @@ public static ZipArgument createDefault() { } public static ZipArgument noTimestamp() { + return noTimestamp(null); + } + + public static ZipArgument noTimestamp(JsonObject trackingInfo) { return ZipArgument.builder() + .trackingInfo(trackingInfo) .appendTimestamp(false) .watcherDelayInMilli(100) .zipParameters(defaultZipParameters()) diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java index 0b75ea1dd..9c547bb03 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java @@ -3,8 +3,6 @@ import java.util.Arrays; import java.util.Collection; -import io.vertx.core.json.JsonObject; - import com.nubeiot.core.event.EventAction; import com.nubeiot.core.event.EventContractor; import com.nubeiot.core.event.EventListener; @@ -20,7 +18,7 @@ public interface ZipNotificationHandler extends EventListener { } @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) - boolean success(@NonNull JsonObject requestData); + boolean success(@NonNull ZipOutput result); @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) boolean error(@NonNull ErrorData error); diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java index 0ef1f63b6..09f157fd5 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java @@ -2,6 +2,11 @@ import java.time.OffsetDateTime; +import io.vertx.core.json.JsonObject; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; import com.nubeiot.core.dto.JsonData; import com.nubeiot.core.utils.DateTimes; @@ -10,29 +15,27 @@ @Getter @Builder(builderClassName = "Builder") +@JsonDeserialize(builder = ZipOutput.Builder.class) public final class ZipOutput implements JsonData { + private final JsonObject trackingInfo; private final String originFile; private final String zipFile; private final long size; private final OffsetDateTime lastModified; - ZipOutput(String originFile, String zipFile, long size, OffsetDateTime lastModified) { - this.originFile = originFile; - this.zipFile = zipFile; - this.size = size; - this.lastModified = lastModified; - } + @JsonPOJOBuilder(withPrefix = "") public static class Builder { - public Builder lastModified(OffsetDateTime lastModified) { - this.lastModified = lastModified; + public Builder lastModified(long lastModified) { + this.lastModified = DateTimes.from(lastModified); return this; } - public Builder lastModified(long lastModified) { - this.lastModified = DateTimes.from(lastModified); + @JsonProperty("lastModified") + public Builder lastModified(OffsetDateTime lastModified) { + this.lastModified = lastModified; return this; } diff --git a/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java b/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java index 914afcc97..4824fa02c 100644 --- a/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java +++ b/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java @@ -45,9 +45,8 @@ public void test(TestContext context) throws IOException { AsyncZipFolder.builder() .transporter(client) .notifiedAddress("xxx") - .zipArgument(ZipArgument.noTimestamp()) .build() - .run(dest, origin); + .run(ZipArgument.noTimestamp(), dest, origin); } } diff --git a/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java index a1a5396e6..127c412fd 100644 --- a/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java +++ b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java @@ -24,8 +24,8 @@ public final class TestZipNotifier implements ZipNotificationHandler { @Override @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) - public boolean success(@NonNull JsonObject response) { - JsonHelper.assertJson(testContext, async, expected, response, JsonHelper.ignore("lastModified")); + public boolean success(ZipOutput response) { + JsonHelper.assertJson(testContext, async, expected, response.toJson(), JsonHelper.ignore("lastModified")); return true; } diff --git a/core/base/src/main/java/com/nubeiot/core/event/EventAction.java b/core/base/src/main/java/com/nubeiot/core/event/EventAction.java index a6366be0e..173a22603 100644 --- a/core/base/src/main/java/com/nubeiot/core/event/EventAction.java +++ b/core/base/src/main/java/com/nubeiot/core/event/EventAction.java @@ -22,6 +22,7 @@ public enum EventAction implements Serializable { GET_ONE, GET_LIST, CREATE_OR_UPDATE, + BACKUP, RETURN, MIGRATE, UNKNOWN, diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java index 23c058f20..1e0767c43 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java @@ -1,8 +1,111 @@ package com.nubeiot.edge.installer.service; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Collection; +import java.util.Collections; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import io.reactivex.Single; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.JsonObject; + +import com.nubeiot.core.NubeConfig; +import com.nubeiot.core.archiver.AsyncZipFolder; +import com.nubeiot.core.archiver.ZipArgument; +import com.nubeiot.core.archiver.ZipNotificationHandler; +import com.nubeiot.core.archiver.ZipOutput; +import com.nubeiot.core.dto.RequestData; +import com.nubeiot.core.event.EventAction; +import com.nubeiot.core.event.EventContractor; +import com.nubeiot.core.exceptions.ErrorData; +import com.nubeiot.core.http.base.event.ActionMethodMapping; +import com.nubeiot.core.utils.Strings; +import com.nubeiot.core.utils.UUID64; +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.model.tables.daos.TblModuleDao; +import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.service.InstallerApiIndex.ApplicationMetadata; + +import lombok.AccessLevel; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; + /** * Represents Backup service. * * @since 1.0.0 */ -public interface BackupService extends InstallerService {} +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +public abstract class BackupService implements InstallerService, ZipNotificationHandler { + + @NonNull + private final InstallerEntityHandler entityHandler; + + protected abstract @NonNull Path backupFolder(); + + @Override + public final String servicePath() { + return "/:app_id/backup"; + } + + @Override + public final String paramPath() { + return null; + } + + @Override + public final ActionMethodMapping methodMapping() { + return ActionMethodMapping.create(Collections.singletonMap(EventAction.BACKUP, HttpMethod.POST)); + } + + @Override + public final @NonNull Collection getAvailableEvents() { + return Stream.of(ZipNotificationHandler.super.getAvailableEvents(), Collections.singleton(EventAction.BACKUP)) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + } + + @EventContractor(action = EventAction.BACKUP, returnType = Single.class) + public final Single backup(@NonNull RequestData data) { + final String appId = Strings.requireNotBlank(data.body().getString("app_id"), "Missing application id"); + return entityHandler.dao(TblModuleDao.class) + .findOneById(appId) + .filter(Optional::isPresent) + .map(Optional::get) + .switchIfEmpty(Single.error(ApplicationMetadata.INSTANCE.notFound(appId))) + .map(this::createBackupRecord) + .doOnSuccess(this::doBackup); + } + + @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) + public final boolean success(@NonNull ZipOutput result) { + return true; + } + + @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) + public final boolean error(@NonNull ErrorData error) { + return true; + } + + protected @NonNull JsonObject createBackupRecord(@NonNull TblModule app) { + return new JsonObject().put("backup_id", UUID64.random()) + .put("deploy_location", app.getDeployLocation()) + .put("data_dir", app.getSystemConfig().getString(NubeConfig.DATA_DIR)); + } + + protected void doBackup(@NonNull JsonObject object) { + final JsonObject trackingInfo = new JsonObject().put("backup_id", object.getString("backup_id")); + final AsyncZipFolder zipper = AsyncZipFolder.builder() + .notifiedAddress(address()) + .transporter(entityHandler.eventClient()) + .build(); + zipper.run(ZipArgument.createDefault(trackingInfo.put("type", "deploy_location")), backupFolder(), + Paths.get(object.getString("deploy_location"))); + zipper.run(ZipArgument.createDefault(trackingInfo.put("type", "data_dir")), backupFolder(), + Paths.get(object.getString(NubeConfig.DATA_DIR))); + } + +} diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java index 4d7f12348..29a0923ca 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java @@ -35,9 +35,9 @@ default List index() { } @NoArgsConstructor(access = AccessLevel.PRIVATE) - final class AppServiceMetadata implements StringKeyEntity { + final class ApplicationMetadata implements StringKeyEntity { - public static final AppServiceMetadata INSTANCE = new AppServiceMetadata(); + public static final ApplicationMetadata INSTANCE = new ApplicationMetadata(); @Override public @NonNull com.nubeiot.edge.installer.model.tables.TblModule table() { @@ -55,10 +55,10 @@ final class AppServiceMetadata implements StringKeyEntity> orderFields() { diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java index 525d189df..ae62347f9 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerService.java @@ -1,5 +1,6 @@ package com.nubeiot.edge.installer.service; +import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.Objects; @@ -38,13 +39,6 @@ static Set createServices(InstallerEntityHandler .collect(Collectors.toSet()); } - @Override - default Set definitions() { - final String fullPath = Urls.combinePath(rootPath(), appPath(), servicePath()); - return Collections.singleton( - EventMethodDefinition.create(fullPath, paramPath(), ActionMethodMapping.byCRUD(getAvailableEvents()))); - } - /** * Defines Root path. * @@ -79,4 +73,21 @@ default String rootPath() { */ String paramPath(); + @Override + default Set definitions() { + final String fullPath = Urls.combinePath(rootPath(), appPath(), servicePath()); + return Collections.singleton(EventMethodDefinition.create(fullPath, paramPath(), methodMapping())); + } + + /** + * Creates Event action Method mapping. + * + * @return the action method mapping. Defaults: {@link ActionMethodMapping#byCRUD(Collection)} + * @see ActionMethodMapping + * @since 1.0.0 + */ + default ActionMethodMapping methodMapping() { + return ActionMethodMapping.byCRUD(getAvailableEvents()); + } + } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/ModuleService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/ModuleService.java index 2272aed4e..761498f43 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/ModuleService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/ModuleService.java @@ -60,7 +60,8 @@ public Single getOne(RequestData data) { if (Strings.isBlank(serviceId)) { throw new IllegalArgumentException("Service id is mandatory"); } - return entityHandler.dao(TblModuleDao.class).findOneById(serviceId) + return entityHandler.dao(TblModuleDao.class) + .findOneById(serviceId) .map(o -> o.map(this::removeCredentialsInAppConfig)) .filter(Optional::isPresent) .map(Optional::get) diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java index 9df671087..06250d609 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java @@ -26,6 +26,21 @@ public abstract class TransactionByAppService implements InstallerService { @NonNull private final InstallerEntityHandler entityHandler; + @Override + public @NonNull Collection getAvailableEvents() { + return Collections.singleton(EventAction.GET_LIST); + } + + @Override + public String servicePath() { + return "/:module_id/transaction"; + } + + @Override + public String paramPath() { + return null; + } + @EventContractor(action = EventAction.GET_LIST, returnType = Single.class) public Single getList(RequestData data) { final ITblTransaction transaction = new TblTransaction().fromJson(data.body()); @@ -52,19 +67,4 @@ private JsonObject removePrevSystemConfig(JsonObject transaction) { return transaction; } - @Override - public @NonNull Collection getAvailableEvents() { - return Collections.singleton(EventAction.GET_LIST); - } - - @Override - public String servicePath() { - return "/:module_id/transaction"; - } - - @Override - public String paramPath() { - return null; - } - } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java index fc3d106f2..8c19382ff 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java @@ -27,26 +27,6 @@ public abstract class TransactionService implements InstallerService { @NonNull private final InstallerEntityHandler entityHandler; - @EventContractor(action = EventAction.GET_ONE, returnType = Single.class) - public Single getOne(RequestData data) { - boolean systemCfg = data.filter().parseBoolean("system_cfg"); - ITblTransaction transaction = new TblTransaction().fromJson(data.body()); - if (Strings.isBlank(transaction.getTransactionId())) { - throw new NubeException(ErrorCode.INVALID_ARGUMENT, "Transaction Id cannot be blank"); - } - return this.entityHandler.findTransactionById(transaction.getTransactionId()) - .map(o -> o.orElseThrow(() -> new NotFoundException( - Strings.format("Not found transaction id '{0}'", transaction.getTransactionId())))) - .map(trans -> removePrevSystemConfig(trans, systemCfg)); - } - - private JsonObject removePrevSystemConfig(JsonObject transaction, boolean systemCfg) { - if (!systemCfg) { - transaction.remove("prev_system_config"); - } - return transaction; - } - @Override public final String servicePath() { return "/transaction"; @@ -62,4 +42,24 @@ public final String paramPath() { return Collections.singletonList(EventAction.GET_ONE); } + @EventContractor(action = EventAction.GET_ONE, returnType = Single.class) + public Single getOne(RequestData data) { + final boolean includeSystemCfg = data.filter().parseBoolean("system_cfg"); + final ITblTransaction transaction = new TblTransaction().fromJson(data.body()); + if (Strings.isBlank(transaction.getTransactionId())) { + throw new NubeException(ErrorCode.INVALID_ARGUMENT, "Transaction Id cannot be blank"); + } + return this.entityHandler.findTransactionById(transaction.getTransactionId()) + .map(o -> o.orElseThrow(() -> new NotFoundException( + Strings.format("Not found transaction id '{0}'", transaction.getTransactionId())))) + .map(trans -> removePrevSystemConfig(trans, includeSystemCfg)); + } + + private JsonObject removePrevSystemConfig(JsonObject transaction, boolean includeSystemCfg) { + if (!includeSystemCfg) { + transaction.remove("prev_system_config"); + } + return transaction; + } + } From 524351ae4a404dcd5882191fd32c9c190ab9dbe7 Mon Sep 17 00:00:00 2001 From: zero-88 Date: Sun, 22 Mar 2020 21:08:05 +0700 Subject: [PATCH 4/6] core:installer: Update Database schema - Rename tbl_module -> application, tbl_transaction -> deploy_transaction, tbl_remove_history -> application_history - Add application_backup --- .../core/archiver/TestZipNotifier.java | 2 +- .../com/nubeiot/core/event/EventMessage.java | 12 +- .../nubeiot/core/exceptions/ErrorData.java | 2 +- .../installer/InstallerEntityHandler.java | 79 +++---- .../installer/InstallerSchemaHandler.java | 2 +- .../edge/installer/loader/ModuleTypeRule.java | 26 +-- .../installer/search/LocalServiceSearch.java | 28 +-- .../service/AppDeploymentTracker.java | 54 ++--- .../service/AppDeploymentWorkflow.java | 98 ++++----- ...leService.java => ApplicationService.java} | 34 +-- .../installer/service/BackupByAppService.java | 160 ++++++++++++++ .../edge/installer/service/BackupService.java | 111 ---------- .../installer/service/InstallerApiIndex.java | 107 +++++++--- .../service/TransactionByAppService.java | 16 +- .../installer/service/TransactionService.java | 17 +- .../src/main/resources/ddl/01_ddl.sql | 38 ++-- .../installer/mock/MockInstallerService.java | 8 +- .../installer/mock/MockInstallerVerticle.java | 4 +- .../service/MockDeploymentService.java | 2 +- .../service/MockFinisherService.java | 2 +- .../com/nubeiot/core/sql/SchemaHandler.java | 4 +- .../edge/bios/EdgeBiosEntityHandler.java | 10 +- .../bios/service/BiosApplicationService.java | 12 ++ .../bios/service/BiosBackupByAppService.java | 14 ++ .../edge/bios/service/BiosModuleService.java | 12 -- .../edge/bios/BaseInstallerVerticleTest.java | 40 ++-- .../nubeiot/edge/bios/HandlerDeleteTest.java | 63 +++--- .../edge/bios/HandlerDeployFailedTest.java | 18 +- .../edge/bios/HandlerUpdateAndPatchTest.java | 18 +- .../edge/bios/ServiceNameDuplicationTest.java | 18 +- .../edge/bios/loader/DeploymentAsserter.java | 4 +- .../handler/EnabledModuleInitData.java | 20 +- .../handler/InvalidModulesInitData.java | 197 +++++++++--------- .../handler/MockInitDataEntityHandler.java | 16 +- ...PendingModuleWithCreateActionInitData.java | 32 +-- .../PendingModuleWithInitActionInitData.java | 32 +-- .../PendingModuleWithPatchActionInitData.java | 50 ++--- ...dingModuleWithTwoTransactionsInitData.java | 58 +++--- ...PendingModuleWithUpdateActionInitData.java | 50 ++--- .../edge/bios/timeout/HandlerTimeoutTest.java | 18 +- .../bacnet/AbstractBACnetVerticle.java | 4 +- .../edge/connector/bacnet/BACnetDevice.java | 4 +- .../service/EdgeApplicationService.java | 14 ++ .../service/EdgeBackupByAppService.java | 14 ++ .../installer/service/EdgeModuleService.java | 14 -- ....java => EdgeTransactionByAppService.java} | 4 +- 46 files changed, 843 insertions(+), 699 deletions(-) rename core/installer/src/main/java/com/nubeiot/edge/installer/service/{ModuleService.java => ApplicationService.java} (83%) create mode 100644 core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java delete mode 100644 core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java create mode 100644 edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosApplicationService.java create mode 100644 edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosBackupByAppService.java delete mode 100644 edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosModuleService.java create mode 100644 edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeApplicationService.java create mode 100644 edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeBackupByAppService.java delete mode 100644 edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeModuleService.java rename edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/{EdgeTransactionByModuleService.java => EdgeTransactionByAppService.java} (53%) diff --git a/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java index 127c412fd..39ef27291 100644 --- a/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java +++ b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java @@ -24,7 +24,7 @@ public final class TestZipNotifier implements ZipNotificationHandler { @Override @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) - public boolean success(ZipOutput response) { + public boolean success(@NonNull ZipOutput response) { JsonHelper.assertJson(testContext, async, expected, response.toJson(), JsonHelper.ignore("lastModified")); return true; } diff --git a/core/base/src/main/java/com/nubeiot/core/event/EventMessage.java b/core/base/src/main/java/com/nubeiot/core/event/EventMessage.java index 2d89d3eaa..78926ef73 100644 --- a/core/base/src/main/java/com/nubeiot/core/event/EventMessage.java +++ b/core/base/src/main/java/com/nubeiot/core/event/EventMessage.java @@ -13,6 +13,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import com.nubeiot.core.dto.JsonData; import com.nubeiot.core.enums.Status; +import com.nubeiot.core.exceptions.ErrorData; import com.nubeiot.core.exceptions.ErrorMessage; import com.nubeiot.core.exceptions.NubeException; import com.nubeiot.core.exceptions.NubeException.ErrorCode; @@ -85,10 +86,19 @@ private EventMessage(Status status, EventAction action, EventAction prevAction, this(status, action, prevAction, Objects.isNull(data) ? null : data.getMap(), null, null); } - public static EventMessage error(EventAction action, @NonNull Throwable throwable) { + public static EventMessage error(@NonNull EventAction action, @NonNull Throwable throwable) { return new EventMessage(Status.FAILED, action, ErrorMessage.parse(throwable)); } + public static EventMessage error(@NonNull EventAction action, @NonNull Throwable throwable, JsonObject extra) { + return new EventMessage(Status.FAILED, action, + ErrorData.builder().throwable(throwable).extraInfo(extra).build()); + } + + public static EventMessage error(@NonNull EventAction action, @NonNull ErrorData errorData) { + return new EventMessage(Status.FAILED, action, errorData); + } + public static EventMessage error(@NonNull EventAction action, @NonNull ErrorCode code, @NonNull String message) { return new EventMessage(Status.FAILED, action, ErrorMessage.parse(code, message)); } diff --git a/core/base/src/main/java/com/nubeiot/core/exceptions/ErrorData.java b/core/base/src/main/java/com/nubeiot/core/exceptions/ErrorData.java index 96db82fe2..4f62b8571 100644 --- a/core/base/src/main/java/com/nubeiot/core/exceptions/ErrorData.java +++ b/core/base/src/main/java/com/nubeiot/core/exceptions/ErrorData.java @@ -17,7 +17,7 @@ @Getter @Builder(builderClassName = "Builder") @JsonDeserialize(builder = ErrorData.Builder.class) -public class ErrorData implements JsonData { +public final class ErrorData implements JsonData { @NonNull private final ErrorMessage error; diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java index 2a8e3ab55..1e0c06bbe 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerEntityHandler.java @@ -35,13 +35,13 @@ import com.nubeiot.edge.installer.model.Keys; import com.nubeiot.edge.installer.model.Tables; import com.nubeiot.edge.installer.model.dto.RequestedServiceData; -import com.nubeiot.edge.installer.model.tables.daos.TblModuleDao; -import com.nubeiot.edge.installer.model.tables.daos.TblRemoveHistoryDao; -import com.nubeiot.edge.installer.model.tables.daos.TblTransactionDao; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblModule; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblRemoveHistory; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationDao; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationHistoryDao; +import com.nubeiot.edge.installer.model.tables.daos.DeployTransactionDao; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplication; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplicationHistory; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; import com.nubeiot.edge.installer.repository.InstallerRepository; import com.nubeiot.edge.installer.service.AppDeployerDefinition; import com.nubeiot.edge.installer.service.InstallerApiIndex; @@ -92,16 +92,16 @@ public final Single before() { return this; } - public final TblModuleDao moduleDao() { - return dao(TblModuleDao.class); + public final ApplicationDao applicationDao() { + return dao(ApplicationDao.class); } - public final TblTransactionDao transDao() { - return dao(TblTransactionDao.class); + public final DeployTransactionDao transDao() { + return dao(DeployTransactionDao.class); } - final Single> getModulesWhenBootstrap() { - return moduleDao().findManyByState(Arrays.asList(State.NONE, State.ENABLED)); + final Single> getModulesWhenBootstrap() { + return applicationDao().findManyByState(Arrays.asList(State.NONE, State.ENABLED)); } final InstallerEntityHandler initDeployer() { @@ -110,11 +110,11 @@ final InstallerEntityHandler initDeployer() { return this; } - protected AppConfig transformAppConfig(RepositoryConfig repoConfig, ITblModule tblModule, AppConfig appConfig) { + protected AppConfig transformAppConfig(RepositoryConfig repoConfig, IApplication tblModule, AppConfig appConfig) { return appConfig; } - protected TblModule decorateModule(TblModule module) { + protected Application decorateModule(Application module) { final OffsetDateTime now = DateTimes.now(); return module.setCreatedAt(now).setModifiedAt(now); } @@ -128,21 +128,21 @@ Single addBuiltinApps(InstallerConfig config) { return Observable.fromIterable(config.getBuiltinApps()) .map(serviceData -> createTblModule(dataDir, config.getRepoConfig(), serviceData)) .map(this::decorateModule) - .collect(ArrayList::new, ArrayList::add) - .flatMap(list -> dao(TblModuleDao.class).insert(list)) + .collect(ArrayList::new, ArrayList::add) + .flatMap(list -> dao(ApplicationDao.class).insert(list)) .map(r -> new JsonObject().put("results", "Inserted " + r + " app module record(s)")); } - private TblModule createTblModule(Path dataDir, RepositoryConfig repoConfig, RequestedServiceData serviceData) { + private Application createTblModule(Path dataDir, RepositoryConfig repoConfig, RequestedServiceData serviceData) { ModuleTypeRule rule = sharedData(SHARED_MODULE_RULE); - ITblModule tblModule = rule.parse(serviceData.getMetadata()); + IApplication tblModule = rule.parse(serviceData.getMetadata()); AppConfig appConfig = transformAppConfig(repoConfig, tblModule, serviceData.getAppConfig()); - return (TblModule) rule.parse(dataDir, tblModule, appConfig).setState(State.NONE); + return (Application) rule.parse(dataDir, tblModule, appConfig).setState(State.NONE); } Single transitionPendingModules() { bootstrap = EventAction.MIGRATE; - final TblModuleDao dao = moduleDao(); + final ApplicationDao dao = applicationDao(); return dao.findManyByState(Collections.singletonList(State.PENDING)) .flattenAsObservable(pendingModules -> pendingModules) .flatMapMaybe(m -> genericQuery().executeAny(context -> getLastWipTransaction(m, context)) @@ -154,17 +154,17 @@ Single transitionPendingModules() { .map(r -> new JsonObject().put("results", r)); } - private Optional getLastWipTransaction(TblModule module, DSLContext dsl) { + private Optional getLastWipTransaction(Application module, DSLContext dsl) { return Optional.ofNullable(dsl.select() - .from(Tables.TBL_TRANSACTION) - .where(DSL.field(Tables.TBL_TRANSACTION.MODULE_ID).eq(module.getServiceId())) - .and(DSL.field(Tables.TBL_TRANSACTION.STATUS).eq(Status.WIP)) - .orderBy(Tables.TBL_TRANSACTION.MODIFIED_AT.desc()) + .from(Tables.APPLICATION) + .where(DSL.field(Tables.APPLICATION.APP_ID).eq(module.getAppId())) + .and(DSL.field(Tables.DEPLOY_TRANSACTION.STATUS).eq(Status.WIP)) + .orderBy(Tables.DEPLOY_TRANSACTION.MODIFIED_AT.desc()) .limit(1) - .fetchOneInto(TblTransaction.class)); + .fetchOneInto(DeployTransaction.class)); } - private TblModule checkingTransaction(TblModule module, TblTransaction transaction) { + private Application checkingTransaction(Application module, DeployTransaction transaction) { if (transaction.getEvent() == EventAction.CREATE || transaction.getEvent() == EventAction.INIT) { return module.setState(State.ENABLED); } @@ -173,14 +173,15 @@ private TblModule checkingTransaction(TblModule module, TblTransaction transacti if (Objects.isNull(prevMeta)) { return module.setState(State.ENABLED); } - return module.setState(new TblModule(prevMeta).getState() == State.DISABLED ? State.DISABLED : State.NONE); + return module.setState( + new Application(prevMeta).getState() == State.DISABLED ? State.DISABLED : State.NONE); } return module.setState(State.DISABLED); } private Single> findHistoryTransactionById(String transactionId) { - return dao(TblRemoveHistoryDao.class).findOneById(transactionId) - .map(optional -> optional.map(ITblRemoveHistory::toJson)); + return dao(ApplicationHistoryDao.class).findOneById(transactionId) + .map(optional -> optional.map(IApplicationHistory::toJson)); } public final Single> findTransactionById(String transactionId) { @@ -190,20 +191,20 @@ public final Single> findTransactionById(String transaction : this.findHistoryTransactionById(transactionId)); } - public final Single> findTransactionByModuleId(String moduleId) { + public final Single> findTransactionByModuleId(String moduleId) { return transDao().queryExecutor() - .findMany(dsl -> dsl.selectFrom(Tables.TBL_TRANSACTION) - .where(DSL.field(Tables.TBL_TRANSACTION.MODULE_ID).eq(moduleId)) - .orderBy(Tables.TBL_TRANSACTION.ISSUED_AT.desc())); + .findMany(dsl -> dsl.selectFrom(Tables.DEPLOY_TRANSACTION) + .where(DSL.field(Tables.DEPLOY_TRANSACTION.APP_ID).eq(moduleId)) + .orderBy(Tables.DEPLOY_TRANSACTION.ISSUED_AT.desc())); } public final Single> findOneTransactionByModuleId(String moduleId) { return transDao().queryExecutor() - .findOne(dsl -> dsl.selectFrom(Tables.TBL_TRANSACTION) - .where(DSL.field(Tables.TBL_TRANSACTION.MODULE_ID).eq(moduleId)) - .orderBy(Tables.TBL_TRANSACTION.ISSUED_AT.desc()) + .findOne(dsl -> dsl.selectFrom(Tables.DEPLOY_TRANSACTION) + .where(DSL.field(Tables.DEPLOY_TRANSACTION.APP_ID).eq(moduleId)) + .orderBy(Tables.DEPLOY_TRANSACTION.ISSUED_AT.desc()) .limit(1)) - .map(optional -> optional.map(TblTransaction::toJson)); + .map(optional -> optional.map(DeployTransaction::toJson)); } @Override diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerSchemaHandler.java b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerSchemaHandler.java index ea40c2d28..13dc677c7 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerSchemaHandler.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/InstallerSchemaHandler.java @@ -15,7 +15,7 @@ final class InstallerSchemaHandler implements SchemaHandler { @Override public @NonNull Table table() { - return Tables.TBL_MODULE; + return Tables.APPLICATION; } @Override diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/loader/ModuleTypeRule.java b/core/installer/src/main/java/com/nubeiot/edge/installer/loader/ModuleTypeRule.java index 5ae555971..f58f2af43 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/loader/ModuleTypeRule.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/loader/ModuleTypeRule.java @@ -15,8 +15,8 @@ import com.nubeiot.core.NubeConfig; import com.nubeiot.core.NubeConfig.AppConfig; import com.nubeiot.core.utils.FileUtils; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplication; +import com.nubeiot.edge.installer.model.tables.pojos.Application; import lombok.AccessLevel; import lombok.NonNull; @@ -31,24 +31,24 @@ public ModuleTypeRule() { rules = new HashMap<>(); } - public ITblModule parse(@NonNull Path dataDir, @NonNull JsonObject metadata, AppConfig appConfig) { - ITblModule tblModule = parse(metadata); - tblModule = tblModule.setAppConfig(appConfig.toJson()); - tblModule = tblModule.setSystemConfig(computeAppSystemConfig(dataDir, tblModule.getServiceId())); - return tblModule; + public IApplication parse(@NonNull Path dataDir, @NonNull JsonObject metadata, AppConfig appConfig) { + IApplication application = parse(metadata); + application = application.setAppConfig(appConfig.toJson()); + application = application.setSystemConfig(computeAppSystemConfig(dataDir, application.getAppId())); + return application; } - public ITblModule parse(JsonObject metadata) { + public IApplication parse(JsonObject metadata) { ModuleType moduleType = ModuleType.factory(metadata.getString("service_type")); String serviceId = metadata.getString("service_id"); JsonObject module = Objects.isNull(serviceId) ? moduleType.serialize(metadata, this) : metadata; - return new TblModule().fromJson(module); + return new Application().fromJson(module); } - public ITblModule parse(@NonNull Path dataDir, @NonNull ITblModule tblModule, AppConfig appConfig) { - tblModule = tblModule.setAppConfig(appConfig.toJson()); - tblModule = tblModule.setSystemConfig(computeAppSystemConfig(dataDir, tblModule.getServiceId())); - return tblModule; + public IApplication parse(@NonNull Path dataDir, @NonNull IApplication application, AppConfig appConfig) { + application = application.setAppConfig(appConfig.toJson()); + application = application.setSystemConfig(computeAppSystemConfig(dataDir, application.getAppId())); + return application; } private JsonObject computeAppSystemConfig(@NonNull Path parentDataDir, String serviceId) { diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/search/LocalServiceSearch.java b/core/installer/src/main/java/com/nubeiot/edge/installer/search/LocalServiceSearch.java index 859ed5b84..f25e33b5c 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/search/LocalServiceSearch.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/search/LocalServiceSearch.java @@ -30,7 +30,7 @@ import com.nubeiot.edge.installer.loader.ModuleType; import com.nubeiot.edge.installer.model.Tables; import com.nubeiot.edge.installer.model.dto.PreDeploymentResult; -import com.nubeiot.edge.installer.model.tables.records.TblModuleRecord; +import com.nubeiot.edge.installer.model.tables.records.ApplicationRecord; import lombok.NonNull; @@ -57,18 +57,18 @@ public Single search(RequestData requestData) throws NubeException { .map(results -> new JsonObject().put("services", results)); } - private Single excludeData(TblModuleRecord rec) { - final JsonObject cfg = PreDeploymentResult.filterOutSensitiveConfig(rec.getServiceId(), rec.getAppConfig()); + private Single excludeData(ApplicationRecord rec) { + final JsonObject cfg = PreDeploymentResult.filterOutSensitiveConfig(rec.getAppId(), rec.getAppConfig()); return Single.just(rec.setAppConfig(cfg).setSystemConfig(null).toJson()); } private JsonObject validateFilter(JsonObject filter) { //TODO fields name, depends object -> validate method JsonObject sqlData = new JsonObject(filter.getMap()); - String state = filter.getString(Tables.TBL_MODULE.STATE.getName().toLowerCase()); + String state = filter.getString(Tables.APPLICATION.STATE.getName().toLowerCase()); if (Strings.isNotBlank(state)) { try { - sqlData.put(Tables.TBL_MODULE.STATE.getName().toLowerCase(), State.valueOf(state)); + sqlData.put(Tables.APPLICATION.STATE.getName().toLowerCase(), State.valueOf(state)); } catch (IllegalArgumentException e) { throw new NubeException(ErrorCode.INVALID_ARGUMENT, "Invalid state", e); } @@ -87,11 +87,11 @@ private JsonObject validateFilter(JsonObject filter) { } @SuppressWarnings( {"unchecked", "rawtypes"}) - private List filter(JsonObject filter, Pagination pagination, DSLContext context) { - SelectConditionStep sql = context.selectFrom(Tables.TBL_MODULE) - .where(DSL.field(Tables.TBL_MODULE.SERVICE_TYPE) - .eq(ModuleType.JAVA)); - Set fieldNames = Arrays.stream(Tables.TBL_MODULE.fields()) + private List filter(JsonObject filter, Pagination pagination, DSLContext context) { + SelectConditionStep sql = context.selectFrom(Tables.APPLICATION) + .where(DSL.field(Tables.APPLICATION.SERVICE_TYPE) + .eq(ModuleType.JAVA)); + Set fieldNames = Arrays.stream(Tables.APPLICATION.fields()) .map(Field::getName) .collect(Collectors.toSet()); filter.getMap() @@ -99,22 +99,22 @@ private List filter(JsonObject filter, Pagination pagination, D .parallelStream() .filter(entry -> fieldNames.contains(entry.getKey())) .forEach(entry -> { - Field field = Tables.TBL_MODULE.field(entry.getKey()); + Field field = Tables.APPLICATION.field(entry.getKey()); sql.and(field.eq(entry.getValue())); }); final Instant from = filter.getInstant("from"); if (Objects.nonNull(from)) { - sql.and(DSL.field(Tables.TBL_MODULE.CREATED_AT).gt(DateTimes.from(from))); + sql.and(DSL.field(Tables.APPLICATION.CREATED_AT).gt(DateTimes.from(from))); } final Instant to = filter.getInstant("to"); if (Objects.nonNull(to)) { - sql.and(DSL.field(Tables.TBL_MODULE.CREATED_AT).lt(DateTimes.from(to))); + sql.and(DSL.field(Tables.APPLICATION.CREATED_AT).lt(DateTimes.from(to))); } return sql.limit(pagination.getPerPage()) .offset(((pagination.getPage() - 1) * pagination.getPerPage())) - .fetchInto(TblModuleRecord.class); + .fetchInto(ApplicationRecord.class); } } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java index b24b485c8..2a50a7482 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentTracker.java @@ -29,12 +29,12 @@ import com.nubeiot.edge.installer.InstallerEntityHandler; import com.nubeiot.edge.installer.model.Tables; import com.nubeiot.edge.installer.model.dto.PostDeploymentResult; -import com.nubeiot.edge.installer.model.tables.daos.TblRemoveHistoryDao; -import com.nubeiot.edge.installer.model.tables.daos.TblTransactionDao; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblRemoveHistory; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblTransaction; -import com.nubeiot.edge.installer.model.tables.pojos.TblRemoveHistory; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationHistoryDao; +import com.nubeiot.edge.installer.model.tables.daos.DeployTransactionDao; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplicationHistory; +import com.nubeiot.edge.installer.model.tables.interfaces.IDeployTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.ApplicationHistory; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; import lombok.AccessLevel; import lombok.NonNull; @@ -68,20 +68,20 @@ private Single handleSuccess(@NonNull PostDeploymentResult final State state = StateMachine.instance().transition(res.getAction(), status, res.getToState()); final String serviceId = res.getServiceId(); if (State.UNAVAILABLE == state) { - final TblTransactionDao dao = entityHandler.transDao(); + final DeployTransactionDao dao = entityHandler.transDao(); LOGGER.info("INSTALLER::Removing service '{}' and its transactions...", serviceId); return dao.findOneById(res.getTransactionId()) .filter(Optional::isPresent) .map(Optional::get) - .defaultIfEmpty(new TblTransaction().setTransactionId(res.getTransactionId()) - .setModuleId(serviceId) - .setEvent(res.getAction())) + .defaultIfEmpty(new DeployTransaction().setTransactionId(res.getTransactionId()) + .setAppId(serviceId) + .setEvent(res.getAction())) .flatMapSingle(r -> createHistoryRecord(r.setStatus(status))) - .flatMap(his -> dao.deleteByCondition(Tables.TBL_TRANSACTION.MODULE_ID.eq(serviceId))) - .flatMap(r -> entityHandler.moduleDao().deleteById(serviceId).map(n -> r + n + 1)) + .flatMap(his -> dao.deleteByCondition(Tables.DEPLOY_TRANSACTION.APP_ID.eq(serviceId))) + .flatMap(r -> entityHandler.applicationDao().deleteById(serviceId).map(n -> r + n + 1)) .map(records -> PostDeploymentResult.from(res, state, records)); } - Map v = Collections.singletonMap(Tables.TBL_MODULE.DEPLOY_ID, res.getDeployId()); + Map v = Collections.singletonMap(Tables.APPLICATION.DEPLOY_ID, res.getDeployId()); final JDBCRXGenericQueryExecutor queryExecutor = entityHandler.genericQuery(); return queryExecutor.executeAny(c -> updateTransStatus(c, res.getTransactionId(), status, null)) .flatMap(r1 -> queryExecutor.executeAny(c -> updateModuleState(c, serviceId, state, v)) @@ -92,38 +92,38 @@ private Single handleSuccess(@NonNull PostDeploymentResult private Single handleError(@NonNull PostDeploymentResult res) { LOGGER.error("INSTALLER::Handle entities after error deployment..."); final JDBCRXGenericQueryExecutor query = entityHandler.genericQuery(); - final Map values = Collections.singletonMap(Tables.TBL_TRANSACTION.LAST_ERROR, res.getError()); + final Map values = Collections.singletonMap(Tables.DEPLOY_TRANSACTION.LAST_ERROR, res.getError()); return query.executeAny(c -> updateTransStatus(c, res.getTransactionId(), Status.FAILED, values)) .flatMap(r1 -> query.executeAny(c -> updateModuleState(c, res.getServiceId(), State.DISABLED, null)) .map(r2 -> r1 + r2)) .map(records -> PostDeploymentResult.from(res, State.DISABLED, records)); } - private Single createHistoryRecord(ITblTransaction transaction) { - ITblRemoveHistory history = this.convertToHistory(transaction); - return entityHandler.dao(TblRemoveHistoryDao.class).insert((TblRemoveHistory) history).map(i -> history); + private Single createHistoryRecord(IDeployTransaction transaction) { + IApplicationHistory history = this.convertToHistory(transaction); + return entityHandler.dao(ApplicationHistoryDao.class).insert((ApplicationHistory) history).map(i -> history); } private int updateModuleState(DSLContext context, String serviceId, State state, Map values) { - return context.update(Tables.TBL_MODULE) - .set(Tables.TBL_MODULE.STATE, state) - .set(Tables.TBL_MODULE.MODIFIED_AT, DateTimes.now()) + return context.update(Tables.APPLICATION) + .set(Tables.APPLICATION.STATE, state) + .set(Tables.APPLICATION.MODIFIED_AT, DateTimes.now()) .set(Objects.isNull(values) ? new HashMap<>() : values) - .where(Tables.TBL_MODULE.SERVICE_ID.eq(serviceId)) + .where(Tables.APPLICATION.APP_ID.eq(serviceId)) .execute(); } private int updateTransStatus(DSLContext context, String transId, Status status, Map values) { - return context.update(Tables.TBL_TRANSACTION) - .set(Tables.TBL_TRANSACTION.STATUS, status) - .set(Tables.TBL_TRANSACTION.MODIFIED_AT, DateTimes.now()) + return context.update(Tables.DEPLOY_TRANSACTION) + .set(Tables.DEPLOY_TRANSACTION.STATUS, status) + .set(Tables.DEPLOY_TRANSACTION.MODIFIED_AT, DateTimes.now()) .set(Objects.isNull(values) ? new HashMap<>() : values) - .where(Tables.TBL_TRANSACTION.TRANSACTION_ID.eq(transId)) + .where(Tables.DEPLOY_TRANSACTION.TRANSACTION_ID.eq(transId)) .execute(); } - private ITblRemoveHistory convertToHistory(ITblTransaction transaction) { - ITblRemoveHistory history = new TblRemoveHistory().fromJson(transaction.toJson()); + private IApplicationHistory convertToHistory(IDeployTransaction transaction) { + IApplicationHistory history = new ApplicationHistory().fromJson(transaction.toJson()); if (Objects.isNull(history.getIssuedAt())) { history.setIssuedAt(DateTimes.now()); } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java index d07825f6a..5669413c2 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/AppDeploymentWorkflow.java @@ -27,9 +27,9 @@ import com.nubeiot.edge.installer.InstallerConfig; import com.nubeiot.edge.installer.InstallerEntityHandler; import com.nubeiot.edge.installer.model.dto.PreDeploymentResult; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplication; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; import lombok.NonNull; @@ -45,21 +45,21 @@ public AppDeploymentWorkflow(InstallerEntityHandler entityHandler) { this.definition = entityHandler.sharedData(InstallerEntityHandler.SHARED_APP_DEPLOYER_CFG); } - public Single process(ITblModule module, EventAction action) { + public Single process(IApplication module, EventAction action) { return process(Collections.singleton(module), action).firstOrError(); } - public Observable process(Collection modules, EventAction action) { + public Observable process(Collection modules, EventAction action) { return Observable.fromIterable(modules).flatMapSingle(module -> processDeployment(module, action)); } - private Single processDeployment(ITblModule module, EventAction action) { - LOGGER.info("INSTALLER handle for {}::::{}", action, module.getServiceId()); + private Single processDeployment(IApplication module, EventAction action) { + LOGGER.info("INSTALLER handle for {}::::{}", action, module.getAppId()); return createPreDeployment(module, action).doOnSuccess(this::deployModule).map(PreDeploymentResult::toResponse); } - private Single createPreDeployment(ITblModule req, EventAction action) { - LOGGER.info("INSTALLER create pre-deployment for {}::::{}", action, req.getServiceId()); + private Single createPreDeployment(IApplication req, EventAction action) { + LOGGER.info("INSTALLER create pre-deployment for {}::::{}", action, req.getAppId()); InstallerConfig config = entityHandler.sharedData(InstallerEntityHandler.SHARED_INSTALLER_CFG); if (EventAction.CREATE == action || EventAction.INIT == action || (EventAction.MIGRATE == action && State.PENDING == req.getState())) { @@ -75,12 +75,13 @@ private Single createPreDeployment(ITblModule req, EventAct .flatMapSingle(m -> persistPreDeployResult(req, action, m)); } - private Single persistPreDeployResult(@NonNull ITblModule request, @NonNull EventAction action, - @NonNull ITblModule dbEntity) { - final TblModule cloneDb = new TblModule(dbEntity); + private Single persistPreDeployResult(@NonNull IApplication request, + @NonNull EventAction action, + @NonNull IApplication dbEntity) { + final Application cloneDb = new Application(dbEntity); final State prevState = EventAction.CREATE == action ? State.NONE : dbEntity.getState(); final State toState = Optional.ofNullable(request.getState()).orElse(dbEntity.getState()); - Maybe into = Maybe.empty(); + Maybe into = Maybe.empty(); if (EventAction.CREATE == action) { into = Maybe.fromSingle(markModuleInsert(cloneDb)); } @@ -106,16 +107,16 @@ private void deployModule(PreDeploymentResult preDeployResult) { .fire(DeliveryEvent.from(definition.getLoaderEvent(), action, preDeployResult.toRequestData())); } - private PreDeploymentResult createPreDeployResult(ITblModule module, String transactionId, EventAction action, + private PreDeploymentResult createPreDeployResult(IApplication module, String transactionId, EventAction action, State prevState, State targetState) { return PreDeploymentResult.builder() .transactionId(transactionId) .action(action == EventAction.MIGRATE ? EventAction.UPDATE : action) .prevState(prevState) .targetState(targetState) - .serviceId(module.getServiceId()) + .serviceId(module.getAppId()) .serviceFQN(module.getServiceType() - .generateFQN(module.getServiceId(), module.getVersion(), + .generateFQN(module.getAppId(), module.getVersion(), module.getServiceName())) .deployId(module.getDeployId()) .appConfig(module.getAppConfig()) @@ -124,15 +125,15 @@ private PreDeploymentResult createPreDeployResult(ITblModule module, String tran .build(); } - private Single> validateModuleState(ITblModule module, EventAction action) { - LOGGER.info("INSTALLER validate service state {}::::{}", action, module.getServiceId()); - return entityHandler.moduleDao() - .findOneById(module.getServiceId()) + private Single> validateModuleState(IApplication module, EventAction action) { + LOGGER.info("INSTALLER validate service state {}::::{}", action, module.getAppId()); + return entityHandler.applicationDao() + .findOneById(module.getAppId()) .map(o -> validateModuleState(o.orElse(null), action, module.getState())); } - private Single createTransaction(EventAction action, ITblModule module) { - LOGGER.info("INSTALLER create transaction for {}::::{}", action, module.getServiceId()); + private Single createTransaction(EventAction action, IApplication module) { + LOGGER.info("INSTALLER create transaction for {}::::{}", action, module.getAppId()); if (LOGGER.isDebugEnabled()) { LOGGER.debug("INSTALLER previous module state: {}", module.toJson()); } @@ -142,43 +143,43 @@ private Single createTransaction(EventAction action, ITblModule module) // TODO replace with POJO constant later metadata.remove("system_config"); metadata.remove("app_config"); - final TblTransaction transaction = new TblTransaction().setTransactionId(transactionId) - .setModuleId(module.getServiceId()) - .setStatus(Status.WIP) - .setEvent(action) - .setIssuedAt(now) - .setModifiedAt(now) - .setRetry(0) - .setPrevMetadata(metadata) - .setPrevSystemConfig(module.getSystemConfig()) - .setPrevAppConfig(module.getAppConfig()); + final DeployTransaction transaction = new DeployTransaction().setTransactionId(transactionId) + .setAppId(module.getAppId()) + .setStatus(Status.WIP) + .setEvent(action) + .setIssuedAt(now) + .setModifiedAt(now) + .setRetry(0) + .setPrevMetadata(metadata) + .setPrevSystemConfig(module.getSystemConfig()) + .setPrevAppConfig(module.getAppConfig()); return entityHandler.transDao().insert(transaction).map(i -> transactionId); } - private Single markModuleInsert(ITblModule module) { - LOGGER.debug("INSTALLER mark service {} to create...", module.getServiceId()); + private Single markModuleInsert(IApplication module) { + LOGGER.debug("INSTALLER mark service {} to create...", module.getAppId()); OffsetDateTime now = DateTimes.now(); - return entityHandler.moduleDao() - .insert((TblModule) module.setCreatedAt(now).setModifiedAt(now).setState(State.PENDING)) + return entityHandler.applicationDao() + .insert((Application) module.setCreatedAt(now).setModifiedAt(now).setState(State.PENDING)) .map(i -> module); } - private Single markModuleModify(ITblModule module, ITblModule oldOne, boolean isUpdated) { - LOGGER.debug("INSTALLER mark service {} to modify...", module.getServiceId()); - ITblModule into = updateModule(oldOne, module, isUpdated); - return entityHandler.moduleDao() - .update((TblModule) into.setState(State.PENDING).setModifiedAt(DateTimes.now())) + private Single markModuleModify(IApplication module, IApplication oldOne, boolean isUpdated) { + LOGGER.debug("INSTALLER mark service {} to modify...", module.getAppId()); + IApplication into = updateModule(oldOne, module, isUpdated); + return entityHandler.applicationDao() + .update((Application) into.setState(State.PENDING).setModifiedAt(DateTimes.now())) .map(ignore -> oldOne); } - private Single markModuleDelete(ITblModule module) { - LOGGER.debug("INSTALLER mark service {} to delete...", module.getServiceId()); - return entityHandler.moduleDao() - .update((TblModule) module.setState(State.PENDING).setModifiedAt(DateTimes.now())) + private Single markModuleDelete(IApplication module) { + LOGGER.debug("INSTALLER mark service {} to delete...", module.getAppId()); + return entityHandler.applicationDao() + .update((Application) module.setState(State.PENDING).setModifiedAt(DateTimes.now())) .map(ignore -> module); } - private ITblModule updateModule(@NonNull ITblModule old, @NonNull ITblModule newOne, boolean isUpdated) { + private IApplication updateModule(@NonNull IApplication old, @NonNull IApplication newOne, boolean isUpdated) { if (Strings.isBlank(newOne.getVersion()) && isUpdated) { throw new IllegalArgumentException("Service version is mandatory"); } @@ -194,15 +195,14 @@ private ITblModule updateModule(@NonNull ITblModule old, @NonNull ITblModule new return old; } - private Optional validateModuleState(ITblModule findModule, EventAction action, State targetState) { + private Optional validateModuleState(IApplication findModule, EventAction action, State targetState) { StateMachine.instance().validate(findModule, action, "service"); if (Objects.nonNull(findModule)) { final State target = action == EventAction.INIT ? State.ENABLED : Optional.ofNullable(targetState).orElse(findModule.getState()); StateMachine.instance() - .validateConflict(findModule.getState(), action, "service " + findModule.getServiceId(), - target); + .validateConflict(findModule.getState(), action, "service " + findModule.getAppId(), target); return Optional.of(findModule); } return Optional.empty(); diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/ModuleService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/ApplicationService.java similarity index 83% rename from core/installer/src/main/java/com/nubeiot/edge/installer/service/ModuleService.java rename to core/installer/src/main/java/com/nubeiot/edge/installer/service/ApplicationService.java index 761498f43..071ac4dee 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/ModuleService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/ApplicationService.java @@ -17,9 +17,9 @@ import com.nubeiot.edge.installer.loader.ModuleTypeRule; import com.nubeiot.edge.installer.model.dto.PreDeploymentResult; import com.nubeiot.edge.installer.model.dto.RequestedServiceData; -import com.nubeiot.edge.installer.model.tables.daos.TblModuleDao; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationDao; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplication; +import com.nubeiot.edge.installer.model.tables.pojos.Application; import com.nubeiot.edge.installer.search.LocalServiceSearch; import lombok.AccessLevel; @@ -27,7 +27,7 @@ import lombok.RequiredArgsConstructor; @RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public abstract class ModuleService implements InstallerService { +public abstract class ApplicationService implements InstallerService { @NonNull private final InstallerEntityHandler entityHandler; @@ -37,7 +37,7 @@ public final String servicePath() { } public final String paramPath() { - return "service_id"; + return "app_id"; } @Override @@ -60,7 +60,7 @@ public Single getOne(RequestData data) { if (Strings.isBlank(serviceId)) { throw new IllegalArgumentException("Service id is mandatory"); } - return entityHandler.dao(TblModuleDao.class) + return entityHandler.dao(ApplicationDao.class) .findOneById(serviceId) .map(o -> o.map(this::removeCredentialsInAppConfig)) .filter(Optional::isPresent) @@ -71,8 +71,8 @@ public Single getOne(RequestData data) { @EventContractor(action = EventAction.PATCH, returnType = Single.class) public Single patch(RequestData data) { - ITblModule module = createTblModule(data.body()); - if (Strings.isBlank(module.getServiceId())) { + IApplication module = createTblModule(data.body()); + if (Strings.isBlank(module.getAppId())) { throw new IllegalArgumentException("Service id is mandatory"); } return new AppDeploymentWorkflow(entityHandler).process(module, EventAction.PATCH); @@ -80,8 +80,8 @@ public Single patch(RequestData data) { @EventContractor(action = EventAction.UPDATE, returnType = Single.class) public Single update(RequestData data) { - ITblModule module = validate(data.body()); - if (Strings.isBlank(module.getServiceName()) && Strings.isBlank(module.getServiceId())) { + IApplication module = validate(data.body()); + if (Strings.isBlank(module.getServiceName()) && Strings.isBlank(module.getAppId())) { throw new IllegalArgumentException("Provide at least service id or service name"); } return new AppDeploymentWorkflow(entityHandler).process(module, EventAction.UPDATE); @@ -89,8 +89,8 @@ public Single update(RequestData data) { @EventContractor(action = EventAction.REMOVE, returnType = Single.class) public Single remove(RequestData data) { - ITblModule module = new TblModule().setServiceId(data.body().getString(paramPath())); - if (Strings.isBlank(module.getServiceId())) { + IApplication module = new Application().setAppId(data.body().getString(paramPath())); + if (Strings.isBlank(module.getAppId())) { throw new IllegalArgumentException("Service id is mandatory"); } return new AppDeploymentWorkflow(entityHandler).process(module, EventAction.REMOVE); @@ -101,13 +101,13 @@ public Single create(RequestData data) { return new AppDeploymentWorkflow(entityHandler).process(validate(data.body()), EventAction.CREATE); } - private JsonObject removeCredentialsInAppConfig(TblModule record) { - record.setAppConfig(PreDeploymentResult.filterOutSensitiveConfig(record.getServiceId(), record.getAppConfig())); + private JsonObject removeCredentialsInAppConfig(Application record) { + record.setAppConfig(PreDeploymentResult.filterOutSensitiveConfig(record.getAppId(), record.getAppConfig())); return record.toJson(); } - private ITblModule validate(@NonNull JsonObject body) { - ITblModule module = createTblModule(body); + private IApplication validate(@NonNull JsonObject body) { + IApplication module = createTblModule(body); if (Strings.isBlank(module.getServiceName())) { throw new IllegalArgumentException("Service name is mandatory"); } @@ -117,7 +117,7 @@ private ITblModule validate(@NonNull JsonObject body) { return module; } - private ITblModule createTblModule(JsonObject body) { + private IApplication createTblModule(JsonObject body) { String serviceId = body.getString(paramPath()); body.remove(paramPath()); RequestedServiceData serviceData = body.isEmpty() diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java new file mode 100644 index 000000000..970a4543e --- /dev/null +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java @@ -0,0 +1,160 @@ +package com.nubeiot.edge.installer.service; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.jooq.Field; + +import io.reactivex.Single; +import io.vertx.core.http.HttpMethod; +import io.vertx.core.json.JsonObject; + +import com.nubeiot.core.NubeConfig; +import com.nubeiot.core.archiver.AsyncZipFolder; +import com.nubeiot.core.archiver.ZipArgument; +import com.nubeiot.core.archiver.ZipNotificationHandler; +import com.nubeiot.core.archiver.ZipOutput; +import com.nubeiot.core.dto.RequestData; +import com.nubeiot.core.enums.Status; +import com.nubeiot.core.event.EventAction; +import com.nubeiot.core.event.EventContractor; +import com.nubeiot.core.exceptions.ErrorData; +import com.nubeiot.core.http.base.event.ActionMethodMapping; +import com.nubeiot.core.sql.service.AbstractReferencingEntityService; +import com.nubeiot.core.sql.service.marker.EntityReferences; +import com.nubeiot.core.utils.Strings; +import com.nubeiot.core.utils.UUID64; +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationDao; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.ApplicationBackup; +import com.nubeiot.edge.installer.service.InstallerApiIndex.ApplicationMetadata; +import com.nubeiot.edge.installer.service.InstallerApiIndex.BackupMetadata; + +import lombok.NonNull; + +/** + * Represents Backup service. + * + * @since 1.0.0 + */ +public abstract class BackupByAppService extends AbstractReferencingEntityService + implements InstallerService, ZipNotificationHandler { + + protected BackupByAppService(@NonNull InstallerEntityHandler entityHandler) { + super(entityHandler); + } + + @Override + public BackupMetadata context() { + return BackupMetadata.INSTANCE; + } + + @Override + public final String servicePath() { + return "/:app_id/backup"; + } + + @Override + public final String paramPath() { + return "backup_id"; + } + + @Override + public final ActionMethodMapping methodMapping() { + final Map map = new HashMap<>(); + map.put(EventAction.BACKUP, HttpMethod.POST); + map.put(EventAction.GET_ONE, HttpMethod.GET); + return ActionMethodMapping.create(map); + } + + @Override + public final @NonNull Collection getAvailableEvents() { + return Stream.of(ZipNotificationHandler.super.getAvailableEvents(), + Arrays.asList(EventAction.BACKUP, EventAction.GET_ONE)) + .flatMap(Collection::stream) + .collect(Collectors.toSet()); + } + + @Override + public final EntityReferences referencedEntities() { + return new EntityReferences().add(ApplicationMetadata.INSTANCE); + } + + @EventContractor(action = EventAction.BACKUP, returnType = Single.class) + public final Single backup(@NonNull RequestData data) { + final String appId = Strings.requireNotBlank(data.body().getString("app_id"), "Missing application id"); + return entityHandler().dao(ApplicationDao.class) + .findOneById(appId) + .filter(Optional::isPresent) + .map(Optional::get) + .switchIfEmpty(Single.error(ApplicationMetadata.INSTANCE.notFound(appId))) + .flatMap(this::createBackupRecord) + .doOnSuccess(this::doBackup); + } + + @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) + public final boolean success(@NonNull ZipOutput result) { + final ApplicationBackup backup = context().parseFromRequest(result.getTrackingInfo()); + final String type = result.getTrackingInfo().getString("type"); + patch(RequestData.builder() + .body(backup.toJson() + .put("status", Status.SUCCESS) + .put(type, result.toJson(Collections.singleton("trackingInfo")))) + .build()); + return true; + } + + @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) + public final boolean error(@NonNull ErrorData error) { + final ApplicationBackup backup = context().parseFromRequest(error.getExtraInfo()); + patch(RequestData.builder() + .body(backup.toJson().put("status", Status.FAILED).put("error", error.getError().toJson())) + .build()); + return true; + } + + protected @NonNull Path backupFolder() { + return entityHandler().dataDir().resolve("backup"); + } + + protected @NonNull Single createBackupRecord(@NonNull Application app) { + final ApplicationBackup backup = new ApplicationBackup().setAppId(app.getAppId()).setStatus(Status.INITIAL); + final String idField = jsonField(context().table().ID); + return create(RequestData.builder().body(backup.toJson()).build()).map( + json -> new JsonObject().put(context().requestKeyName(), UUID64.uuidToBase64(json.getString(idField))) + .put(jsonField(context().table().APP_ID), app.getAppId()) + .put(jsonField(context().table().INSTALLATION_DIR), app.getDeployLocation()) + .put(jsonField(context().table().DATA_DIR), + app.getSystemConfig().getString(NubeConfig.DATA_DIR))); + } + + protected void doBackup(@NonNull JsonObject record) { + final JsonObject info = new JsonObject().put(context().requestKeyName(), + record.getString(context().requestKeyName())) + .put(ApplicationMetadata.INSTANCE.requestKeyName(), + record.getString(ApplicationMetadata.INSTANCE.requestKeyName())); + final AsyncZipFolder zipper = AsyncZipFolder.builder() + .notifiedAddress(address()) + .transporter(entityHandler().eventClient()) + .build(); + // final String installationDirField = jsonField(context().table().INSTALLATION_DIR); + final String dataDirField = jsonField(context().table().DATA_DIR); + // zipper.run(ZipArgument.createDefault(info.put("type", installationDirField)), backupFolder(), + // Paths.get(installationDirField)); + zipper.run(ZipArgument.createDefault(info.put("type", dataDirField)), backupFolder(), Paths.get(dataDirField)); + } + + private String jsonField(Field installation_dir) { + return context().table().getJsonField(installation_dir); + } + +} diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java deleted file mode 100644 index 1e0767c43..000000000 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupService.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.nubeiot.edge.installer.service; - -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Collection; -import java.util.Collections; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import io.reactivex.Single; -import io.vertx.core.http.HttpMethod; -import io.vertx.core.json.JsonObject; - -import com.nubeiot.core.NubeConfig; -import com.nubeiot.core.archiver.AsyncZipFolder; -import com.nubeiot.core.archiver.ZipArgument; -import com.nubeiot.core.archiver.ZipNotificationHandler; -import com.nubeiot.core.archiver.ZipOutput; -import com.nubeiot.core.dto.RequestData; -import com.nubeiot.core.event.EventAction; -import com.nubeiot.core.event.EventContractor; -import com.nubeiot.core.exceptions.ErrorData; -import com.nubeiot.core.http.base.event.ActionMethodMapping; -import com.nubeiot.core.utils.Strings; -import com.nubeiot.core.utils.UUID64; -import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.model.tables.daos.TblModuleDao; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.service.InstallerApiIndex.ApplicationMetadata; - -import lombok.AccessLevel; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; - -/** - * Represents Backup service. - * - * @since 1.0.0 - */ -@RequiredArgsConstructor(access = AccessLevel.PROTECTED) -public abstract class BackupService implements InstallerService, ZipNotificationHandler { - - @NonNull - private final InstallerEntityHandler entityHandler; - - protected abstract @NonNull Path backupFolder(); - - @Override - public final String servicePath() { - return "/:app_id/backup"; - } - - @Override - public final String paramPath() { - return null; - } - - @Override - public final ActionMethodMapping methodMapping() { - return ActionMethodMapping.create(Collections.singletonMap(EventAction.BACKUP, HttpMethod.POST)); - } - - @Override - public final @NonNull Collection getAvailableEvents() { - return Stream.of(ZipNotificationHandler.super.getAvailableEvents(), Collections.singleton(EventAction.BACKUP)) - .flatMap(Collection::stream) - .collect(Collectors.toSet()); - } - - @EventContractor(action = EventAction.BACKUP, returnType = Single.class) - public final Single backup(@NonNull RequestData data) { - final String appId = Strings.requireNotBlank(data.body().getString("app_id"), "Missing application id"); - return entityHandler.dao(TblModuleDao.class) - .findOneById(appId) - .filter(Optional::isPresent) - .map(Optional::get) - .switchIfEmpty(Single.error(ApplicationMetadata.INSTANCE.notFound(appId))) - .map(this::createBackupRecord) - .doOnSuccess(this::doBackup); - } - - @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) - public final boolean success(@NonNull ZipOutput result) { - return true; - } - - @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) - public final boolean error(@NonNull ErrorData error) { - return true; - } - - protected @NonNull JsonObject createBackupRecord(@NonNull TblModule app) { - return new JsonObject().put("backup_id", UUID64.random()) - .put("deploy_location", app.getDeployLocation()) - .put("data_dir", app.getSystemConfig().getString(NubeConfig.DATA_DIR)); - } - - protected void doBackup(@NonNull JsonObject object) { - final JsonObject trackingInfo = new JsonObject().put("backup_id", object.getString("backup_id")); - final AsyncZipFolder zipper = AsyncZipFolder.builder() - .notifiedAddress(address()) - .transporter(entityHandler.eventClient()) - .build(); - zipper.run(ZipArgument.createDefault(trackingInfo.put("type", "deploy_location")), backupFolder(), - Paths.get(object.getString("deploy_location"))); - zipper.run(ZipArgument.createDefault(trackingInfo.put("type", "data_dir")), backupFolder(), - Paths.get(object.getString(NubeConfig.DATA_DIR))); - } - -} diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java index 29a0923ca..ab23f42e5 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/InstallerApiIndex.java @@ -8,17 +8,21 @@ import com.nubeiot.core.sql.EntityMetadata; import com.nubeiot.core.sql.EntityMetadata.StringKeyEntity; +import com.nubeiot.core.sql.EntityMetadata.UUIDKeyEntity; import com.nubeiot.core.sql.MetadataIndex; import com.nubeiot.edge.installer.model.Tables; -import com.nubeiot.edge.installer.model.tables.daos.TblModuleDao; -import com.nubeiot.edge.installer.model.tables.daos.TblRemoveHistoryDao; -import com.nubeiot.edge.installer.model.tables.daos.TblTransactionDao; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblRemoveHistory; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; -import com.nubeiot.edge.installer.model.tables.records.TblModuleRecord; -import com.nubeiot.edge.installer.model.tables.records.TblRemoveHistoryRecord; -import com.nubeiot.edge.installer.model.tables.records.TblTransactionRecord; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationBackupDao; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationDao; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationHistoryDao; +import com.nubeiot.edge.installer.model.tables.daos.DeployTransactionDao; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.ApplicationBackup; +import com.nubeiot.edge.installer.model.tables.pojos.ApplicationHistory; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; +import com.nubeiot.edge.installer.model.tables.records.ApplicationBackupRecord; +import com.nubeiot.edge.installer.model.tables.records.ApplicationHistoryRecord; +import com.nubeiot.edge.installer.model.tables.records.ApplicationRecord; +import com.nubeiot.edge.installer.model.tables.records.DeployTransactionRecord; import lombok.AccessLevel; import lombok.NoArgsConstructor; @@ -35,34 +39,34 @@ default List index() { } @NoArgsConstructor(access = AccessLevel.PRIVATE) - final class ApplicationMetadata implements StringKeyEntity { + final class ApplicationMetadata implements StringKeyEntity { public static final ApplicationMetadata INSTANCE = new ApplicationMetadata(); @Override - public @NonNull com.nubeiot.edge.installer.model.tables.TblModule table() { - return Tables.TBL_MODULE; + public @NonNull com.nubeiot.edge.installer.model.tables.Application table() { + return Tables.APPLICATION; } @Override - public @NonNull Class modelClass() { - return TblModule.class; + public @NonNull Class modelClass() { + return Application.class; } @Override - public @NonNull Class daoClass() { - return TblModuleDao.class; + public @NonNull Class daoClass() { + return ApplicationDao.class; } @Override - public @NonNull String requestKeyName() { return "service_id"; } + public @NonNull String requestKeyName() { return "app_id"; } @Override public @NonNull String singularKeyName() { return "app"; } @Override public @NonNull List> orderFields() { - return Arrays.asList(table().STATE, table().SERVICE_TYPE, table().SERVICE_ID); + return Arrays.asList(table().STATE, table().SERVICE_TYPE, table().APP_ID); } } @@ -70,23 +74,23 @@ final class ApplicationMetadata implements StringKeyEntity { + implements StringKeyEntity { public static final TransactionMetadata INSTANCE = new TransactionMetadata(); @Override - public @NonNull com.nubeiot.edge.installer.model.tables.TblTransaction table() { - return Tables.TBL_TRANSACTION; + public @NonNull com.nubeiot.edge.installer.model.tables.DeployTransaction table() { + return Tables.DEPLOY_TRANSACTION; } @Override - public @NonNull Class modelClass() { - return TblTransaction.class; + public @NonNull Class modelClass() { + return DeployTransaction.class; } @Override - public @NonNull Class daoClass() { - return TblTransactionDao.class; + public @NonNull Class daoClass() { + return DeployTransactionDao.class; } @Override @@ -97,7 +101,7 @@ final class TransactionMetadata @Override public @NonNull List> orderFields() { - return Arrays.asList(table().MODULE_ID, table().MODIFIED_AT.desc()); + return Arrays.asList(table().APP_ID, table().MODIFIED_AT.desc()); } } @@ -105,23 +109,23 @@ final class TransactionMetadata @NoArgsConstructor(access = AccessLevel.PRIVATE) final class HistoryMetadata - implements StringKeyEntity { + implements StringKeyEntity { public static final HistoryMetadata INSTANCE = new HistoryMetadata(); @Override - public @NonNull com.nubeiot.edge.installer.model.tables.TblRemoveHistory table() { - return Tables.TBL_REMOVE_HISTORY; + public @NonNull com.nubeiot.edge.installer.model.tables.ApplicationHistory table() { + return Tables.APPLICATION_HISTORY; } @Override - public @NonNull Class modelClass() { - return TblRemoveHistory.class; + public @NonNull Class modelClass() { + return ApplicationHistory.class; } @Override - public @NonNull Class daoClass() { - return TblRemoveHistoryDao.class; + public @NonNull Class daoClass() { + return ApplicationHistoryDao.class; } @Override @@ -132,7 +136,42 @@ final class HistoryMetadata @Override public @NonNull List> orderFields() { - return Arrays.asList(table().MODULE_ID, table().MODIFIED_AT.desc()); + return Arrays.asList(table().APP_ID, table().MODIFIED_AT.desc()); + } + + } + + + @NoArgsConstructor(access = AccessLevel.PRIVATE) + final class BackupMetadata + implements UUIDKeyEntity { + + public static final BackupMetadata INSTANCE = new BackupMetadata(); + + @Override + public @NonNull com.nubeiot.edge.installer.model.tables.ApplicationBackup table() { + return Tables.APPLICATION_BACKUP; + } + + @Override + public @NonNull Class modelClass() { + return ApplicationBackup.class; + } + + @Override + public @NonNull Class daoClass() { + return ApplicationBackupDao.class; + } + + @Override + public @NonNull String requestKeyName() { return "backup_id"; } + + @Override + public @NonNull String singularKeyName() { return "backup"; } + + @Override + public @NonNull List> orderFields() { + return Collections.singletonList(table().APP_ID); } } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java index 06250d609..0481a62a9 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionByAppService.java @@ -13,8 +13,8 @@ import com.nubeiot.core.exceptions.NotFoundException; import com.nubeiot.core.utils.Strings; import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblTransaction; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.interfaces.IDeployTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; import lombok.AccessLevel; import lombok.NonNull; @@ -33,7 +33,7 @@ public abstract class TransactionByAppService implements InstallerService { @Override public String servicePath() { - return "/:module_id/transaction"; + return "/:app_id/transaction"; } @Override @@ -43,19 +43,19 @@ public String paramPath() { @EventContractor(action = EventAction.GET_LIST, returnType = Single.class) public Single getList(RequestData data) { - final ITblTransaction transaction = new TblTransaction().fromJson(data.body()); - if (Strings.isBlank(transaction.getModuleId())) { + final IDeployTransaction transaction = new DeployTransaction().fromJson(data.body()); + if (Strings.isBlank(transaction.getAppId())) { throw new IllegalArgumentException("Service id is mandatory"); } if (data.filter().parseBoolean("last")) { - return this.entityHandler.findOneTransactionByModuleId(transaction.getModuleId()) + return this.entityHandler.findOneTransactionByModuleId(transaction.getAppId()) .map(o -> o.orElseThrow(() -> new NotFoundException( - String.format("Not found service id '%s'", transaction.getModuleId())))) + String.format("Not found service id '%s'", transaction.getAppId())))) .map(this::removePrevSystemConfig) .map(transactions -> new JsonObject().put("transactions", new JsonArray().add(transactions))); } - return this.entityHandler.findTransactionByModuleId(transaction.getModuleId()) + return this.entityHandler.findTransactionByModuleId(transaction.getAppId()) .flattenAsObservable(transactions -> transactions) .flatMapSingle(trans -> Single.just(removePrevSystemConfig(trans.toJson()))) .toList() diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java index 8c19382ff..dd8618d68 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/TransactionService.java @@ -10,12 +10,10 @@ import com.nubeiot.core.event.EventAction; import com.nubeiot.core.event.EventContractor; import com.nubeiot.core.exceptions.NotFoundException; -import com.nubeiot.core.exceptions.NubeException; -import com.nubeiot.core.exceptions.NubeException.ErrorCode; import com.nubeiot.core.utils.Strings; import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblTransaction; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.interfaces.IDeployTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; import lombok.AccessLevel; import lombok.NonNull; @@ -45,13 +43,12 @@ public final String paramPath() { @EventContractor(action = EventAction.GET_ONE, returnType = Single.class) public Single getOne(RequestData data) { final boolean includeSystemCfg = data.filter().parseBoolean("system_cfg"); - final ITblTransaction transaction = new TblTransaction().fromJson(data.body()); - if (Strings.isBlank(transaction.getTransactionId())) { - throw new NubeException(ErrorCode.INVALID_ARGUMENT, "Transaction Id cannot be blank"); - } - return this.entityHandler.findTransactionById(transaction.getTransactionId()) + final IDeployTransaction transaction = new DeployTransaction().fromJson(data.body()); + final String transactionId = Strings.requireNotBlank(transaction.getTransactionId(), + "Transaction Id cannot be blank"); + return this.entityHandler.findTransactionById(transactionId) .map(o -> o.orElseThrow(() -> new NotFoundException( - Strings.format("Not found transaction id '{0}'", transaction.getTransactionId())))) + Strings.format("Not found transaction id '{0}'", transactionId)))) .map(trans -> removePrevSystemConfig(trans, includeSystemCfg)); } diff --git a/core/installer/src/main/resources/ddl/01_ddl.sql b/core/installer/src/main/resources/ddl/01_ddl.sql index 0c8b67ce3..ce84efea0 100644 --- a/core/installer/src/main/resources/ddl/01_ddl.sql +++ b/core/installer/src/main/resources/ddl/01_ddl.sql @@ -1,5 +1,5 @@ -CREATE TABLE IF NOT EXISTS tbl_module ( - service_id varchar(127) NOT NULL, +CREATE TABLE IF NOT EXISTS application ( + app_id varchar(127) NOT NULL, service_name varchar(127) NOT NULL, service_type varchar(15) NOT NULL, version varchar(31) NOT NULL, @@ -11,13 +11,13 @@ CREATE TABLE IF NOT EXISTS tbl_module ( app_config_json text, system_config_json text, deploy_location varchar(500), - CONSTRAINT Pk_tbl_module PRIMARY KEY ( service_id ), - CONSTRAINT Unique_tbl_module UNIQUE ( service_name, service_type ) + CONSTRAINT Pk_application PRIMARY KEY ( app_id ), + CONSTRAINT Unique_application UNIQUE ( service_name, service_type ) ); -CREATE TABLE IF NOT EXISTS tbl_transaction ( +CREATE TABLE IF NOT EXISTS deploy_transaction ( transaction_id varchar(63) NOT NULL, - module_id varchar(127) NOT NULL, + app_id varchar(127) NOT NULL, event varchar(15) NOT NULL, status varchar(15) NOT NULL, issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -29,17 +29,17 @@ CREATE TABLE IF NOT EXISTS tbl_transaction ( prev_system_config_json text, last_error_json text, retry integer NOT NULL DEFAULT 0, - CONSTRAINT Pk_tbl_transaction PRIMARY KEY ( transaction_id ), - FOREIGN KEY ( module_id ) REFERENCES tbl_module( service_id ) + CONSTRAINT Pk_deploy_transaction PRIMARY KEY ( transaction_id ), + FOREIGN KEY ( app_id ) REFERENCES application( app_id ) ); -CREATE INDEX IF NOT EXISTS Idx_tbl_transaction_module_id ON tbl_transaction ( module_id ); +CREATE INDEX IF NOT EXISTS Idx_deploy_transaction_app_id ON deploy_transaction ( app_id ); -CREATE INDEX IF NOT EXISTS Idx_tbl_transaction_module_lifetime ON tbl_transaction ( module_id, issued_at ); +CREATE INDEX IF NOT EXISTS Idx_deploy_transaction_module_lifetime ON deploy_transaction ( app_id, issued_at ); -CREATE TABLE IF NOT EXISTS tbl_remove_history ( +CREATE TABLE IF NOT EXISTS application_history ( transaction_id varchar(63) NOT NULL, - module_id varchar(127) NOT NULL, + app_id varchar(127) NOT NULL, event varchar(15) NOT NULL, status varchar(15) NOT NULL, issued_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, @@ -50,5 +50,17 @@ CREATE TABLE IF NOT EXISTS tbl_remove_history ( prev_app_config_json text, prev_system_config_json text, retry integer NOT NULL DEFAULT 0, - CONSTRAINT Pk_tbl_remove_history PRIMARY KEY ( transaction_id ) + CONSTRAINT Pk_application_history PRIMARY KEY ( transaction_id ) + ); + + CREATE TABLE IF NOT EXISTS APPLICATION_BACKUP ( + ID uuid NOT NULL, + APP_ID varchar(127) , + STATUS varchar(15) NOT NULL, + DATA_DIR_JSON text, + INSTALLATION_DIR_JSON text, + ERROR_JSON text, + TIME_AUDIT varchar(500) , + SYNC_AUDIT clob(2147483647) , + CONSTRAINT PK_APPLICATION_BACKUP PRIMARY KEY ( ID ) ); diff --git a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java index abb0bd17e..ac18355ca 100644 --- a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java +++ b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerService.java @@ -1,8 +1,8 @@ package com.nubeiot.edge.installer.mock; import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.service.ApplicationService; import com.nubeiot.edge.installer.service.InstallerService; -import com.nubeiot.edge.installer.service.ModuleService; import com.nubeiot.edge.installer.service.TransactionService; import lombok.NonNull; @@ -14,12 +14,12 @@ default String api() { } default String appPath() { - return "/modules"; + return "/app"; } - class MockModuleService extends ModuleService implements MockInstallerService { + class MockApplicationService extends ApplicationService implements MockInstallerService { - public MockModuleService(@NonNull InstallerEntityHandler entityHandler) { + public MockApplicationService(@NonNull InstallerEntityHandler entityHandler) { super(entityHandler); } diff --git a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java index 1db4dd18d..f3745bff9 100644 --- a/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java +++ b/core/installer/src/test/java/com/nubeiot/edge/installer/mock/MockInstallerVerticle.java @@ -10,7 +10,7 @@ import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleType; import com.nubeiot.edge.installer.loader.ModuleTypeRule; -import com.nubeiot.edge.installer.mock.MockInstallerService.MockModuleService; +import com.nubeiot.edge.installer.mock.MockInstallerService.MockApplicationService; import com.nubeiot.edge.installer.mock.MockInstallerService.MockTransactionService; import com.nubeiot.edge.installer.service.AppDeployerDefinition; import com.nubeiot.edge.installer.service.InstallerService; @@ -44,7 +44,7 @@ public class MockInstallerVerticle extends InstallerVerticle { @Override protected @NonNull Supplier> services(@NonNull InstallerEntityHandler handler) { - return () -> Stream.of(new MockModuleService(handler), new MockTransactionService(handler)) + return () -> Stream.of(new MockApplicationService(handler), new MockTransactionService(handler)) .collect(Collectors.toSet()); } diff --git a/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockDeploymentService.java b/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockDeploymentService.java index be2971012..ca9b103bc 100644 --- a/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockDeploymentService.java +++ b/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockDeploymentService.java @@ -15,7 +15,7 @@ public class MockDeploymentService extends AppDeploymentService { @NonNull private final UUID mockDeployId; - MockDeploymentService(@NonNull InstallerEntityHandler entityHandler, @NonNull UUID mockDeployId) { + protected MockDeploymentService(@NonNull InstallerEntityHandler entityHandler, @NonNull UUID mockDeployId) { super(entityHandler); this.mockDeployId = mockDeployId; } diff --git a/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockFinisherService.java b/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockFinisherService.java index be8f54caa..6e5d2f0ee 100644 --- a/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockFinisherService.java +++ b/core/installer/src/test/java/com/nubeiot/edge/installer/service/MockFinisherService.java @@ -5,7 +5,7 @@ //TODO extends this for success/failed/timeout case and assert PostDeploymentResult public class MockFinisherService extends AppDeploymentFinisher { - MockFinisherService(InstallerEntityHandler entityHandler) { + protected MockFinisherService(InstallerEntityHandler entityHandler) { super(entityHandler); } diff --git a/core/sql/src/main/java/com/nubeiot/core/sql/SchemaHandler.java b/core/sql/src/main/java/com/nubeiot/core/sql/SchemaHandler.java index f54fc5e57..8625f3b5a 100644 --- a/core/sql/src/main/java/com/nubeiot/core/sql/SchemaHandler.java +++ b/core/sql/src/main/java/com/nubeiot/core/sql/SchemaHandler.java @@ -104,8 +104,8 @@ default boolean isNew(DSLContext dsl) { : migrator().execute(entityHandler); final EventbusClient c = entityHandler.eventClient(); final String address = readinessAddress(entityHandler); - return result.doOnError(t -> c.publish(address, EventMessage.initial(EventAction.NOTIFY_ERROR, - ErrorData.builder().throwable(t).build()))) + return result.doOnError(t -> c.publish(address, EventMessage.error(EventAction.NOTIFY_ERROR, + ErrorData.builder().throwable(t).build()))) .doOnSuccess(msg -> { final JsonObject headers = new JsonObject().put("status", msg.getStatus()) .put("action", msg.getAction()); diff --git a/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosEntityHandler.java b/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosEntityHandler.java index a9d184b97..5924cfa04 100644 --- a/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosEntityHandler.java +++ b/edge/bios/src/main/java/com/nubeiot/edge/bios/EdgeBiosEntityHandler.java @@ -10,8 +10,8 @@ import com.nubeiot.edge.installer.InstallerConfig; import com.nubeiot.edge.installer.InstallerConfig.RepositoryConfig; import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplication; +import com.nubeiot.edge.installer.model.tables.pojos.Application; public final class EdgeBiosEntityHandler extends InstallerEntityHandler { @@ -19,8 +19,8 @@ protected EdgeBiosEntityHandler(Configuration configuration, Vertx vertx) { super(configuration, vertx); } - protected AppConfig transformAppConfig(RepositoryConfig repoConfig, ITblModule tblModule, AppConfig appConfig) { - if (String.format("%s:%s", "com.nubeiot.edge.module", "installer").equals(tblModule.getServiceId())) { + protected AppConfig transformAppConfig(RepositoryConfig repoConfig, IApplication application, AppConfig appConfig) { + if (String.format("%s:%s", "com.nubeiot.edge.module", "installer").equals(application.getAppId())) { InstallerConfig installerConfig = new InstallerConfig(); installerConfig.setRepoConfig(repoConfig); return IConfig.merge(new JsonObject().put(installerConfig.key(), installerConfig.toJson()), appConfig, @@ -29,7 +29,7 @@ protected AppConfig transformAppConfig(RepositoryConfig repoConfig, ITblModule t return appConfig; } - protected TblModule decorateModule(TblModule m) { + protected Application decorateModule(Application m) { return super.decorateModule(m).setPublishedBy("NubeIO"); } diff --git a/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosApplicationService.java b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosApplicationService.java new file mode 100644 index 000000000..6a4c07780 --- /dev/null +++ b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosApplicationService.java @@ -0,0 +1,12 @@ +package com.nubeiot.edge.bios.service; + +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.service.ApplicationService; + +public final class BiosApplicationService extends ApplicationService implements BiosInstallerService { + + public BiosApplicationService(InstallerEntityHandler entityHandler) { + super(entityHandler); + } + +} diff --git a/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosBackupByAppService.java b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosBackupByAppService.java new file mode 100644 index 000000000..a415b600d --- /dev/null +++ b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosBackupByAppService.java @@ -0,0 +1,14 @@ +package com.nubeiot.edge.bios.service; + +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.service.BackupByAppService; + +import lombok.NonNull; + +public final class BiosBackupByAppService extends BackupByAppService implements BiosInstallerService { + + protected BiosBackupByAppService(@NonNull InstallerEntityHandler entityHandler) { + super(entityHandler); + } + +} diff --git a/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosModuleService.java b/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosModuleService.java deleted file mode 100644 index c3aceb54d..000000000 --- a/edge/bios/src/main/java/com/nubeiot/edge/bios/service/BiosModuleService.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.nubeiot.edge.bios.service; - -import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.service.ModuleService; - -public final class BiosModuleService extends ModuleService implements BiosInstallerService { - - public BiosModuleService(InstallerEntityHandler entityHandler) { - super(entityHandler); - } - -} diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/BaseInstallerVerticleTest.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/BaseInstallerVerticleTest.java index ebfd88837..5d6312767 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/BaseInstallerVerticleTest.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/BaseInstallerVerticleTest.java @@ -36,10 +36,10 @@ import com.nubeiot.core.event.EventPattern; import com.nubeiot.core.sql.SqlConfig; import com.nubeiot.core.statemachine.StateMachine; -import com.nubeiot.edge.bios.service.BiosModuleService; +import com.nubeiot.edge.bios.service.BiosApplicationService; import com.nubeiot.edge.installer.InstallerVerticle; -import com.nubeiot.edge.installer.model.tables.daos.TblModuleDao; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationDao; +import com.nubeiot.edge.installer.model.tables.pojos.Application; import lombok.NonNull; @@ -113,9 +113,9 @@ protected NubeConfig getNubeConfig() { return nubeConfig; } - protected void insertModule(TestContext context, TblModule module) { + protected void insertModule(TestContext context, Application module) { Async async = context.async(1); - installerVerticle.getEntityHandler().moduleDao().insert(module).subscribe(result -> { + installerVerticle.getEntityHandler().applicationDao().insert(module).subscribe(result -> { System.out.println("Insert module successfully!"); TestHelper.testComplete(async); }, error -> { @@ -143,8 +143,9 @@ protected void testingDBUpdated(TestContext context, State expectedModuleState, private void assertTransaction(TestContext context, Status expectedTransactionStatus, Async async, CountDownLatch latch) { - installerVerticle.getEntityHandler().transDao() - .findManyByModuleId(Collections.singletonList(BaseInstallerVerticleTest.MODULE_ID)) + installerVerticle.getEntityHandler() + .transDao() + .findManyByAppId(Collections.singletonList(BaseInstallerVerticleTest.MODULE_ID)) .subscribe(result -> { context.assertNotNull(result); context.assertFalse(result.isEmpty()); @@ -164,16 +165,17 @@ private void assertTransaction(TestContext context, Status expectedTransactionSt private void assertModule(TestContext context, State expectedModuleState, JsonObject expectedConfig, Async async, CountDownLatch latch) { - installerVerticle.getEntityHandler().moduleDao() + installerVerticle.getEntityHandler() + .applicationDao() .findOneById(BaseInstallerVerticleTest.MODULE_ID) .subscribe(result -> { - TblModule tblModule = result.orElse(null); - context.assertNotNull(tblModule); - if (tblModule.getState() != State.PENDING) { + Application application = result.orElse(null); + context.assertNotNull(application); + if (application.getState() != State.PENDING) { latch.countDown(); System.out.println("Ready. Testing module"); - context.assertEquals(tblModule.getState(), expectedModuleState); - JsonObject actualConfig = IConfig.from(tblModule.getAppConfig(), AppConfig.class) + context.assertEquals(application.getState(), expectedModuleState); + JsonObject actualConfig = IConfig.from(application.getAppConfig(), AppConfig.class) .toJson(); JsonHelper.assertJson(context, async, expectedConfig, actualConfig, JSONCompareMode.STRICT); @@ -188,21 +190,21 @@ private void assertModule(TestContext context, State expectedModuleState, JsonOb void executeThenAssert(EventAction action, TestContext context, JsonObject body, Handler handler) { installerVerticle.getEventbusClient() - .fire(DeliveryEvent.from(BiosModuleService.class.getName(), EventPattern.REQUEST_RESPONSE, + .fire(DeliveryEvent.from(BiosApplicationService.class.getName(), EventPattern.REQUEST_RESPONSE, action, RequestData.builder().body(body).build().toJson()), EventbusHelper.replyAsserter(context, handler)); } protected void assertModuleState(TestContext context, Async async, State expectedState, String moduleId) { - final TblModuleDao moduleDao = this.installerVerticle.getEntityHandler().moduleDao(); + final ApplicationDao moduleDao = this.installerVerticle.getEntityHandler().applicationDao(); CountDownLatch latch = new CountDownLatch(1); long timer = this.vertx.setPeriodic(1000, event -> moduleDao.findOneById(moduleId).subscribe(result -> { - TblModule tblModule = result.orElse(null); - context.assertNotNull(tblModule); - if (tblModule.getState() != State.PENDING) { + Application application = result.orElse(null); + context.assertNotNull(application); + if (application.getState() != State.PENDING) { System.out.println("Checking state of " + moduleId); if (Objects.nonNull(expectedState)) { - context.assertEquals(tblModule.getState(), expectedState); + context.assertEquals(application.getState(), expectedState); } latch.countDown(); TestHelper.testComplete(async); diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeleteTest.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeleteTest.java index a94a2e4bd..5ecdac061 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeleteTest.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeleteTest.java @@ -25,10 +25,10 @@ import com.nubeiot.core.exceptions.NubeException.ErrorCode; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.bios.loader.DeploymentAsserter; -import com.nubeiot.edge.bios.service.BiosModuleService; +import com.nubeiot.edge.bios.service.BiosApplicationService; import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.pojos.Application; @Ignore public class HandlerDeleteTest extends BaseInstallerVerticleTest { @@ -36,14 +36,14 @@ public class HandlerDeleteTest extends BaseInstallerVerticleTest { @Before public void before(TestContext context) { super.before(context); - this.insertModule(context, new TblModule().setServiceId(MODULE_ID) - .setServiceType(ModuleType.JAVA) - .setServiceName(SERVICE_NAME) - .setState(State.ENABLED) - .setVersion(VERSION) - .setSystemConfig(APP_SYSTEM_CONFIG) - .setAppConfig(APP_CONFIG) - .setModifiedAt(DateTimes.now())); + this.insertModule(context, new Application().setAppId(MODULE_ID) + .setServiceType(ModuleType.JAVA) + .setServiceName(SERVICE_NAME) + .setState(State.ENABLED) + .setVersion(VERSION) + .setSystemConfig(APP_SYSTEM_CONFIG) + .setAppConfig(APP_CONFIG) + .setModifiedAt(DateTimes.now())); } @Override @@ -56,24 +56,24 @@ public void test_delete_should_success(TestContext context) { JsonObject body = new JsonObject().put("service_id", MODULE_ID); Async async = context.async(); installerVerticle.getEventbusClient() - .fire(DeliveryEvent.from(BiosModuleService.class.getName(), EventPattern.REQUEST_RESPONSE, + .fire(DeliveryEvent.from(BiosApplicationService.class.getName(), EventPattern.REQUEST_RESPONSE, EventAction.REMOVE, RequestData.builder().body(body).build().toJson()), EventbusHelper.replyAsserter(context, resp -> { - System.out.println(resp); - context.assertEquals(resp.getString("status"), Status.SUCCESS.name()); - TestHelper.testComplete(async); - })); + System.out.println(resp); + context.assertEquals(resp.getString("status"), Status.SUCCESS.name()); + TestHelper.testComplete(async); + })); CountDownLatch latch = new CountDownLatch(2); Async async2 = context.async(2); //Event module is deployed/updated successfully, we still have a gap for DB update. long timer = this.vertx.setPeriodic(1000, event -> { - installerVerticle.getEntityHandler().moduleDao().findOneById(GROUP_ID).subscribe(result -> { - TblModule tblModule = result.orElse(null); - if (Objects.nonNull(tblModule) && tblModule.getState() != State.PENDING) { + installerVerticle.getEntityHandler().applicationDao().findOneById(GROUP_ID).subscribe(result -> { + Application application = result.orElse(null); + if (Objects.nonNull(application) && application.getState() != State.PENDING) { return; } - context.assertNull(tblModule); + context.assertNull(application); TestHelper.testComplete(async2); latch.countDown(); }, error -> { @@ -81,19 +81,20 @@ public void test_delete_should_success(TestContext context) { context.fail(error); TestHelper.testComplete(async2); }); - installerVerticle.getEntityHandler().transDao() - .findManyByModuleId(Collections.singletonList(MODULE_ID)) + installerVerticle.getEntityHandler() + .transDao() + .findManyByAppId(Collections.singletonList(MODULE_ID)) .subscribe(result -> { - if (!Objects.nonNull(result) || result.isEmpty() || - result.get(0).getStatus() != Status.WIP) { - TestHelper.testComplete(async2); - latch.countDown(); - } - }, error -> { - latch.countDown(); - context.fail(error); - TestHelper.testComplete(async2); - }); + if (!Objects.nonNull(result) || result.isEmpty() || + result.get(0).getStatus() != Status.WIP) { + TestHelper.testComplete(async2); + latch.countDown(); + } + }, error -> { + latch.countDown(); + context.fail(error); + TestHelper.testComplete(async2); + }); }); stopTimer(context, latch, timer); } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeployFailedTest.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeployFailedTest.java index 39b3f859b..2261d7595 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeployFailedTest.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerDeployFailedTest.java @@ -13,7 +13,7 @@ import com.nubeiot.edge.bios.loader.DeploymentAsserter; import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.pojos.Application; @Ignore public class HandlerDeployFailedTest extends BaseInstallerVerticleTest { @@ -81,14 +81,14 @@ public void test_delete_when_deploy_failed(TestContext context) { } private void createService(TestContext context) { - this.insertModule(context, new TblModule().setServiceId(MODULE_ID) - .setServiceType(ModuleType.JAVA) - .setServiceName(SERVICE_NAME) - .setState(State.ENABLED) - .setVersion(VERSION) - .setAppConfig(APP_CONFIG) - .setSystemConfig(APP_SYSTEM_CONFIG) - .setModifiedAt(DateTimes.now())); + this.insertModule(context, new Application().setAppId(MODULE_ID) + .setServiceType(ModuleType.JAVA) + .setServiceName(SERVICE_NAME) + .setState(State.ENABLED) + .setVersion(VERSION) + .setAppConfig(APP_CONFIG) + .setSystemConfig(APP_SYSTEM_CONFIG) + .setModifiedAt(DateTimes.now())); } } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerUpdateAndPatchTest.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerUpdateAndPatchTest.java index 15d0e0e04..fc6ca3f09 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerUpdateAndPatchTest.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/HandlerUpdateAndPatchTest.java @@ -15,7 +15,7 @@ import com.nubeiot.edge.bios.loader.DeploymentAsserter; import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.pojos.Application; @Ignore public class HandlerUpdateAndPatchTest extends BaseInstallerVerticleTest { @@ -23,14 +23,14 @@ public class HandlerUpdateAndPatchTest extends BaseInstallerVerticleTest { @Before public void before(TestContext context) { super.before(context); - this.insertModule(context, new TblModule().setServiceId(MODULE_ID) - .setServiceType(ModuleType.JAVA) - .setServiceName(SERVICE_NAME) - .setState(State.ENABLED) - .setVersion(VERSION) - .setAppConfig(APP_CONFIG) - .setSystemConfig(APP_SYSTEM_CONFIG) - .setModifiedAt(DateTimes.now())); + this.insertModule(context, new Application().setAppId(MODULE_ID) + .setServiceType(ModuleType.JAVA) + .setServiceName(SERVICE_NAME) + .setState(State.ENABLED) + .setVersion(VERSION) + .setAppConfig(APP_CONFIG) + .setSystemConfig(APP_SYSTEM_CONFIG) + .setModifiedAt(DateTimes.now())); } @Override diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/ServiceNameDuplicationTest.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/ServiceNameDuplicationTest.java index ab254853f..51d6d849e 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/ServiceNameDuplicationTest.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/ServiceNameDuplicationTest.java @@ -14,7 +14,7 @@ import com.nubeiot.edge.bios.loader.DeploymentAsserter; import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.pojos.Application; @Ignore public class ServiceNameDuplicationTest extends BaseInstallerVerticleTest { @@ -22,14 +22,14 @@ public class ServiceNameDuplicationTest extends BaseInstallerVerticleTest { @Before public void before(TestContext context) { super.before(context); - this.insertModule(context, new TblModule().setServiceId(MODULE_ID) - .setServiceType(ModuleType.JAVA) - .setServiceName(SERVICE_NAME) - .setState(State.ENABLED) - .setVersion(VERSION) - .setSystemConfig(APP_SYSTEM_CONFIG) - .setAppConfig(APP_CONFIG) - .setModifiedAt(DateTimes.now())); + this.insertModule(context, new Application().setAppId(MODULE_ID) + .setServiceType(ModuleType.JAVA) + .setServiceName(SERVICE_NAME) + .setState(State.ENABLED) + .setVersion(VERSION) + .setSystemConfig(APP_SYSTEM_CONFIG) + .setAppConfig(APP_CONFIG) + .setModifiedAt(DateTimes.now())); } @Override diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/loader/DeploymentAsserter.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/loader/DeploymentAsserter.java index 5cd5697fb..bf45d7933 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/loader/DeploymentAsserter.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/loader/DeploymentAsserter.java @@ -13,7 +13,7 @@ import com.nubeiot.core.enums.Status; import com.nubeiot.core.event.EventAction; import com.nubeiot.core.event.EventMessage; -import com.nubeiot.edge.bios.service.BiosModuleService; +import com.nubeiot.edge.bios.service.BiosApplicationService; import com.nubeiot.edge.bios.service.BiosTransactionService; import com.nubeiot.edge.installer.model.dto.PreDeploymentResult; @@ -34,7 +34,7 @@ static DeploymentAsserter init(Vertx vertx, TestContext context) { RequestData.builder().body(transactionBody).build()); final Async async = context.async(2); - vertx.eventBus().send(BiosModuleService.class.getName(), serviceMessage.toJson(), result -> { + vertx.eventBus().send(BiosApplicationService.class.getName(), serviceMessage.toJson(), result -> { System.out.println("Asserting module"); JsonObject body = (JsonObject) result.result().body(); context.assertEquals(body.getString("status"), Status.SUCCESS.name()); diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/EnabledModuleInitData.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/EnabledModuleInitData.java index d7e6bcdee..92a6a1b0a 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/EnabledModuleInitData.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/EnabledModuleInitData.java @@ -9,7 +9,7 @@ import com.nubeiot.core.enums.State; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.pojos.Application; public class EnabledModuleInitData extends MockInitDataEntityHandler { @@ -19,15 +19,15 @@ protected EnabledModuleInitData(Configuration configuration, Vertx vertx) { @Override protected Single initModules() { - return tblModuleDao.insert(new TblModule().setServiceId("enabled-service") - .setServiceName("service0") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.ENABLED) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject())); + return applicationDao.insert(new Application().setAppId("enabled-service") + .setServiceName("service0") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.ENABLED) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject())); } } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/InvalidModulesInitData.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/InvalidModulesInitData.java index a0b2e0878..6e55bb5a2 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/InvalidModulesInitData.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/InvalidModulesInitData.java @@ -15,8 +15,8 @@ import com.nubeiot.core.event.EventAction; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; public class InvalidModulesInitData extends MockInitDataEntityHandler { @@ -26,111 +26,112 @@ protected InvalidModulesInitData(Configuration configuration, Vertx vertx) { @Override protected Single initModules() { - final TblModule service5 = new TblModule().setServiceId( + final Application service5 = new Application().setAppId( "pending-service-with-transaction-is-wip-prestate-action-is-update-disabled") - .setServiceName("service5") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject()); - Single insert05 = tblModuleDao.insert(service5); + .setServiceName("service5") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject()); + Single insert05 = applicationDao.insert(service5); Single insertTransaction05 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId(service5.getServiceId()) - .setStatus(Status.WIP) - .setEvent(EventAction.UPDATE) - .setModifiedAt(DateTimes.now()) - .setPrevMetadata(new JsonObject( - "{\"service_id\": \"pending-service-with-transaction-is-wip-prestate-action-is" + - "-patch-disabled\",\"service_name\": \"service6\",\"service_type\": \"JAVA\"," + - "\"version\": \"1.0.0\",\"published_by\": null,\"state\": \"DISABLED\"," + - "\"created_at\": \"2019-05-02T09:15:37.230Z\"," + - "\"modified_at\": \"2019-05-02T09:15:37.230Z\",\"deploy_id\": null," + - "\"deploy_config\": {},\"deploy_location\": null }"))); - - final TblModule service6 = new TblModule().setServiceId( + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId(service5.getAppId()) + .setStatus(Status.WIP) + .setEvent(EventAction.UPDATE) + .setModifiedAt(DateTimes.now()) + .setPrevMetadata(new JsonObject( + "{\"service_id\": \"pending-service-with-transaction-is-wip-prestate-action-is" + + "-patch-disabled\",\"service_name\": \"service6\",\"service_type\": \"JAVA\"," + + "\"version\": \"1.0.0\",\"published_by\": null,\"state\": \"DISABLED\"," + + "\"created_at\": \"2019-05-02T09:15:37.230Z\"," + + "\"modified_at\": \"2019-05-02T09:15:37.230Z\",\"deploy_id\": null," + + "\"deploy_config\": {},\"deploy_location\": null }"))); + + final Application service6 = new Application().setAppId( "pending-service-with-transaction-is-wip-prestate-action-is-patch-disabled") - .setServiceName("service6") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject()); - Single insert06 = tblModuleDao.insert(service6); + .setServiceName("service6") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject()); + Single insert06 = applicationDao.insert(service6); Single insertTransaction06 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId(service6.getServiceId()) - .setStatus(Status.WIP) - .setEvent(EventAction.PATCH) - .setModifiedAt(DateTimes.now()) - .setPrevMetadata(new JsonObject( - "{\"service_id\":\"pending-service-with-transaction-is-wip-prestate-action-is" + - "-update-disabled\",\"service_name" + "\":\"service5\",\"service_type\":\"JAVA\"," + - "\"version\":\"1.0.0\"," + "\"published_by\":null," + "\"state\":\"DISABLED\"," + - "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + - "\"modified_at\":\"2019-05-02T09:15:37.230Z\",\"deploy_id\":null," + - "\"deploy_config\":{}," + "\"deploy_location\":null}\t "))); - - Single insert07 = tblModuleDao.insert(new TblModule().setServiceId("disabled-module") - .setServiceName("service7") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.DISABLED) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setAppConfig(new JsonObject()) - .setSystemConfig(new JsonObject())); - - Single insert09 = tblModuleDao.insert( - new TblModule().setServiceId("pending_module_with_two_transactions_invalid") - .setServiceName("service9") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject())); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId(service6.getAppId()) + .setStatus(Status.WIP) + .setEvent(EventAction.PATCH) + .setModifiedAt(DateTimes.now()) + .setPrevMetadata(new JsonObject( + "{\"service_id\":\"pending-service-with-transaction-is-wip-prestate-action-is" + + "-update-disabled\",\"service_name" + + "\":\"service5\",\"service_type\":\"JAVA\"," + "\"version\":\"1.0.0\"," + + "\"published_by\":null," + "\"state\":\"DISABLED\"," + + "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + + "\"modified_at\":\"2019-05-02T09:15:37.230Z\",\"deploy_id\":null," + + "\"deploy_config\":{}," + "\"deploy_location\":null}\t "))); + + Single insert07 = applicationDao.insert(new Application().setAppId("disabled-module") + .setServiceName("service7") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.DISABLED) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setAppConfig(new JsonObject()) + .setSystemConfig(new JsonObject())); + + Single insert09 = applicationDao.insert( + new Application().setAppId("pending_module_with_two_transactions_invalid") + .setServiceName("service9") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject())); Single insertTransaction09_1 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending_module_with_two_transactions_invalid") - .setStatus(Status.WIP) - .setEvent(EventAction.CREATE) - .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 25, 0, ZoneOffset.UTC))); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending_module_with_two_transactions_invalid") + .setStatus(Status.WIP) + .setEvent(EventAction.CREATE) + .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 25, 0, ZoneOffset.UTC))); Single insertTransaction09_2 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending_module_with_two_transactions_invalid") - .setStatus(Status.WIP) - .setEvent(EventAction.PATCH) - .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 30, 0, ZoneOffset.UTC)) - .setPrevMetadata(new JsonObject( - "{\"service_id\":\"pending_module_with_two_transactions_invalid\"," + - "\"service_name\":\"service9\",\"service_type\":\"JAVA\"," + - "\"version\":\"1.0.0\",\"published_by\":null,\"state\":\"DISABLED\"," + - "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + - "\"modified_at\":\"2019-05-02T09:15:37.230Z\",\"deploy_id\":null," + - "\"deploy_config\":{}," + "\"deploy_location\":null}"))); - - Single insert10 = tblModuleDao.insert(new TblModule().setServiceId("pending-but-failed-module") - .setServiceName("service10") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now())); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending_module_with_two_transactions_invalid") + .setStatus(Status.WIP) + .setEvent(EventAction.PATCH) + .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 30, 0, ZoneOffset.UTC)) + .setPrevMetadata(new JsonObject( + "{\"service_id\":\"pending_module_with_two_transactions_invalid\"," + + "\"service_name\":\"service9\",\"service_type\":\"JAVA\"," + + "\"version\":\"1.0.0\",\"published_by\":null,\"state\":\"DISABLED\"," + + "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + + "\"modified_at\":\"2019-05-02T09:15:37.230Z\",\"deploy_id\":null," + + "\"deploy_config\":{}," + "\"deploy_location\":null}"))); + + Single insert10 = applicationDao.insert(new Application().setAppId("pending-but-failed-module") + .setServiceName("service10") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now())); Single insertTransaction10 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending-but-failed-module") - .setStatus(Status.FAILED) - .setEvent(EventAction.CREATE) - .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 30, 0, ZoneOffset.UTC))); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending-but-failed-module") + .setStatus(Status.FAILED) + .setEvent(EventAction.CREATE) + .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 30, 0, ZoneOffset.UTC))); final Single insertModules = Single.zip(insert05, insert06, insert07, insert09, insert10, (r1, r2, r3, r4, r5) -> r1 + r2 + r3 + r4 + r5); diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/MockInitDataEntityHandler.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/MockInitDataEntityHandler.java index 38d29a51e..cf15c1dee 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/MockInitDataEntityHandler.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/MockInitDataEntityHandler.java @@ -8,19 +8,19 @@ import com.nubeiot.core.NubeConfig.AppConfig; import com.nubeiot.edge.installer.InstallerConfig.RepositoryConfig; import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.model.tables.daos.TblModuleDao; -import com.nubeiot.edge.installer.model.tables.daos.TblTransactionDao; -import com.nubeiot.edge.installer.model.tables.interfaces.ITblModule; +import com.nubeiot.edge.installer.model.tables.daos.ApplicationDao; +import com.nubeiot.edge.installer.model.tables.daos.DeployTransactionDao; +import com.nubeiot.edge.installer.model.tables.interfaces.IApplication; abstract class MockInitDataEntityHandler extends InstallerEntityHandler { - final TblModuleDao tblModuleDao; - final TblTransactionDao tblTransactionDao; + final ApplicationDao applicationDao; + final DeployTransactionDao tblTransactionDao; MockInitDataEntityHandler(Configuration configuration, Vertx vertx) { super(configuration, vertx); - this.tblModuleDao = dao(TblModuleDao.class); - this.tblTransactionDao = dao(TblTransactionDao.class); + this.applicationDao = applicationDao(); + this.tblTransactionDao = transDao(); } // @Override @@ -32,7 +32,7 @@ abstract class MockInitDataEntityHandler extends InstallerEntityHandler { // } @Override - protected AppConfig transformAppConfig(RepositoryConfig repoConfig, ITblModule tblModule, AppConfig appConfig) { + protected AppConfig transformAppConfig(RepositoryConfig repoConfig, IApplication tblModule, AppConfig appConfig) { return appConfig; } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithCreateActionInitData.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithCreateActionInitData.java index 0494f43e9..926783b91 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithCreateActionInitData.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithCreateActionInitData.java @@ -13,8 +13,8 @@ import com.nubeiot.core.event.EventAction; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; public class PendingModuleWithCreateActionInitData extends MockInitDataEntityHandler { @@ -24,20 +24,22 @@ protected PendingModuleWithCreateActionInitData(Configuration configuration, Ver @Override protected Single initModules() { - Single insert02 = tblModuleDao.insert( - new TblModule().setServiceId("pending-service-with-transaction-is-wip-prestate-action-is-create") - .setServiceName("service2") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject())); + Single insert02 = applicationDao.insert( + new Application().setAppId("pending-service-with-transaction-is-wip-prestate-action-is-create") + .setServiceName("service2") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject())); Single insertTransaction02 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending-service-with-transaction-is-wip-prestate-action-is-create") - .setStatus(Status.WIP).setEvent(EventAction.CREATE).setModifiedAt(DateTimes.now())); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending-service-with-transaction-is-wip-prestate-action-is-create") + .setStatus(Status.WIP) + .setEvent(EventAction.CREATE) + .setModifiedAt(DateTimes.now())); return Single.zip(insert02, insertTransaction02, Integer::sum); } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithInitActionInitData.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithInitActionInitData.java index 96036f49e..14036c491 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithInitActionInitData.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithInitActionInitData.java @@ -13,8 +13,8 @@ import com.nubeiot.core.event.EventAction; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; public class PendingModuleWithInitActionInitData extends MockInitDataEntityHandler { @@ -24,20 +24,22 @@ protected PendingModuleWithInitActionInitData(Configuration configuration, Vertx @Override protected Single initModules() { - Single insert01 = tblModuleDao.insert( - new TblModule().setServiceId("pending-service-with-transaction-is-wip-prestate-action-is-init") - .setServiceName("service1") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject())); + Single insert01 = applicationDao.insert( + new Application().setAppId("pending-service-with-transaction-is-wip-prestate-action-is-init") + .setServiceName("service1") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject())); Single insertTransaction01 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending-service-with-transaction-is-wip-prestate-action-is-init") - .setStatus(Status.WIP).setEvent(EventAction.INIT).setModifiedAt(DateTimes.now())); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending-service-with-transaction-is-wip-prestate-action-is-init") + .setStatus(Status.WIP) + .setEvent(EventAction.INIT) + .setModifiedAt(DateTimes.now())); return Single.zip(insert01, insertTransaction01, Integer::sum); } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithPatchActionInitData.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithPatchActionInitData.java index 7f4109cc7..322e0e27a 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithPatchActionInitData.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithPatchActionInitData.java @@ -13,8 +13,8 @@ import com.nubeiot.core.event.EventAction; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; public class PendingModuleWithPatchActionInitData extends MockInitDataEntityHandler { @@ -24,31 +24,31 @@ protected PendingModuleWithPatchActionInitData(Configuration configuration, Vert @Override protected Single initModules() { - Single insert04 = tblModuleDao.insert( - new TblModule().setServiceId("pending-service-with-transaction-is-wip-prestate-action-is-patch") - .setServiceName("service4") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject())); + Single insert04 = applicationDao.insert( + new Application().setAppId("pending-service-with-transaction-is-wip-prestate-action-is-patch") + .setServiceName("service4") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject())); Single insertTransaction04 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending-service-with-transaction-is-wip-prestate-action-is-patch") - .setStatus(Status.WIP) - .setEvent(EventAction.PATCH) - .setModifiedAt(DateTimes.now()) - .setPrevMetadata(new JsonObject( - "{\"service_id\":\"pending-service-with-transaction-is-wip" + - "-prestate-action-is-patch\"," + - "\"service_name\":\"service4\",\"service_type\":\"JAVA\"," + - "\"version\":\"1.0.0\",\"published_by\":null," + "\"state\":\"PENDING\"," + - "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + - "\"modified_at\":\"2019-05-02T09:15:37.230Z\"," + - "\"deploy_id\":null,\"deploy_config\":{}," + "\"deploy_location\":null}\t"))); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending-service-with-transaction-is-wip-prestate-action-is-patch") + .setStatus(Status.WIP) + .setEvent(EventAction.PATCH) + .setModifiedAt(DateTimes.now()) + .setPrevMetadata(new JsonObject( + "{\"service_id\":\"pending-service-with-transaction-is-wip" + + "-prestate-action-is-patch\"," + + "\"service_name\":\"service4\",\"service_type\":\"JAVA\"," + + "\"version\":\"1.0.0\",\"published_by\":null," + "\"state\":\"PENDING\"," + + "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + + "\"modified_at\":\"2019-05-02T09:15:37.230Z\"," + + "\"deploy_id\":null,\"deploy_config\":{}," + "\"deploy_location\":null}\t"))); return Single.zip(insert04, insertTransaction04, Integer::sum); } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithTwoTransactionsInitData.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithTwoTransactionsInitData.java index 78ab9d5e2..67e5fa22a 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithTwoTransactionsInitData.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithTwoTransactionsInitData.java @@ -15,8 +15,8 @@ import com.nubeiot.core.event.EventAction; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; public class PendingModuleWithTwoTransactionsInitData extends MockInitDataEntityHandler { @@ -26,36 +26,36 @@ protected PendingModuleWithTwoTransactionsInitData(Configuration configuration, @Override protected Single initModules() { - Single insert08 = tblModuleDao.insert( - new TblModule().setServiceId("pending_module_with_two_transactions") - .setServiceName("service8") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject())); + Single insert08 = applicationDao.insert( + new Application().setAppId("pending_module_with_two_transactions") + .setServiceName("service8") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject())); Single insertTransaction08_1 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending_module_with_two_transactions") - .setStatus(Status.WIP) - .setEvent(EventAction.PATCH) - .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 25, 0, ZoneOffset.UTC)) - .setPrevMetadata(new JsonObject( - "{\"service_id" + "\":\"pending_module_with_two_transactions\"," + - "\"service_name" + "\":\"service5" + "\",\"service_type\":\"JAVA\"," + - "\"version\":\"1.0.0\"," + "\"published_by\":null," + "\"state\":\"DISABLED\"," + - "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + - "\"modified_at\":\"2019-05-02T09:15:37.230Z\",\"deploy_id\":null," + - "\"deploy_config\":{},\"deploy_location\":null}\t "))); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending_module_with_two_transactions") + .setStatus(Status.WIP) + .setEvent(EventAction.PATCH) + .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 25, 0, ZoneOffset.UTC)) + .setPrevMetadata(new JsonObject( + "{\"service_id" + "\":\"pending_module_with_two_transactions\"," + + "\"service_name" + "\":\"service5" + "\",\"service_type\":\"JAVA\"," + + "\"version\":\"1.0.0\"," + "\"published_by\":null," + "\"state\":\"DISABLED\"," + + "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + + "\"modified_at\":\"2019-05-02T09:15:37.230Z\",\"deploy_id\":null," + + "\"deploy_config\":{},\"deploy_location\":null}\t "))); Single insertTransaction08_2 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending_module_with_two_transactions") - .setStatus(Status.WIP) - .setEvent(EventAction.CREATE) - .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 30, 0, ZoneOffset.UTC))); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending_module_with_two_transactions") + .setStatus(Status.WIP) + .setEvent(EventAction.CREATE) + .setModifiedAt(OffsetDateTime.of(2019, 5, 3, 12, 20, 30, 0, ZoneOffset.UTC))); return Single.zip(insert08, insertTransaction08_1, insertTransaction08_2, (r1, r2, r3) -> r1 + r2 + r3); } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithUpdateActionInitData.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithUpdateActionInitData.java index 27e8b18c7..e943c3d03 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithUpdateActionInitData.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/startupmodules/handler/PendingModuleWithUpdateActionInitData.java @@ -13,8 +13,8 @@ import com.nubeiot.core.event.EventAction; import com.nubeiot.core.utils.DateTimes; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; -import com.nubeiot.edge.installer.model.tables.pojos.TblTransaction; +import com.nubeiot.edge.installer.model.tables.pojos.Application; +import com.nubeiot.edge.installer.model.tables.pojos.DeployTransaction; public class PendingModuleWithUpdateActionInitData extends MockInitDataEntityHandler { @@ -24,31 +24,31 @@ protected PendingModuleWithUpdateActionInitData(Configuration configuration, Ver @Override protected Single initModules() { - Single insert03 = tblModuleDao.insert( - new TblModule().setServiceId("pending-service-with-transaction-is-wip-prestate-action-is-update") - .setServiceName("service3") - .setServiceType(ModuleType.JAVA) - .setVersion("1.0.0") - .setState(State.PENDING) - .setCreatedAt(DateTimes.now()) - .setModifiedAt(DateTimes.now()) - .setSystemConfig(new JsonObject()) - .setAppConfig(new JsonObject())); + Single insert03 = applicationDao.insert( + new Application().setAppId("pending-service-with-transaction-is-wip-prestate-action-is-update") + .setServiceName("service3") + .setServiceType(ModuleType.JAVA) + .setVersion("1.0.0") + .setState(State.PENDING) + .setCreatedAt(DateTimes.now()) + .setModifiedAt(DateTimes.now()) + .setSystemConfig(new JsonObject()) + .setAppConfig(new JsonObject())); Single insertTransaction03 = tblTransactionDao.insert( - new TblTransaction().setTransactionId(UUID.randomUUID().toString()) - .setModuleId("pending-service-with-transaction-is-wip-prestate-action-is-update") - .setStatus(Status.WIP) - .setEvent(EventAction.UPDATE) - .setModifiedAt(DateTimes.now()) - .setPrevMetadata(new JsonObject( - "{\"service_id\":\"pending-service-with-transaction-is-wip" + - "-prestate-action-is-update\"," + - "\"service_name\":\"service3\",\"service_type\":\"JAVA\"," + - "\"version\":\"1.0.0\",\"published_by\":null," + "\"state\":\"PENDING\"," + - "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + - "\"modified_at\":\"2019-05-02T09:15:37.230Z\"," + - "\"deploy_id\":null,\"deploy_config\":{}," + "\"deploy_location\":null}\t"))); + new DeployTransaction().setTransactionId(UUID.randomUUID().toString()) + .setAppId("pending-service-with-transaction-is-wip-prestate-action-is-update") + .setStatus(Status.WIP) + .setEvent(EventAction.UPDATE) + .setModifiedAt(DateTimes.now()) + .setPrevMetadata(new JsonObject( + "{\"service_id\":\"pending-service-with-transaction-is-wip" + + "-prestate-action-is-update\"," + + "\"service_name\":\"service3\",\"service_type\":\"JAVA\"," + + "\"version\":\"1.0.0\",\"published_by\":null," + "\"state\":\"PENDING\"," + + "\"created_at\":\"2019-05-02T09:15:37.230Z\"," + + "\"modified_at\":\"2019-05-02T09:15:37.230Z\"," + + "\"deploy_id\":null,\"deploy_config\":{}," + "\"deploy_location\":null}\t"))); return Single.zip(insert03, insertTransaction03, Integer::sum); } diff --git a/edge/bios/src/test/java/com/nubeiot/edge/bios/timeout/HandlerTimeoutTest.java b/edge/bios/src/test/java/com/nubeiot/edge/bios/timeout/HandlerTimeoutTest.java index 69fb7cc13..b485b8fe7 100644 --- a/edge/bios/src/test/java/com/nubeiot/edge/bios/timeout/HandlerTimeoutTest.java +++ b/edge/bios/src/test/java/com/nubeiot/edge/bios/timeout/HandlerTimeoutTest.java @@ -24,7 +24,7 @@ import com.nubeiot.edge.bios.BaseInstallerVerticleTest; import com.nubeiot.edge.installer.InstallerVerticle; import com.nubeiot.edge.installer.loader.ModuleType; -import com.nubeiot.edge.installer.model.tables.pojos.TblModule; +import com.nubeiot.edge.installer.model.tables.pojos.Application; import com.nubeiot.eventbus.edge.installer.InstallerEventModel; @Ignore @@ -33,14 +33,14 @@ public class HandlerTimeoutTest extends BaseInstallerVerticleTest { @Before public void before(TestContext context) { super.before(context); - this.insertModule(context, new TblModule().setServiceId(MODULE_ID) - .setServiceType(ModuleType.JAVA) - .setServiceName(SERVICE_NAME) - .setState(State.ENABLED) - .setVersion(VERSION) - .setAppConfig(APP_CONFIG) - .setSystemConfig(APP_SYSTEM_CONFIG) - .setModifiedAt(DateTimes.now())); + this.insertModule(context, new Application().setAppId(MODULE_ID) + .setServiceType(ModuleType.JAVA) + .setServiceName(SERVICE_NAME) + .setState(State.ENABLED) + .setVersion(VERSION) + .setAppConfig(APP_CONFIG) + .setSystemConfig(APP_SYSTEM_CONFIG) + .setModifiedAt(DateTimes.now())); } @Override diff --git a/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/AbstractBACnetVerticle.java b/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/AbstractBACnetVerticle.java index 804af26fe..2439cc426 100644 --- a/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/AbstractBACnetVerticle.java +++ b/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/AbstractBACnetVerticle.java @@ -66,8 +66,8 @@ protected void successHandler(@NonNull C config) { private void readinessHandler(@NonNull C config, JsonObject d, Throwable e) { final EventMessage msg = Objects.nonNull(e) - ? EventMessage.initial(EventAction.NOTIFY_ERROR, - ErrorData.builder().throwable(e).build()) + ? EventMessage.error(EventAction.NOTIFY_ERROR, + ErrorData.builder().throwable(e).build()) : EventMessage.initial(EventAction.NOTIFY, RequestData.builder().body(d).build()); getEventbusClient().publish(config.getReadinessAddress(), msg); } diff --git a/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/BACnetDevice.java b/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/BACnetDevice.java index 768052139..0a87c445a 100644 --- a/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/BACnetDevice.java +++ b/edge/connector/bacnet/base/src/main/java/com/nubeiot/edge/connector/bacnet/BACnetDevice.java @@ -147,8 +147,8 @@ private EventMessage createErrorDiscoverMsg(@NonNull Throwable t) { .localDevice(metadata) .build() .toJson(); - return EventMessage.initial(EventAction.NOTIFY_ERROR, - ErrorData.builder().throwable(t).extraInfo(extraInfo).build()); + return EventMessage.error(EventAction.NOTIFY_ERROR, + ErrorData.builder().throwable(t).extraInfo(extraInfo).build()); } } diff --git a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeApplicationService.java b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeApplicationService.java new file mode 100644 index 000000000..8ab4aebef --- /dev/null +++ b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeApplicationService.java @@ -0,0 +1,14 @@ +package com.nubeiot.edge.module.installer.service; + +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.service.ApplicationService; + +import lombok.NonNull; + +public final class EdgeApplicationService extends ApplicationService implements EdgeInstallerService { + + public EdgeApplicationService(@NonNull InstallerEntityHandler entityHandler) { + super(entityHandler); + } + +} diff --git a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeBackupByAppService.java b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeBackupByAppService.java new file mode 100644 index 000000000..779f95b3b --- /dev/null +++ b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeBackupByAppService.java @@ -0,0 +1,14 @@ +package com.nubeiot.edge.module.installer.service; + +import com.nubeiot.edge.installer.InstallerEntityHandler; +import com.nubeiot.edge.installer.service.BackupByAppService; + +import lombok.NonNull; + +public final class EdgeBackupByAppService extends BackupByAppService implements EdgeInstallerService { + + protected EdgeBackupByAppService(@NonNull InstallerEntityHandler entityHandler) { + super(entityHandler); + } + +} diff --git a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeModuleService.java b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeModuleService.java deleted file mode 100644 index 824fff52b..000000000 --- a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeModuleService.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.nubeiot.edge.module.installer.service; - -import com.nubeiot.edge.installer.InstallerEntityHandler; -import com.nubeiot.edge.installer.service.ModuleService; - -import lombok.NonNull; - -public final class EdgeModuleService extends ModuleService implements EdgeInstallerService { - - public EdgeModuleService(@NonNull InstallerEntityHandler entityHandler) { - super(entityHandler); - } - -} diff --git a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByModuleService.java b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByAppService.java similarity index 53% rename from edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByModuleService.java rename to edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByAppService.java index 53fe25177..918b0818e 100644 --- a/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByModuleService.java +++ b/edge/module/installer/src/main/java/com/nubeiot/edge/module/installer/service/EdgeTransactionByAppService.java @@ -5,9 +5,9 @@ import lombok.NonNull; -public final class EdgeTransactionByModuleService extends TransactionByAppService implements EdgeInstallerService { +public final class EdgeTransactionByAppService extends TransactionByAppService implements EdgeInstallerService { - public EdgeTransactionByModuleService(@NonNull InstallerEntityHandler entityHandler) { + public EdgeTransactionByAppService(@NonNull InstallerEntityHandler entityHandler) { super(entityHandler); } From eb8b8e749b8ef357457eeea1407a80d23066012b Mon Sep 17 00:00:00 2001 From: zero-88 Date: Sun, 22 Mar 2020 21:11:00 +0700 Subject: [PATCH 5/6] core:archiver: Add tracking info in publish Zip result --- .../src/main/java/com/nubeiot/core/archiver/AsyncZip.java | 5 +++-- .../main/java/com/nubeiot/core/archiver/AsyncZipFolder.java | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java index bac413e87..6f3ca6217 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java @@ -40,8 +40,9 @@ default void onSuccess(@NonNull ZipOutput information) { transporter().publish(notifiedAddress(), EventMessage.success(EventAction.NOTIFY, information.toJson())); } - default void onError(@NonNull Throwable throwable) { - transporter().publish(notifiedAddress(), EventMessage.error(EventAction.NOTIFY_ERROR, throwable)); + default void onError(@NonNull ZipArgument argument, @NonNull Throwable throwable) { + transporter().publish(notifiedAddress(), + EventMessage.error(EventAction.NOTIFY_ERROR, throwable, argument.trackingInfo())); } } diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java index d42a4856b..c58afeb78 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java @@ -46,7 +46,7 @@ private void doRun(@NonNull ZipArgument argument, @NonNull File destFolder, @Non .setPeriodic(argument.watcherDelayInMilli(), id -> watch(id, argument, progressMonitor, zipFile.getFile())); } catch (ZipException e) { - onError(e); + onError(argument, e); } } @@ -80,7 +80,7 @@ private void watch(long timerId, @NonNull ZipArgument argument, @NonNull Progres .build()); return; } - onError(progressMonitor.getException()); + onError(argument, progressMonitor.getException()); } } From 88cefe55378903118145b96ad0f8ad2a44a5297d Mon Sep 17 00:00:00 2001 From: zero-88 Date: Tue, 24 Mar 2020 00:45:38 +0700 Subject: [PATCH 6/6] :core:archiver: Implement AsyncUnzip and standard JavaAPI --- .../core/archiver/AbstractAsyncArchiver.java | 75 +++++++++++++++ .../nubeiot/core/archiver/AsyncArchiver.java | 77 ++++++++++++++++ .../com/nubeiot/core/archiver/AsyncUnzip.java | 31 +++++++ .../com/nubeiot/core/archiver/AsyncZip.java | 76 ++++++++++------ .../nubeiot/core/archiver/AsyncZipFolder.java | 91 ++++++------------- .../core/archiver/DefaultAsyncUnzip.java | 51 +++++++++++ .../nubeiot/core/archiver/ZipArgument.java | 18 +--- .../core/archiver/ZipNotificationHandler.java | 19 ++++ .../com/nubeiot/core/archiver/ZipOutput.java | 4 +- .../core/archiver/AsyncZipFolderTest.java | 79 ++++++++++++++-- .../core/archiver/TestZipNotifier.java | 18 +++- .../nubeiot/core/event/AnnotationHandler.java | 4 +- .../com/nubeiot/core/utils/FileUtils.java | 9 +- .../installer/service/BackupByAppService.java | 2 +- 14 files changed, 430 insertions(+), 124 deletions(-) create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/AbstractAsyncArchiver.java create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncArchiver.java create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncUnzip.java create mode 100644 core/archiver/src/main/java/com/nubeiot/core/archiver/DefaultAsyncUnzip.java diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AbstractAsyncArchiver.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AbstractAsyncArchiver.java new file mode 100644 index 000000000..4d8ec10e4 --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AbstractAsyncArchiver.java @@ -0,0 +1,75 @@ +package com.nubeiot.core.archiver; + +import java.io.File; +import java.nio.file.Path; + +import io.vertx.core.logging.Logger; +import io.vertx.core.logging.LoggerFactory; + +import com.nubeiot.core.event.EventbusClient; + +import lombok.Getter; +import lombok.NonNull; +import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import net.lingala.zip4j.progress.ProgressMonitor; +import net.lingala.zip4j.progress.ProgressMonitor.Result; +import net.lingala.zip4j.progress.ProgressMonitor.State; + +@Getter +@Accessors(fluent = true) +@SuperBuilder +public abstract class AbstractAsyncArchiver implements AsyncArchiver { + + protected final Logger logger = LoggerFactory.getLogger(this.getClass()); + + @NonNull + private final EventbusClient transporter; + @NonNull + private final String notifiedAddress; + + protected void execute(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File originFile) { + try { + final ZipFile zipFile = createZipFile(argument, destFolder, originFile); + zipFile.setRunInThread(true); + run(argument, zipFile, destFolder, originFile); + transporter().getVertx() + .setPeriodic(argument.watcherDelayInMilli(), id -> watch(id, argument, zipFile, originFile)); + } catch (ZipException e) { + onError(argument, new IllegalArgumentException(e)); + } + } + + protected abstract ZipFile createZipFile(@NonNull ZipArgument argument, @NonNull File destination, + @NonNull File originFile); + + protected abstract void run(@NonNull ZipArgument argument, @NonNull ZipFile zipFile, @NonNull File destination, + @NonNull File originFile) throws ZipException; + + protected void watch(long timerId, @NonNull ZipArgument argument, @NonNull ZipFile zipFile, + @NonNull File originFile) { + final ProgressMonitor progressMonitor = zipFile.getProgressMonitor(); + final Path path = zipFile.getFile().toPath(); + if (progressMonitor.getState().equals(State.BUSY)) { + logger.debug("{} {} | Progress: {}% | Current file: {} | Current task: {}", action(), path, + progressMonitor.getPercentDone(), progressMonitor.getFileName(), + progressMonitor.getCurrentTask()); + return; + } + transporter().getVertx().cancelTimer(timerId); + final Result result = progressMonitor.getResult(); + if (result == Result.SUCCESS) { + onSuccess(createOutput(argument, zipFile, progressMonitor, originFile)); + return; + } + onError(argument, new IllegalArgumentException(progressMonitor.getException())); + } + + protected abstract String action(); + + protected abstract ZipOutput createOutput(@NonNull ZipArgument argument, @NonNull ZipFile zipFile, + @NonNull ProgressMonitor progressMonitor, @NonNull File originFile); + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncArchiver.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncArchiver.java new file mode 100644 index 000000000..8181a06c9 --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncArchiver.java @@ -0,0 +1,77 @@ +package com.nubeiot.core.archiver; + +import java.nio.file.Path; + +import com.nubeiot.core.component.EventClientProxy; +import com.nubeiot.core.event.EventAction; +import com.nubeiot.core.event.EventMessage; + +import lombok.NonNull; + +/** + * Represents Async archvier. + * + * @since 1.0.0 + */ +public interface AsyncArchiver extends EventClientProxy { + + /** + * The constant EXT_ZIP_FILE. + */ + String EXT_ZIP_FILE = ".zip"; + + /** + * Appends {@code ext} in file name. + * + * @param fileName the file name + * @return the string + * @since 1.0.0 + */ + @NonNull + static String ext(@NonNull String fileName) { + return fileName + EXT_ZIP_FILE; + } + + /** + * Appends {@code ext} in file name. + * + * @param fileName the file name + * @return the string + * @since 1.0.0 + */ + @NonNull + static String ext(@NonNull Path fileName) { + return ext(fileName.toString()); + } + + /** + * Notified address string. + * + * @return the string + * @since 1.0.0 + */ + @NonNull String notifiedAddress(); + + /** + * On success. + * + * @param information the information + * @since 1.0.0 + */ + default void onSuccess(@NonNull ZipOutput information) { + transporter().publish(notifiedAddress(), EventMessage.success(EventAction.NOTIFY, information.toJson())); + } + + /** + * On error. + * + * @param argument the argument + * @param throwable the throwable + * @since 1.0.0 + */ + default void onError(@NonNull ZipArgument argument, @NonNull Throwable throwable) { + transporter().publish(notifiedAddress(), + EventMessage.error(EventAction.NOTIFY_ERROR, throwable, argument.trackingInfo())); + } + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncUnzip.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncUnzip.java new file mode 100644 index 000000000..dc49d5bf4 --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncUnzip.java @@ -0,0 +1,31 @@ +package com.nubeiot.core.archiver; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import com.nubeiot.core.utils.FileUtils; +import com.nubeiot.core.utils.Strings; + +import lombok.NonNull; + +public interface AsyncUnzip extends AsyncArchiver { + + default void extract(@NonNull ZipArgument argument, @NonNull String destFolder, @NonNull String zipFile) { + extract(argument, Paths.get(destFolder), Paths.get(zipFile)); + } + + default void extract(@NonNull ZipArgument argument, @NonNull Path destFolder, @NonNull Path zipFile) { + extract(argument, destFolder.toFile(), zipFile.toFile()); + } + + void extract(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File zipFile); + + default String computeExtractedFolder(@NonNull ZipArgument argument, @NonNull File zippedFile) { + if (Strings.isNotBlank(argument.overriddenDestFileName())) { + return argument.overriddenDestFileName(); + } + return FileUtils.withoutExtension(zippedFile.toPath().getFileName().toString()); + } + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java index 6f3ca6217..18539bd67 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZip.java @@ -4,45 +4,61 @@ import java.nio.file.Path; import java.nio.file.Paths; -import com.nubeiot.core.component.EventClientProxy; -import com.nubeiot.core.event.EventAction; -import com.nubeiot.core.event.EventMessage; +import com.nubeiot.core.utils.DateTimes; +import com.nubeiot.core.utils.Strings; import lombok.NonNull; -public interface AsyncZip extends EventClientProxy { +/** + * Represents Async zip. + * + * @since 1.0.0 + */ +public interface AsyncZip extends AsyncArchiver { - String EXT_ZIP_FILE = ".zip"; - - @NonNull - static String ext(@NonNull String fileName) { - return fileName + EXT_ZIP_FILE; - } - - @NonNull - static String ext(@NonNull Path fileName) { - return ext(fileName.toString()); - } - - @NonNull String notifiedAddress(); - - default void run(@NonNull ZipArgument argument, @NonNull String destFolder, @NonNull String tobeZipped) { - run(argument, Paths.get(destFolder), Paths.get(tobeZipped)); + /** + * Do zip folder. + * + * @param argument the argument + * @param destFolder the dest folder + * @param tobeZipped the tobe zipped + * @see ZipArgument + * @since 1.0.0 + */ + default void zip(@NonNull ZipArgument argument, @NonNull String destFolder, @NonNull String tobeZipped) { + zip(argument, Paths.get(destFolder), Paths.get(tobeZipped)); } - default void run(@NonNull ZipArgument argument, @NonNull Path destFolder, @NonNull Path tobeZipped) { - run(argument, destFolder.toFile(), tobeZipped.toFile()); + /** + * Do zip folder. + * + * @param argument the argument + * @param destFolder the dest folder + * @param tobeZipped the tobe zipped + * @see ZipArgument + * @since 1.0.0 + */ + default void zip(@NonNull ZipArgument argument, @NonNull Path destFolder, @NonNull Path tobeZipped) { + zip(argument, destFolder.toFile(), tobeZipped.toFile()); } - void run(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped); - - default void onSuccess(@NonNull ZipOutput information) { - transporter().publish(notifiedAddress(), EventMessage.success(EventAction.NOTIFY, information.toJson())); - } + /** + * Do zip folder. + * + * @param argument the argument + * @param destFolder the dest folder + * @param tobeZipped the tobe zipped + * @see ZipArgument + * @since 1.0.0 + */ + void zip(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped); - default void onError(@NonNull ZipArgument argument, @NonNull Throwable throwable) { - transporter().publish(notifiedAddress(), - EventMessage.error(EventAction.NOTIFY_ERROR, throwable, argument.trackingInfo())); + default String computeZipName(@NonNull ZipArgument argument, @NonNull File toZippedFile) { + if (Strings.isNotBlank(argument.overriddenDestFileName())) { + return AsyncArchiver.ext(argument.overriddenDestFileName()); + } + final String fileName = toZippedFile.toPath().getFileName().toString(); + return AsyncArchiver.ext(fileName + (argument.appendTimestamp() ? "-" + DateTimes.nowMilli() : "")); } } diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java index c58afeb78..e2c3252da 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/AsyncZipFolder.java @@ -1,86 +1,51 @@ package com.nubeiot.core.archiver; import java.io.File; -import java.nio.file.Path; -import io.vertx.core.logging.Logger; -import io.vertx.core.logging.LoggerFactory; - -import com.nubeiot.core.event.EventbusClient; import com.nubeiot.core.utils.ExecutorHelpers; -import com.nubeiot.core.utils.Strings; -import lombok.Builder; -import lombok.Getter; import lombok.NonNull; -import lombok.experimental.Accessors; +import lombok.experimental.SuperBuilder; import net.lingala.zip4j.ZipFile; import net.lingala.zip4j.exception.ZipException; import net.lingala.zip4j.progress.ProgressMonitor; -import net.lingala.zip4j.progress.ProgressMonitor.Result; -import net.lingala.zip4j.progress.ProgressMonitor.State; - -@Getter -@Accessors(fluent = true) -@Builder(builderClassName = "Builder") -public final class AsyncZipFolder implements AsyncZip { - private static final Logger LOGGER = LoggerFactory.getLogger(AsyncZipFolder.class); +@SuperBuilder +public final class AsyncZipFolder extends AbstractAsyncArchiver implements AsyncZip { - @NonNull - private final EventbusClient transporter; - @NonNull - private final String notifiedAddress; + @Override + public void zip(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped) { + ExecutorHelpers.blocking(transporter().getVertx(), () -> execute(argument, destFolder, tobeZipped)); + } @Override - public void run(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped) { - ExecutorHelpers.blocking(transporter.getVertx(), () -> doRun(argument, destFolder, tobeZipped)); + protected ZipFile createZipFile(@NonNull ZipArgument argument, @NonNull File destination, + @NonNull File originFile) { + return new ZipFile(destination.toPath().resolve(computeZipName(argument, originFile)).toString(), + argument.toPassword()); } - private void doRun(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File tobeZipped) { - try { - final ZipFile zipFile = createZipFile(argument, destFolder, tobeZipped); - final ProgressMonitor progressMonitor = zipFile.getProgressMonitor(); - zipFile.addFolder(tobeZipped, argument.zipParameters()); - transporter.getVertx() - .setPeriodic(argument.watcherDelayInMilli(), - id -> watch(id, argument, progressMonitor, zipFile.getFile())); - } catch (ZipException e) { - onError(argument, e); - } + @Override + protected void run(@NonNull ZipArgument argument, ZipFile zipFile, @NonNull File destination, + @NonNull File originFile) throws ZipException { + zipFile.addFolder(originFile, argument.zipParameters()); } - private ZipFile createZipFile(@NonNull ZipArgument argument, @NonNull File destination, @NonNull File origin) { - final String dest = destination.toPath().resolve(argument.getZipFileName(origin)).toString(); - final String password = argument.password(); - final ZipFile zipFile = new ZipFile(AsyncZip.ext(dest), - Strings.isBlank(password) ? null : password.toCharArray()); - zipFile.setRunInThread(true); - return zipFile; + @Override + protected String action() { + return "Compressing"; } - private void watch(long timerId, @NonNull ZipArgument argument, @NonNull ProgressMonitor progressMonitor, - @NonNull File archiveFile) { - final Path path = archiveFile.toPath(); - if (progressMonitor.getState().equals(State.BUSY)) { - LOGGER.info("Zipping: {} | Progress: {}% | Current file: {} | Current task: {}", path, - progressMonitor.getPercentDone(), progressMonitor.getFileName(), - progressMonitor.getCurrentTask()); - return; - } - transporter.getVertx().cancelTimer(timerId); - final Result result = progressMonitor.getResult(); - if (result == Result.SUCCESS) { - onSuccess(ZipOutput.builder() - .originFile(progressMonitor.getFileName()) - .zipFile(path.toString()) - .size(archiveFile.length()) - .lastModified(archiveFile.lastModified()) - .trackingInfo(argument.trackingInfo()) - .build()); - return; - } - onError(argument, progressMonitor.getException()); + @Override + protected ZipOutput createOutput(@NonNull ZipArgument argument, @NonNull ZipFile zipFile, + @NonNull ProgressMonitor progressMonitor, @NonNull File originFile) { + return ZipOutput.builder() + .inputPath(originFile.getPath()) + .outputPath(zipFile.getFile().toString()) + .size(zipFile.getFile().length()) + .lastModified(zipFile.getFile().lastModified()) + .trackingInfo(argument.trackingInfo()) + .build(); } } diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/DefaultAsyncUnzip.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/DefaultAsyncUnzip.java new file mode 100644 index 000000000..a3e9c30a1 --- /dev/null +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/DefaultAsyncUnzip.java @@ -0,0 +1,51 @@ +package com.nubeiot.core.archiver; + +import java.io.File; +import java.nio.file.Paths; + +import com.nubeiot.core.utils.ExecutorHelpers; + +import lombok.NonNull; +import lombok.experimental.SuperBuilder; +import net.lingala.zip4j.ZipFile; +import net.lingala.zip4j.exception.ZipException; +import net.lingala.zip4j.progress.ProgressMonitor; + +@SuperBuilder +public final class DefaultAsyncUnzip extends AbstractAsyncArchiver implements AsyncUnzip { + + @Override + public void extract(@NonNull ZipArgument argument, @NonNull File destFolder, @NonNull File zipFile) { + ExecutorHelpers.blocking(transporter().getVertx(), () -> execute(argument, destFolder, zipFile)); + } + + @Override + protected ZipFile createZipFile(@NonNull ZipArgument argument, @NonNull File destination, + @NonNull File originFile) { + return new ZipFile(originFile, argument.toPassword()); + } + + @Override + protected void run(@NonNull ZipArgument argument, @NonNull ZipFile zipFile, @NonNull File destination, + @NonNull File originFile) throws ZipException { + zipFile.extractAll(destination.toPath().resolve(computeExtractedFolder(argument, originFile)).toString()); + } + + @Override + protected String action() { + return "Extracting"; + } + + @Override + protected ZipOutput createOutput(@NonNull ZipArgument argument, @NonNull ZipFile zipFile, + @NonNull ProgressMonitor progressMonitor, @NonNull File originFile) { + final File outputFile = Paths.get(progressMonitor.getFileName()).getParent().toFile(); + return ZipOutput.builder() + .inputPath(originFile.getPath()) + .outputPath(outputFile.getPath()) + .lastModified(outputFile.lastModified()) + .trackingInfo(argument.trackingInfo()) + .build(); + } + +} diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java index 67c355bbf..e71cdb6f1 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipArgument.java @@ -1,12 +1,8 @@ package com.nubeiot.core.archiver; -import java.io.File; -import java.nio.file.Path; - import io.vertx.core.json.JsonObject; import com.nubeiot.core.dto.JsonData; -import com.nubeiot.core.utils.DateTimes; import com.nubeiot.core.utils.Strings; import lombok.Builder; @@ -45,23 +41,17 @@ public static ZipArgument noTimestamp(JsonObject trackingInfo) { return ZipArgument.builder() .trackingInfo(trackingInfo) .appendTimestamp(false) - .watcherDelayInMilli(100) - .zipParameters(defaultZipParameters()) - .build(); + .watcherDelayInMilli(100).zipParameters(defaultZipParameters()).build(); } static @NonNull ZipParameters defaultZipParameters() { ZipParameters parameters = new ZipParameters(); - parameters.setIncludeRootFolder(true); + parameters.setIncludeRootFolder(false); return parameters; } - public String getZipFileName(@NonNull File toZippedFile) { - if (Strings.isNotBlank(overriddenDestFileName)) { - return overriddenDestFileName; - } - final Path fileName = toZippedFile.toPath().getFileName(); - return appendTimestamp ? fileName.toString() + "-" + DateTimes.nowMilli() : fileName.toString(); + public char[] toPassword() { + return Strings.isBlank(password) ? null : password.toCharArray(); } } diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java index 9c547bb03..9bb99b565 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipNotificationHandler.java @@ -10,6 +10,11 @@ import lombok.NonNull; +/** + * Represents Zip notification handler. + * + * @since 1.0.0 + */ public interface ZipNotificationHandler extends EventListener { @Override @@ -17,9 +22,23 @@ public interface ZipNotificationHandler extends EventListener { return Arrays.asList(EventAction.NOTIFY, EventAction.NOTIFY_ERROR); } + /** + * Handles {@code success}. + * + * @param result the result + * @return the boolean + * @since 1.0.0 + */ @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) boolean success(@NonNull ZipOutput result); + /** + * Handles {@code error} case. + * + * @param error the error + * @return the boolean + * @since 1.0.0 + */ @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) boolean error(@NonNull ErrorData error); diff --git a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java index 09f157fd5..92aa48778 100644 --- a/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java +++ b/core/archiver/src/main/java/com/nubeiot/core/archiver/ZipOutput.java @@ -19,8 +19,8 @@ public final class ZipOutput implements JsonData { private final JsonObject trackingInfo; - private final String originFile; - private final String zipFile; + private final String inputPath; + private final String outputPath; private final long size; private final OffsetDateTime lastModified; diff --git a/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java b/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java index 4824fa02c..652085bd2 100644 --- a/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java +++ b/core/archiver/src/test/java/com/nubeiot/core/archiver/AsyncZipFolderTest.java @@ -2,6 +2,9 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; import org.junit.Before; import org.junit.Rule; @@ -11,11 +14,16 @@ import io.vertx.core.Vertx; import io.vertx.core.eventbus.DeliveryOptions; +import io.vertx.core.json.JsonObject; +import io.vertx.ext.unit.Async; import io.vertx.ext.unit.TestContext; import io.vertx.ext.unit.junit.VertxUnitRunner; +import com.nubeiot.core.TestHelper; import com.nubeiot.core.component.EventClientProxy; import com.nubeiot.core.event.EventbusClient; +import com.nubeiot.core.exceptions.NubeException.ErrorCode; +import com.nubeiot.core.utils.FileUtils; @RunWith(VertxUnitRunner.class) public class AsyncZipFolderTest { @@ -23,30 +31,81 @@ public class AsyncZipFolderTest { @Rule public TemporaryFolder folder = new TemporaryFolder(); private EventbusClient client; + private File origin; + private File dest; @Before - public void setup() { + public void setup() throws IOException { final Vertx vertx = Vertx.vertx(); client = EventClientProxy.create(vertx, new DeliveryOptions()).transporter(); + origin = folder.newFolder("origin"); + dest = folder.newFolder("dest"); } @Test - public void test(TestContext context) throws IOException { - final File dest = folder.newFolder("destination"); - final File origin = folder.newFolder("origin"); + public void test_zip(TestContext context) throws IOException { folder.newFile(folder.getRoot().toPath().relativize(origin.toPath().resolve("abc.txt")).toString()); + folder.newFile(folder.getRoot().toPath().relativize(origin.toPath().resolve("def.txt")).toString()); + final Path xyz = origin.toPath().resolve("xyz"); + assert xyz.toFile().mkdirs(); + folder.newFile(folder.getRoot().toPath().relativize(xyz.resolve("ghj.txt")).toString()); + final String outFile = AsyncArchiver.ext(dest.toPath().resolve(origin.toPath().getFileName())); final ZipOutput expected = ZipOutput.builder() - .originFile(origin.toString()) - .zipFile(AsyncZip.ext(dest.toPath().resolve(origin.toPath().getFileName()))) - .size(216) + .inputPath(origin.toString()) + .outputPath(outFile) + .size(384) .build(); - final TestZipNotifier notifier = new TestZipNotifier(context, context.async(), expected.toJson()); - client.register("xxx", notifier); + createNotifier(context, expected.toJson(), context.async(), null); AsyncZipFolder.builder() .transporter(client) .notifiedAddress("xxx") .build() - .run(ZipArgument.noTimestamp(), dest, origin); + .zip(ZipArgument.noTimestamp(), dest, origin); + } + + @Test + public void test_unzip(TestContext context) throws InterruptedException { + final File zipFile = FileUtils.getClasspathFile("origin.zip").toFile(); + final ZipOutput expected = ZipOutput.builder() + .inputPath(zipFile.toString()) + .outputPath(dest.toPath().resolve("origin").toString()) + .build(); + final Async async = context.async(2); + final CountDownLatch latch = new CountDownLatch(1); + createNotifier(context, expected.toJson(), async, latch); + DefaultAsyncUnzip.builder() + .transporter(client) + .notifiedAddress("xxx") + .build() + .extract(ZipArgument.noTimestamp(), dest, zipFile); + latch.await(TestHelper.TEST_TIMEOUT_SEC, TimeUnit.SECONDS); + final Path extractFile = dest.toPath().resolve("origin").resolve("abc.txt"); + client.getVertx().fileSystem().exists(extractFile.toString(), event -> { + context.assertTrue(event.succeeded()); + context.assertTrue(event.result()); + TestHelper.testComplete(async); + }); + } + + @Test + public void test_unzip_not_found(TestContext context) { + final Async async = context.async(); + final Path zipFile = dest.toPath().resolve("origin.zip"); + final JsonObject expected = new JsonObject().put("code", ErrorCode.INVALID_ARGUMENT) + .put("message", "java.io.FileNotFoundException: " + zipFile + + " (The system cannot find the file " + + "specified)"); + createNotifier(context, expected, async, null); + DefaultAsyncUnzip.builder() + .transporter(client) + .notifiedAddress("xxx") + .build() + .extract(ZipArgument.noTimestamp(), dest.toPath(), zipFile); + } + + private void createNotifier(TestContext context, JsonObject expected, Async async, CountDownLatch latch) { + final TestZipNotifier notifier = new TestZipNotifier(context, async, expected, latch); + client.register("xxx", notifier); } } diff --git a/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java index 39ef27291..4ffbc0c1b 100644 --- a/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java +++ b/core/archiver/src/test/java/com/nubeiot/core/archiver/TestZipNotifier.java @@ -1,5 +1,8 @@ package com.nubeiot.core.archiver; +import java.util.Optional; +import java.util.concurrent.CountDownLatch; + import io.vertx.core.json.JsonObject; import io.vertx.ext.unit.Async; import io.vertx.ext.unit.TestContext; @@ -21,18 +24,29 @@ public final class TestZipNotifier implements ZipNotificationHandler { private final Async async; @NonNull private final JsonObject expected; + private final CountDownLatch latch; @Override @EventContractor(action = EventAction.NOTIFY, returnType = boolean.class) public boolean success(@NonNull ZipOutput response) { - JsonHelper.assertJson(testContext, async, expected, response.toJson(), JsonHelper.ignore("lastModified")); + try { + System.out.println(response.toJson()); + JsonHelper.assertJson(testContext, async, expected, response.toJson(), JsonHelper.ignore("lastModified")); + } finally { + Optional.ofNullable(latch).ifPresent(CountDownLatch::countDown); + } return true; } @Override @EventContractor(action = EventAction.NOTIFY_ERROR, returnType = boolean.class) public boolean error(@NonNull ErrorData error) { - JsonHelper.assertJson(testContext, async, expected, error.toJson()); + try { + System.out.println(error.toJson()); + JsonHelper.assertJson(testContext, async, expected, error.getError().toJson()); + } finally { + Optional.ofNullable(latch).ifPresent(CountDownLatch::countDown); + } return true; } diff --git a/core/base/src/main/java/com/nubeiot/core/event/AnnotationHandler.java b/core/base/src/main/java/com/nubeiot/core/event/AnnotationHandler.java index 84e43d72a..3359d73af 100644 --- a/core/base/src/main/java/com/nubeiot/core/event/AnnotationHandler.java +++ b/core/base/src/main/java/com/nubeiot/core/event/AnnotationHandler.java @@ -137,7 +137,9 @@ private Object[] parseMessage(EventMessage message, Map> params if (params.isEmpty()) { return new Object[] {}; } - JsonObject data = message.isError() ? message.getError().toJson() : message.getData(); + JsonObject data = message.isError() && Objects.nonNull(message.getError()) + ? message.getError().toJson() + : message.getData(); if (Objects.isNull(data)) { throw new NubeException(ErrorCode.INVALID_ARGUMENT, Strings.format("Event Message Data is null: {0}", message.toJson())); diff --git a/core/base/src/main/java/com/nubeiot/core/utils/FileUtils.java b/core/base/src/main/java/com/nubeiot/core/utils/FileUtils.java index 6c052dff5..d42d03497 100644 --- a/core/base/src/main/java/com/nubeiot/core/utils/FileUtils.java +++ b/core/base/src/main/java/com/nubeiot/core/utils/FileUtils.java @@ -98,7 +98,7 @@ public static Path toPath(String filePath, String classpathFile) { return Strings.isBlank(filePath) ? getClasspathFile(classpathFile) : toPath(filePath); } - private static Path getClasspathFile(String classpathFile) { + public static Path getClasspathFile(String classpathFile) { final Path fileInWorkingDir = Paths.get(".", classpathFile); if (fileInWorkingDir.toFile().exists()) { return fileInWorkingDir; @@ -310,4 +310,11 @@ public static String getExtension(String filename) { .orElse(""); } + public static String withoutExtension(String filename) { + return Optional.ofNullable(filename) + .filter(f -> f.contains(".")) + .map(f -> f.substring(0, filename.lastIndexOf("."))) + .orElse(""); + } + } diff --git a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java index 970a4543e..7c90e0365 100644 --- a/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java +++ b/core/installer/src/main/java/com/nubeiot/edge/installer/service/BackupByAppService.java @@ -150,7 +150,7 @@ protected void doBackup(@NonNull JsonObject record) { final String dataDirField = jsonField(context().table().DATA_DIR); // zipper.run(ZipArgument.createDefault(info.put("type", installationDirField)), backupFolder(), // Paths.get(installationDirField)); - zipper.run(ZipArgument.createDefault(info.put("type", dataDirField)), backupFolder(), Paths.get(dataDirField)); + zipper.zip(ZipArgument.createDefault(info.put("type", dataDirField)), backupFolder(), Paths.get(dataDirField)); } private String jsonField(Field installation_dir) {