From e03ab8b03821d1fccba10da841db2771d9bc749a Mon Sep 17 00:00:00 2001 From: 006627 Date: Tue, 4 Feb 2020 18:14:02 +0000 Subject: [PATCH] prevents multiple jobs for the same resource [skip ci] --- .../common/api/v1/CollectionResource.java | 22 +++- .../DataTransformation.java | 4 +- .../handler/DataTransformationUtils.java | 13 ++- .../client/exceptions/RESTException.java | 5 + .../collection/CollectionConfiguration.java | 68 ------------ .../collection/ColumnConfiguration.java | 45 -------- .../collection/TableConfiguration.java | 100 ------------------ .../DataTransformationProgressData.java | 65 ------------ .../common/client/services/JobService.java | 7 -- .../server/DataTransformationObserver.java | 29 ----- .../common/server/jobs/JobListener.java | 4 +- .../transformers/DenormalizeTransformer.java | 4 - 12 files changed, 41 insertions(+), 325 deletions(-) delete mode 100644 src/main/java/com/databasepreservation/common/client/models/configuration/collection/CollectionConfiguration.java delete mode 100644 src/main/java/com/databasepreservation/common/client/models/configuration/collection/ColumnConfiguration.java delete mode 100644 src/main/java/com/databasepreservation/common/client/models/configuration/collection/TableConfiguration.java delete mode 100644 src/main/java/com/databasepreservation/common/client/models/progress/DataTransformationProgressData.java delete mode 100644 src/main/java/com/databasepreservation/common/server/DataTransformationObserver.java diff --git a/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java b/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java index 473979938..dfaf9dcdb 100644 --- a/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java +++ b/src/main/java/com/databasepreservation/common/api/v1/CollectionResource.java @@ -29,12 +29,14 @@ import org.roda.core.data.utils.JsonUtils; import org.roda.core.data.v2.index.sublist.Sublist; import org.springframework.batch.core.Job; +import org.springframework.batch.core.JobExecution; import org.springframework.batch.core.JobParameters; import org.springframework.batch.core.JobParametersBuilder; import org.springframework.batch.core.JobParametersInvalidException; import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.launch.JobLauncher; import org.springframework.batch.core.launch.JobOperator; +import org.springframework.batch.core.launch.NoSuchJobException; import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException; import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException; import org.springframework.batch.core.repository.JobRestartException; @@ -287,7 +289,7 @@ public DenormalizeConfiguration getDenormalizeConfigurationFile(String databaseU } @Override - public Boolean createDenormalizeConfigurationFile(String databaseUUID, String collectionUUID, String tableUUID, + public synchronized Boolean createDenormalizeConfigurationFile(String databaseUUID, String collectionUUID, String tableUUID, DenormalizeConfiguration configuration) { ControllerAssistant controllerAssistant = new ControllerAssistant() {}; User user = UserUtility.getUser(request); @@ -295,6 +297,14 @@ public Boolean createDenormalizeConfigurationFile(String databaseUUID, String co controllerAssistant.checkRoles(user); + // check if there is no job running on table + for (JobExecution runningJobExecution : jobExplorer.findRunningJobExecutions("denormalizeJob")) { + System.out.println(runningJobExecution); + if (runningJobExecution.getJobParameters().getString(ViewerConstants.CONTROLLER_TABLE_ID_PARAM).equals(tableUUID)) { + throw new RESTException("A job is already running on this table", com.google.gwt.http.client.Response.SC_CONFLICT); + } + } + try { JsonTransformer.writeObjectToFile(configuration, ViewerConfiguration.getInstance().getDatabasesPath().resolve(databaseUUID) @@ -340,13 +350,21 @@ public Boolean deleteDenormalizeConfigurationFile(String databaseUUID, String co } @Override - public void run(String databaseUUID, String collectionUUID, String tableUUID) { + public synchronized void run(String databaseUUID, String collectionUUID, String tableUUID) { ControllerAssistant controllerAssistant = new ControllerAssistant() {}; User user = UserUtility.getUser(request); LogEntryState state = LogEntryState.SUCCESS; controllerAssistant.checkRoles(user); + // check if there is no job running on table + for (JobExecution runningJobExecution : jobExplorer.findRunningJobExecutions("denormalizeJob")) { + System.out.println(runningJobExecution); + if (runningJobExecution.getJobParameters().getString(ViewerConstants.CONTROLLER_TABLE_ID_PARAM).equals(tableUUID)) { + throw new RESTException("A job is already running on this table", com.google.gwt.http.client.Response.SC_CONFLICT); + } + } + JobParametersBuilder jobBuilder = new JobParametersBuilder(); jobBuilder.addDate(ViewerConstants.SOLR_SEARCHES_DATE_ADDED, new Date()); jobBuilder.addString(ViewerConstants.INDEX_ID, SolrUtils.randomUUID()); diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/dataTransformation/DataTransformation.java b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/dataTransformation/DataTransformation.java index ff48c3c3a..583dd4a6f 100644 --- a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/dataTransformation/DataTransformation.java +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/dataTransformation/DataTransformation.java @@ -219,8 +219,8 @@ private void createButtons() { messages.dataTransformationBtnRunTable()); btnRunConfiguration.setStyleName("btn btn-play"); btnRunConfiguration.addClickHandler(clickEvent -> { - DataTransformationUtils.saveConfiguration(database.getUuid(), denormalizeConfiguration, collectionStatus); - HistoryManager.gotoJobs(); + DataTransformationUtils.saveConfiguration(database.getUuid(), denormalizeConfiguration, collectionStatus); + HistoryManager.gotoJobs(); }); btnRunAllConfiguration.setText(messages.dataTransformationBtnRunAll()); diff --git a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/handler/DataTransformationUtils.java b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/handler/DataTransformationUtils.java index 5a9ea3e5a..0b9f4f29d 100644 --- a/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/handler/DataTransformationUtils.java +++ b/src/main/java/com/databasepreservation/common/client/common/visualization/browse/configuration/handler/DataTransformationUtils.java @@ -5,6 +5,7 @@ import com.databasepreservation.common.client.ObserverManager; import com.databasepreservation.common.client.ViewerConstants; +import com.databasepreservation.common.client.common.dialogs.Dialogs; import com.databasepreservation.common.client.common.visualization.browse.configuration.dataTransformation.TableNode; import com.databasepreservation.common.client.configuration.observer.CollectionObserver; import com.databasepreservation.common.client.models.status.collection.CollectionStatus; @@ -21,11 +22,15 @@ import com.databasepreservation.common.client.models.structure.ViewerTable; import com.databasepreservation.common.client.services.CollectionService; import com.databasepreservation.common.client.widgets.Toast; +import com.google.gwt.core.client.GWT; + +import config.i18n.client.ClientMessages; /** * @author Gabriel Barros */ public class DataTransformationUtils { + public static ClientMessages messages = GWT.create(ClientMessages.class); private DataTransformationUtils() {} public static void includeRelatedTable(TableNode childNode, DenormalizeConfiguration denormalizeConfiguration) { @@ -92,9 +97,15 @@ public static void saveConfiguration(String databaseUUID, DenormalizeConfigurati final CollectionObserver collectionObserver = ObserverManager.getCollectionObserver(); collectionObserver.setCollectionStatus(collectionStatus); CollectionService.Util.call((Void response) -> { - Toast.showInfo("Configuration file", + Toast.showInfo(messages.advancedConfigurationLabelForDataTransformation(), "Created denormalization configuration file with success for " + denormalizeConfiguration.getTableID()); + }, errorMessage -> { + Dialogs.showErrors(messages.advancedConfigurationLabelForDataTransformation(), errorMessage, + messages.basicActionClose()); }).run(databaseUUID,databaseUUID, denormalizeConfiguration.getTableUUID()); + }, errorMessage -> { + Dialogs.showErrors(messages.advancedConfigurationLabelForDataTransformation(), errorMessage, + messages.basicActionClose()); }).createDenormalizeConfigurationFile(databaseUUID, databaseUUID, denormalizeConfiguration.getTableUUID(), denormalizeConfiguration); } diff --git a/src/main/java/com/databasepreservation/common/client/exceptions/RESTException.java b/src/main/java/com/databasepreservation/common/client/exceptions/RESTException.java index fc45caa16..892e12cf6 100644 --- a/src/main/java/com/databasepreservation/common/client/exceptions/RESTException.java +++ b/src/main/java/com/databasepreservation/common/client/exceptions/RESTException.java @@ -34,6 +34,11 @@ public RESTException(Throwable cause) { this.status = getResponseStatusCode(cause); } + public RESTException(String message, int status) { + super(message); + this.status = status; + } + public RESTException(Throwable cause, int status) { super("Remote exception" + getCauseMessage(cause)); this.status = status; diff --git a/src/main/java/com/databasepreservation/common/client/models/configuration/collection/CollectionConfiguration.java b/src/main/java/com/databasepreservation/common/client/models/configuration/collection/CollectionConfiguration.java deleted file mode 100644 index 08648c17a..000000000 --- a/src/main/java/com/databasepreservation/common/client/models/configuration/collection/CollectionConfiguration.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.databasepreservation.common.client.models.configuration.collection; - -import com.databasepreservation.common.client.models.structure.ViewerDatabase; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Gabriel Barros - */ -public class CollectionConfiguration implements Serializable { - private String version; - private String uuid; - private String name; - private String description; - private List tables; - - public CollectionConfiguration(ViewerDatabase database){ - setUuid(database.getUuid()); - setName(database.getMetadata().getName()); - setDescription(database.getMetadata().getDescription()); - setTables(new ArrayList<>()); - } - - public CollectionConfiguration() { - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public List getTables() { - return tables; - } - - public void setTables(List tables) { - this.tables = tables; - } -} diff --git a/src/main/java/com/databasepreservation/common/client/models/configuration/collection/ColumnConfiguration.java b/src/main/java/com/databasepreservation/common/client/models/configuration/collection/ColumnConfiguration.java deleted file mode 100644 index ab290f371..000000000 --- a/src/main/java/com/databasepreservation/common/client/models/configuration/collection/ColumnConfiguration.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.databasepreservation.common.client.models.configuration.collection; - -import java.io.Serializable; - -/** - * @author Gabriel Barros - */ -public class ColumnConfiguration implements Serializable { - private String id; - private String name; - private String description; - private Boolean hide; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Boolean getHide() { - return hide; - } - - public void setHide(Boolean hide) { - this.hide = hide; - } -} diff --git a/src/main/java/com/databasepreservation/common/client/models/configuration/collection/TableConfiguration.java b/src/main/java/com/databasepreservation/common/client/models/configuration/collection/TableConfiguration.java deleted file mode 100644 index db196ef66..000000000 --- a/src/main/java/com/databasepreservation/common/client/models/configuration/collection/TableConfiguration.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.databasepreservation.common.client.models.configuration.collection; - -import com.databasepreservation.common.client.models.status.denormalization.DenormalizeConfiguration; -import com.databasepreservation.common.client.models.structure.ViewerTable; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Gabriel Barros - */ -public class TableConfiguration implements Serializable { - private String uuid; - private String id; - private String name; - private String description; - private Boolean hide; - private List column; - private List relatedTables; - private DenormalizeConfiguration denormalizeConfiguration; - - public TableConfiguration(ViewerTable table){ - setUuid(table.getUuid()); - setId(table.getId()); - setName(table.getName()); - setDescription(table.getDescription()); - setHide(false); - column = new ArrayList<>(); - relatedTables = new ArrayList<>(); - denormalizeConfiguration = new DenormalizeConfiguration(); - } - - public TableConfiguration() { - } - - public String getUuid() { - return uuid; - } - - public void setUuid(String uuid) { - this.uuid = uuid; - } - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public Boolean getHide() { - return hide; - } - - public void setHide(Boolean hide) { - this.hide = hide; - } - - public List getColumn() { - return column; - } - - public void setColumn(List column) { - this.column = column; - } - - public DenormalizeConfiguration getDenormalizeConfiguration() { - return denormalizeConfiguration; - } - - public void setDenormalizeConfiguration(DenormalizeConfiguration denormalizeConfiguration) { - this.denormalizeConfiguration = denormalizeConfiguration; - } - - public List getRelatedTables() { - return relatedTables; - } - - public void setRelatedTables(List relatedTables) { - this.relatedTables = relatedTables; - } -} diff --git a/src/main/java/com/databasepreservation/common/client/models/progress/DataTransformationProgressData.java b/src/main/java/com/databasepreservation/common/client/models/progress/DataTransformationProgressData.java deleted file mode 100644 index 80649da94..000000000 --- a/src/main/java/com/databasepreservation/common/client/models/progress/DataTransformationProgressData.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.databasepreservation.common.client.models.progress; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -/** - * @author Gabriel Barros - */ -public class DataTransformationProgressData implements Serializable { - private long rowsToProcess; - private long processedRows; - private boolean finished = false; - - private static Map instances = new HashMap<>(); - - public DataTransformationProgressData() { - } - - public static DataTransformationProgressData getInstance(String jobUUID) { - return instances.computeIfAbsent(jobUUID, k -> new DataTransformationProgressData()); - } - - public static Map getInstances() { - return instances; - } - - public long getRowsToProcess() { - return rowsToProcess; - } - - public void setRowsToProcess(long rowsToProcess) { - this.rowsToProcess = rowsToProcess; - } - - public long getProcessedRows() { - return processedRows; - } - - public void setProcessedRows(long processedRows) { - this.processedRows = processedRows; - } - - public void incrementProcessedRows() { - if(this.processedRows <= this.rowsToProcess){ - this.processedRows++; - } - } - - public boolean getFinished() { - return finished; - } - - public void setFinished(boolean status) { - finished = status; - if(finished){ - this.processedRows = this.rowsToProcess; - } - } - - public void reset(){ - finished = false; - processedRows = 0; - } -} diff --git a/src/main/java/com/databasepreservation/common/client/services/JobService.java b/src/main/java/com/databasepreservation/common/client/services/JobService.java index 54592f7c2..fe934159d 100644 --- a/src/main/java/com/databasepreservation/common/client/services/JobService.java +++ b/src/main/java/com/databasepreservation/common/client/services/JobService.java @@ -1,16 +1,10 @@ package com.databasepreservation.common.client.services; -import java.util.List; -import java.util.Map; import java.util.function.Consumer; -import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; -import javax.ws.rs.core.MediaType; import org.fusesource.restygwt.client.DirectRestService; import org.fusesource.restygwt.client.MethodCallback; @@ -20,7 +14,6 @@ import com.databasepreservation.common.client.common.DefaultMethodCallback; import com.databasepreservation.common.client.index.FindRequest; import com.databasepreservation.common.client.index.IndexResult; -import com.databasepreservation.common.client.models.progress.DataTransformationProgressData; import com.databasepreservation.common.client.models.structure.ViewerJob; import com.google.gwt.core.client.GWT; diff --git a/src/main/java/com/databasepreservation/common/server/DataTransformationObserver.java b/src/main/java/com/databasepreservation/common/server/DataTransformationObserver.java deleted file mode 100644 index 2bb9ea55b..000000000 --- a/src/main/java/com/databasepreservation/common/server/DataTransformationObserver.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.databasepreservation.common.server; - -import com.databasepreservation.common.client.models.progress.DataTransformationProgressData; - -/** - * @author Gabriel Barros - */ -public class DataTransformationObserver { - private DataTransformationProgressData progressData; - - public DataTransformationObserver(String jobUUID) { - progressData = DataTransformationProgressData.getInstance(jobUUID); - progressData.setProcessedRows(0); - progressData.setFinished(false); - } - - public void notifyStartDataTransformation(long rowsToProcess){ - progressData.setRowsToProcess(rowsToProcess); - } - - public void notifyProcessedRow(){ - progressData.incrementProcessedRows(); - } - - public void notifyFinishDataTransformation(){ - progressData.setFinished(true); - } - -} diff --git a/src/main/java/com/databasepreservation/common/server/jobs/JobListener.java b/src/main/java/com/databasepreservation/common/server/jobs/JobListener.java index 45a0332b9..c3c908914 100644 --- a/src/main/java/com/databasepreservation/common/server/jobs/JobListener.java +++ b/src/main/java/com/databasepreservation/common/server/jobs/JobListener.java @@ -3,15 +3,15 @@ import java.nio.file.Files; import java.nio.file.Path; -import com.databasepreservation.common.client.models.structure.ViewerDatabase; -import com.databasepreservation.common.server.ViewerFactory; import org.roda.core.data.exceptions.GenericException; import org.roda.core.data.exceptions.NotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.batch.core.BatchStatus; import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.explore.JobExplorer; import org.springframework.batch.core.listener.JobExecutionListenerSupport; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.databasepreservation.common.client.ViewerConstants; diff --git a/src/main/java/com/databasepreservation/common/transformers/DenormalizeTransformer.java b/src/main/java/com/databasepreservation/common/transformers/DenormalizeTransformer.java index c7d4b444d..3a6a0b713 100644 --- a/src/main/java/com/databasepreservation/common/transformers/DenormalizeTransformer.java +++ b/src/main/java/com/databasepreservation/common/transformers/DenormalizeTransformer.java @@ -27,7 +27,6 @@ import com.databasepreservation.common.client.models.structure.ViewerDatabase; import com.databasepreservation.common.client.models.structure.ViewerRow; import com.databasepreservation.common.client.tools.FilterUtils; -import com.databasepreservation.common.server.DataTransformationObserver; import com.databasepreservation.common.server.ViewerConfiguration; import com.databasepreservation.common.server.ViewerFactory; import com.databasepreservation.common.server.index.DatabaseRowsSolrManager; @@ -46,13 +45,11 @@ public class DenormalizeTransformer { private final String databaseUUID; private final String jobUUID; private final String tableUUID; - private DataTransformationObserver observer; public DenormalizeTransformer(String databaseUUID, String tableUUID, String jobUUID) throws ModuleException { this.databaseUUID = databaseUUID; this.jobUUID = jobUUID; this.tableUUID = tableUUID; - observer = new DataTransformationObserver(jobUUID); solrManager = ViewerFactory.getSolrManager(); try { database = solrManager.retrieve(ViewerDatabase.class, this.databaseUUID); @@ -63,7 +60,6 @@ public DenormalizeTransformer(String databaseUUID, String tableUUID, String jobU queryOverRootTable(); updateCollectionStatus(); } catch (NotFoundException | GenericException e) { - observer.notifyFinishDataTransformation(); throw new ModuleException().withMessage("Cannot retrieved database from solr"); } }