Skip to content

Commit a9319b6

Browse files
authored
fix(TCDICORE-498): auto-fail stuck datasets and add force-fail button (#45)
1 parent b5523b6 commit a9319b6

File tree

6 files changed

+149
-23
lines changed

6 files changed

+149
-23
lines changed

forms/src/main/java/org/devgateway/toolkit/forms/service/DatasetClientService.java

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import org.apache.commons.io.FileUtils;
44
import org.devgateway.toolkit.forms.client.DataSetClientException;
55
import org.devgateway.toolkit.forms.client.DatasetClient;
6+
import org.devgateway.toolkit.forms.client.DatasetJobStatus;
67
import org.devgateway.toolkit.persistence.dao.data.CSVDataset;
78
import org.devgateway.toolkit.persistence.dao.data.Dataset;
89
import org.devgateway.toolkit.persistence.dao.data.TetsimDataset;
@@ -28,6 +29,7 @@
2829
import static org.devgateway.toolkit.persistence.dao.DBConstants.Status.ERROR_IN_UNPUBLISHING;
2930
import static org.devgateway.toolkit.persistence.dao.DBConstants.Status.PUBLISHED;
3031
import static org.devgateway.toolkit.persistence.dao.DBConstants.Status.PUBLISHING;
32+
import static org.devgateway.toolkit.persistence.dao.DBConstants.Status.UNPUBLISHING;
3133

3234
@Service
3335
public class DatasetClientService {
@@ -55,34 +57,66 @@ public void triggerCheckDatasetsJob() {
5557

5658
private void checkDatasetJobs(List<Dataset> datasets) {
5759
datasets.forEach(d -> {
58-
ServiceMetadata serviceMetadata = eurekaClientService.findByName(d.getDestinationService());
59-
DatasetClient client = new DatasetClient(serviceMetadata.getUrl());
60-
String status = client.getDatasetJobStatus(CODE_PREFIX + d.getId()).getStatus();
61-
String initialStatus = d.getStatus();
62-
if (COMPLETED.equals(status)) {
63-
String completedStatus = getCompletedStatus(initialStatus);
64-
d.setStatus(completedStatus);
65-
logger.info(String.format("The dataset with id %s changed the status from %s to %s",
66-
d.getId(), initialStatus, completedStatus));
67-
} else if (ERROR.equals(status)) {
68-
String errorStatus = getErrorStatus(initialStatus);
69-
d.setStatus(errorStatus);
70-
logger.info(String.format("The dataset with id %s changed the status from %s to %s",
71-
d.getId(), initialStatus, errorStatus));
72-
}
73-
74-
if (!initialStatus.equals(d.getStatus())) {
75-
if (d instanceof TetsimDataset) {
76-
tetsimDatasetService.save((TetsimDataset) d);
77-
} else if (d instanceof CSVDataset) {
78-
csvDatasetService.save((CSVDataset) d);
60+
try {
61+
ServiceMetadata serviceMetadata = eurekaClientService.findByName(d.getDestinationService());
62+
DatasetClient client = new DatasetClient(serviceMetadata.getUrl());
63+
DatasetJobStatus jobStatus = client.getDatasetJobStatus(CODE_PREFIX + d.getId());
64+
String initialStatus = d.getStatus();
65+
66+
if (jobStatus == null) {
67+
// Remote service returned a non-2xx response (job not found or server error) — auto-fail
68+
String errorStatus = getErrorStatus(initialStatus);
69+
d.setStatus(errorStatus);
70+
logger.warn("Dataset {} job not found on remote service, auto-failing from {} to {}",
71+
d.getId(), initialStatus, errorStatus);
7972
} else {
80-
throw new RuntimeException("Invalid dataset class");
73+
String status = jobStatus.getStatus();
74+
if (COMPLETED.equals(status)) {
75+
String completedStatus = getCompletedStatus(initialStatus);
76+
d.setStatus(completedStatus);
77+
logger.info("The dataset with id {} changed the status from {} to {}",
78+
d.getId(), initialStatus, completedStatus);
79+
} else if (ERROR.equals(status)) {
80+
String errorStatus = getErrorStatus(initialStatus);
81+
d.setStatus(errorStatus);
82+
logger.info("The dataset with id {} changed the status from {} to {}",
83+
d.getId(), initialStatus, errorStatus);
84+
}
85+
}
86+
87+
if (!initialStatus.equals(d.getStatus())) {
88+
if (d instanceof TetsimDataset) {
89+
tetsimDatasetService.save((TetsimDataset) d);
90+
} else if (d instanceof CSVDataset) {
91+
csvDatasetService.save((CSVDataset) d);
92+
} else {
93+
throw new RuntimeException("Invalid dataset class");
94+
}
8195
}
96+
} catch (Exception e) {
97+
logger.error("Failed to check job status for dataset {}: {}", d.getId(), e.getMessage(), e);
8298
}
8399
});
84100
}
85101

102+
public void forceFailPublishing(Dataset dataset) {
103+
String status = dataset.getStatus();
104+
if (!PUBLISHING.equals(status) && !UNPUBLISHING.equals(status)) {
105+
throw new IllegalStateException("Dataset " + dataset.getId()
106+
+ " is not in PUBLISHING or UNPUBLISHING state: " + status);
107+
}
108+
String errorStatus = getErrorStatus(status);
109+
dataset.setStatus(errorStatus);
110+
logger.info("Force failing dataset {} from status {} to {}", dataset.getId(), status, errorStatus);
111+
if (dataset instanceof TetsimDataset) {
112+
tetsimDatasetService.save((TetsimDataset) dataset);
113+
} else if (dataset instanceof CSVDataset) {
114+
csvDatasetService.save((CSVDataset) dataset);
115+
} else {
116+
throw new RuntimeException("Invalid dataset class");
117+
}
118+
}
119+
86120
private String getCompletedStatus(final String status) {
87121
return PUBLISHING.equals(status) ? PUBLISHED : DRAFT;
88122
}

forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/edit/AbstractEditStatusEntityPage.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,13 @@
8787
<button wicket:id="submitAndNext" type="button" class="btn btn-info btn-form-action">Save & Next</button>
8888
<button wicket:id="saveApprove" type="button" class="btn btn-success btn-form-action">Save & Approve</button>
8989
<button wicket:id="approve" type="button" class="btn btn-success btn-form-action">Approve</button>
90-
<button wicket:id="revertToDraft" type="button" class="btn btn-warning btn-form-action">Save & Validate</button>
90+
<button wicket:id="revertToDraft" type="button" class="btn btn-warning btn-form-action">Unpublish</button>
91+
<button wicket:id="forceFail" type="button" class="btn btn-danger btn-form-action">Force Fail</button>
9192
</wicket:fragment>
9293

9394
<div wicket:id="approveModal"></div>
9495
<div wicket:id="unpublishModal"></div>
96+
<div wicket:id="forceFailModal"></div>
9597

9698
<wicket:fragment wicket:id="noButtons"></wicket:fragment>
9799
</wicket:extend>

forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/edit/AbstractEditStatusEntityPage.java

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,14 @@ public abstract class AbstractEditStatusEntityPage<T extends AbstractStatusAudit
9393

9494
protected SaveEditPageButton revertToDraftPageButton;
9595

96+
protected SaveEditPageButton forceFailButton;
97+
9698
protected TextContentModal approveModal;
9799

98100
protected TextContentModal unpublishModal;
99101

102+
protected TextContentModal forceFailModal;
103+
100104
private CheckBoxYesNoToggleBootstrapFormComponent visibleStatusComments;
101105

102106
private TransparentWebMarkupContainer statusCommentsWrapper;
@@ -316,9 +320,15 @@ protected void onInitialize() {
316320
revertToDraftPageButton = getRevertToDraftPageButton();
317321
entityButtonsFragment.add(revertToDraftPageButton);
318322

323+
forceFailButton = getForceFailPageButton();
324+
entityButtonsFragment.add(forceFailButton);
325+
319326
unpublishModal = createUnpublishModal();
320327
editForm.add(unpublishModal);
321328

329+
forceFailModal = createForceFailModal();
330+
editForm.add(forceFailModal);
331+
322332
applyDraftSaveBehavior(saveButton);
323333
applyDraftSaveBehavior(saveDraftContinueButton);
324334
applyDraftSaveBehavior(revertToDraftPageButton);
@@ -766,6 +776,51 @@ protected void onError(final AjaxRequestTarget target) {
766776
return saveEditPageButton;
767777
}
768778

779+
protected SaveEditPageButton getForceFailPageButton() {
780+
final SaveEditPageButton button = new SaveEditPageButton("forceFail",
781+
new StringResourceModel("forceFailButton", this, null)) {
782+
783+
@Override
784+
protected void onSubmit(final AjaxRequestTarget target) {
785+
forceFailModal.show(true);
786+
target.add(forceFailModal);
787+
}
788+
789+
@Override
790+
protected void onError(final AjaxRequestTarget target) {
791+
super.onError(target);
792+
target.add(feedbackPanel);
793+
}
794+
};
795+
button.setType(Buttons.Type.Danger);
796+
button.setIconType(FontAwesome5IconType.exclamation_triangle_s);
797+
return button;
798+
}
799+
800+
protected TextContentModal createForceFailModal() {
801+
final TextContentModal modal = new TextContentModal("forceFailModal",
802+
new StringResourceModel("forceFailModal", this, null));
803+
804+
final SaveEditPageButton confirmButton = new SaveEditPageButton("button", Model.of("Yes")) {
805+
@Override
806+
protected String getOnClickScript() {
807+
return WebConstants.DISABLE_FORM_LEAVING_JS;
808+
}
809+
810+
@Override
811+
protected void onSubmit(final AjaxRequestTarget target) {
812+
onForceFailPublishing(target);
813+
super.onSubmit(target);
814+
}
815+
};
816+
confirmButton.setType(Buttons.Type.Danger);
817+
confirmButton.setIconType(FontAwesome5IconType.exclamation_triangle_s);
818+
modal.addButton(confirmButton);
819+
modal.addCloseButton(Model.of("No"));
820+
821+
return modal;
822+
}
823+
769824
protected void onAfterRevertToDraft(AjaxRequestTarget target) {
770825

771826
}
@@ -774,6 +829,10 @@ protected void onApprove(AjaxRequestTarget target) {
774829

775830
}
776831

832+
protected void onForceFailPublishing(AjaxRequestTarget target) {
833+
834+
}
835+
777836
protected void setStatusAppendComment(final String status) {
778837
final T saveable = editForm.getModelObject();
779838

@@ -798,6 +857,7 @@ protected void setButtonsPermissions() {
798857
addSaveApproveButtonPermissions(saveApproveButton);
799858
addApproveButtonPermissions(approveButton);
800859
addSaveRevertButtonPermissions(revertToDraftPageButton);
860+
addForceFailButtonPermissions(forceFailButton);
801861
addDeleteButtonPermissions(deleteButton);
802862

803863
// no need to display the buttons on print view so we overwrite the above permissions
@@ -824,6 +884,12 @@ protected void addSaveRevertButtonPermissions(final Component button) {
824884
|| ERROR_IN_UNPUBLISHING.equals(editForm.getModelObject().getStatus())));
825885
}
826886

887+
protected void addForceFailButtonPermissions(final Component button) {
888+
MetaDataRoleAuthorizationStrategy.authorize(button, Component.RENDER, SecurityConstants.Roles.ROLE_ADMIN);
889+
button.setVisibilityAllowed(PUBLISHING.equals(editForm.getModelObject().getStatus())
890+
|| UNPUBLISHING.equals(editForm.getModelObject().getStatus()));
891+
}
892+
827893
protected void addSaveApproveButtonPermissions(final Component button) {
828894
addDefaultAllButtonsPermissions(button);
829895
MetaDataRoleAuthorizationStrategy.authorize(

forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/edit/AbstractEditStatusEntityPage.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,5 @@ autosave_message=Form is saving
2020
autoSaveLabelMessage=Form auto-saved less than {0,number} minutes ago.
2121
checkedOutToMessage=Checked out to user {0}.
2222
errorInPublishingTitle=There was an error during {0}. Please check the data and try to republish it. If it doesn't work please contact the admin.
23+
forceFailButton=Force Fail
24+
forceFailModal=Are you sure you want to force fail this publishing process? The dataset status will be set to error and it will need to be re-published.

forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/edit/dataset/EditCSVDatasetPage.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,17 @@ protected void onApprove(final AjaxRequestTarget target) {
226226
setResponsePage(listPageClass);
227227
}
228228

229+
@Override
230+
protected void onForceFailPublishing(final AjaxRequestTarget target) {
231+
try {
232+
datasetClientService.forceFailPublishing(editForm.getModelObject());
233+
} catch (Exception e) {
234+
logger.error(e.getMessage(), e);
235+
failedModal.show(target);
236+
}
237+
setResponsePage(listPageClass, getSaveEditParameters());
238+
}
239+
229240
protected BootstrapCancelButton getCancelButton(final String id) {
230241
return new CancelEditPageButton(id, new StringResourceModel("cancelButton", this, null));
231242
}

forms/src/main/java/org/devgateway/toolkit/forms/wicket/page/edit/dataset/EditTetsimDatasetPage.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,17 @@ protected void onApprove(final AjaxRequestTarget target) {
164164
setResponsePage(listPageClass);
165165
}
166166

167+
@Override
168+
protected void onForceFailPublishing(final AjaxRequestTarget target) {
169+
try {
170+
datasetClientService.forceFailPublishing(editForm.getModelObject());
171+
} catch (Exception e) {
172+
logger.error(e.getMessage(), e);
173+
failedModal.show(target);
174+
}
175+
setResponsePage(listPageClass);
176+
}
177+
167178
protected BootstrapCancelButton getCancelButton(final String id) {
168179
return new CancelEditPageButton(id, new StringResourceModel("cancelButton", this, null));
169180
}

0 commit comments

Comments
 (0)