Skip to content

Commit

Permalink
Added notifications for various failure cases. #10623
Browse files Browse the repository at this point in the history
  • Loading branch information
landreev committed Aug 19, 2024
1 parent 9c62b81 commit 8cdff8d
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 59 deletions.
27 changes: 26 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/MailServiceBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -623,6 +623,7 @@ public String getMessageTextBasedOnNotification(UserNotification userNotificatio
comment
)) ;
return downloadCompletedMessage;

case GLOBUSUPLOADCOMPLETEDWITHERRORS:
dataset = (Dataset) targetObject;
messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
Expand All @@ -633,8 +634,30 @@ public String getMessageTextBasedOnNotification(UserNotification userNotificatio
comment
)) ;
return uploadCompletedWithErrorsMessage;

case GLOBUSUPLOADREMOTEFAILURE:
dataset = (Dataset) targetObject;
messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
String uploadFailedRemotelyMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.upload.failedRemotely", Arrays.asList(
systemConfig.getDataverseSiteUrl(),
dataset.getGlobalId().asString(),
dataset.getDisplayName(),
comment
)) ;
return uploadFailedRemotelyMessage;

case GLOBUSDOWNLOADCOMPLETEDWITHERRORS:
case GLOBUSUPLOADLOCALFAILURE:
dataset = (Dataset) targetObject;
messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
String uploadFailedLocallyMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.upload.failedLocally", Arrays.asList(
systemConfig.getDataverseSiteUrl(),
dataset.getGlobalId().asString(),
dataset.getDisplayName(),
comment
)) ;
return uploadFailedLocallyMessage;

case GLOBUSDOWNLOADCOMPLETEDWITHERRORS:
dataset = (Dataset) targetObject;
messageText = BundleUtil.getStringFromBundle("notification.email.greeting.html");
String downloadCompletedWithErrorsMessage = messageText + BundleUtil.getStringFromBundle("notification.mail.globus.download.completedWithErrors", Arrays.asList(
Expand Down Expand Up @@ -763,6 +786,8 @@ public Object getObjectOfNotification (UserNotification userNotification){
return versionService.find(userNotification.getObjectId());
case GLOBUSUPLOADCOMPLETED:
case GLOBUSUPLOADCOMPLETEDWITHERRORS:
case GLOBUSUPLOADREMOTEFAILURE:
case GLOBUSUPLOADLOCALFAILURE:
case GLOBUSDOWNLOADCOMPLETED:
case GLOBUSDOWNLOADCOMPLETEDWITHERRORS:
return datasetService.find(userNotification.getObjectId());
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/edu/harvard/iq/dataverse/UserNotification.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ public enum Type {
CHECKSUMIMPORT, CHECKSUMFAIL, CONFIRMEMAIL, APIGENERATED, INGESTCOMPLETED, INGESTCOMPLETEDWITHERRORS,
PUBLISHFAILED_PIDREG, WORKFLOW_SUCCESS, WORKFLOW_FAILURE, STATUSUPDATED, DATASETCREATED, DATASETMENTIONED,
GLOBUSUPLOADCOMPLETED, GLOBUSUPLOADCOMPLETEDWITHERRORS,
GLOBUSDOWNLOADCOMPLETED, GLOBUSDOWNLOADCOMPLETEDWITHERRORS, REQUESTEDFILEACCESS;
GLOBUSDOWNLOADCOMPLETED, GLOBUSDOWNLOADCOMPLETEDWITHERRORS, REQUESTEDFILEACCESS,
GLOBUSUPLOADREMOTEFAILURE, GLOBUSUPLOADLOCALFAILURE;

public String getDescription() {
return BundleUtil.getStringFromBundle("notification.typeDescription." + this.name());
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ private ApiConstants() {
public static final String DS_VERSION_LATEST = ":latest";
public static final String DS_VERSION_DRAFT = ":draft";
public static final String DS_VERSION_LATEST_PUBLISHED = ":latest-published";

// addFiles call
public static final String API_ADD_FILES_COUNT_PROCESSED = "Total number of files";
public static final String API_ADD_FILES_COUNT_SUCCESSFULL = "Number of files successfully added";
}
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,8 @@ public void displayNotification() {
case GLOBUSUPLOADCOMPLETEDWITHERRORS:
case GLOBUSDOWNLOADCOMPLETED:
case GLOBUSDOWNLOADCOMPLETEDWITHERRORS:
case GLOBUSUPLOADREMOTEFAILURE:
case GLOBUSUPLOADLOCALFAILURE:
userNotification.setTheObject(datasetService.find(userNotification.getObjectId()));
break;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2167,8 +2167,8 @@ public Response addFiles(String jsonData, Dataset dataset, User authUser) {
}

JsonObjectBuilder result = Json.createObjectBuilder()
.add("Total number of files", totalNumberofFiles)
.add("Number of files successfully added", successNumberofFiles);
.add(ApiConstants.API_ADD_FILES_COUNT_PROCESSED, totalNumberofFiles)
.add(ApiConstants.API_ADD_FILES_COUNT_SUCCESSFULL, successNumberofFiles);


return Response.ok().entity(Json.createObjectBuilder()
Expand Down
120 changes: 69 additions & 51 deletions src/main/java/edu/harvard/iq/dataverse/globus/GlobusServiceBean.java
Original file line number Diff line number Diff line change
Expand Up @@ -766,7 +766,7 @@ public void globusUpload(JsonObject jsonData, ApiToken token, Dataset dataset, S

boolean taskSuccess = GlobusUtil.isTaskCompleted(taskState);

processCompletedUploadTask(dataset, filesJsonArray, authUser, ruleId, globusLogger, fileHandler, taskSuccess, taskStatus);
processCompletedUploadTask(dataset, filesJsonArray, authUser, ruleId, globusLogger, taskSuccess, taskStatus);

if (fileHandler != null) {
fileHandler.close();
Expand Down Expand Up @@ -798,7 +798,6 @@ private void processCompletedUploadTask(Dataset dataset,
AuthenticatedUser authUser,
String ruleId,
Logger globusLogger,
FileHandler fileHandler,
boolean taskSuccess,
String taskStatus) {

Expand Down Expand Up @@ -861,11 +860,17 @@ private void processCompletedUploadTask(Dataset dataset,
}

if (!taskSuccess) {
String comment = "Reason : " + taskStatus.split("#")[1] + "<br> Short Description : "
+ taskStatus.split("#")[2];
String comment;
if (taskStatus != null) {
comment = "Reason : " + taskStatus.split("#")[1] + "<br> Short Description : "
+ taskStatus.split("#")[2];
} else {
comment = "No further information available";
}

myLogger.info("Globus Upload task failed ");
userNotificationService.sendNotification((AuthenticatedUser) authUser, new Timestamp(new Date().getTime()),
UserNotification.Type.GLOBUSUPLOADCOMPLETEDWITHERRORS, dataset.getId(), comment, true);
myLogger.info("Globus task failed ");
UserNotification.Type.GLOBUSUPLOADREMOTEFAILURE, dataset.getId(), comment, true);

} else {
try {
Expand Down Expand Up @@ -908,6 +913,8 @@ private void processUploadedFiles(JsonArray filesJsonArray, Dataset dataset, Aut
Integer countAll = 0;
Integer countSuccess = 0;
Integer countError = 0;
Integer countAddFilesSuccess = 0;
String notificationErrorMessage = "";

List<String> inputList = new ArrayList<String>();

Expand Down Expand Up @@ -991,13 +998,22 @@ private void processUploadedFiles(JsonArray filesJsonArray, Dataset dataset, Aut
myLogger.info("Files processed successfully: " + countSuccess);
myLogger.info("Files failures to process: " + countError);

/*String command = "curl -H \"X-Dataverse-key:" + token.getTokenString() + "\" -X POST "
+ httpRequestUrl + "/api/datasets/:persistentId/addFiles?persistentId=doi:"
+ datasetIdentifier + " -F jsonData='" + newjsonData + "'";
System.out.println("*******====command ==== " + command);*/
// ToDo - refactor to call AddReplaceFileHelper.addFiles directly instead of
// calling API
// a quick experimental AddReplaceFileHelper implementation:
if (countSuccess < 1) {
// We don't have any valid entries to call addFiles() for; so, no
// need to proceed.
notificationErrorMessage = "Failed to successfully process any of the file entries, "
+ "out of the " + countAll + " total as submitted to Dataverse";
userNotificationService.sendNotification((AuthenticatedUser) authUser,
new Timestamp(new Date().getTime()), UserNotification.Type.GLOBUSUPLOADREMOTEFAILURE,
dataset.getId(), notificationErrorMessage, true);
return;
} else if (countSuccess < countAll) {
notificationErrorMessage = "Out of the " + countAll + " file entries submitted to /addGlobusFiles "
+ "only " + countSuccess + " could be successfully parsed and processed. ";
}

// A new AddReplaceFileHelper implementation, replacing the old one that
// was relying on calling /addFiles api via curl:

// Passing null for the HttpServletRequest to make a new DataverseRequest.
// The parent method is always executed asynchronously, so the real request
Expand Down Expand Up @@ -1028,55 +1044,57 @@ private void processUploadedFiles(JsonArray filesJsonArray, Dataset dataset, Aut

JsonObject addFilesJsonObject = JsonUtil.getJsonObject(addFilesResponse.getEntity().toString());

// @todo null checks etc.
// @todo null check?
String addFilesStatus = addFilesJsonObject.getString("status", null);
myLogger.info("addFilesResponse status: " + addFilesStatus);


if (ApiConstants.STATUS_OK.equalsIgnoreCase(addFilesStatus)) {
if (addFilesJsonObject.containsKey("data")) {
JsonObject responseFilesData = addFilesJsonObject.getJsonObject("data");
if (responseFilesData.containsKey("Result")) {
JsonObject addFilesResult = responseFilesData.getJsonObject("Result");

Integer addFilesTotal = addFilesResult.getInt("Total number of files", -1);
Integer addFilesSuccess = addFilesResult.getInt("Number of files successfully added", -1);
// @todo handle -1 (missing values) above
// @todo log all this stuff in a task-specific log (??)
myLogger.info("Files processed by addFiles: " + addFilesTotal + ", successfully added: " + addFilesSuccess);
// @todo incorporate this into the user notification
} else {
logger.warning("Malformed addFiles data section: "+ responseFilesData.toString());
}
} else {
logger.warning("Malformed addFiles response json: " + addFilesJsonObject.toString());
}

// if(!taskSkippedFiles)
if (countError == 0) {
userNotificationService.sendNotification((AuthenticatedUser) authUser,
new Timestamp(new Date().getTime()), UserNotification.Type.GLOBUSUPLOADCOMPLETED,
dataset.getId(), countSuccess + " files added out of " + countAll, true);
if (addFilesJsonObject.containsKey("data") && addFilesJsonObject.getJsonObject("data").containsKey("Result")) {

//Integer countAddFilesTotal = addFilesJsonObject.getJsonObject("data").getJsonObject("Result").getInt(ApiConstants.API_ADD_FILES_COUNT_PROCESSED, -1);
countAddFilesSuccess = addFilesJsonObject.getJsonObject("data").getJsonObject("Result").getInt(ApiConstants.API_ADD_FILES_COUNT_SUCCESSFULL, -1);
myLogger.info("Files successfully added by addFiles(): " + countAddFilesSuccess);

} else {
userNotificationService.sendNotification((AuthenticatedUser) authUser,
new Timestamp(new Date().getTime()),
UserNotification.Type.GLOBUSUPLOADCOMPLETEDWITHERRORS, dataset.getId(),
countSuccess + " files added out of " + countAll, true);
myLogger.warning("Malformed addFiles response json: " + addFilesJsonObject.toString());
notificationErrorMessage = "Malformed response received when attempting to add the files to the dataset. ";
}
myLogger.info("Successfully completed addFiles call ");

myLogger.info("Completed addFiles call ");
} else if (ApiConstants.STATUS_ERROR.equalsIgnoreCase(addFilesStatus)) {
String addFilesMessage = addFilesJsonObject.getString("message", null);

myLogger.log(Level.SEVERE,
"******* Error while executing addFiles ", newjsonData);
myLogger.log(Level.SEVERE, "****** Output from addFiles: ", addFilesMessage);
// @todo send Failure notification
notificationErrorMessage += "Error response received when attempting to add the files to the dataset: " + addFilesMessage + " ";

} else {
myLogger.log(Level.SEVERE,
"******* Error while executing addFiles ", newjsonData);
// @todo send Failure notification
notificationErrorMessage += "Unexpected error encountered when attemptingh to add the files to the dataset.";
}

// if(!taskSkippedFiles)
if (countAddFilesSuccess == countAll) {
userNotificationService.sendNotification((AuthenticatedUser) authUser,
new Timestamp(new Date().getTime()), UserNotification.Type.GLOBUSUPLOADCOMPLETED,
dataset.getId(), countSuccess + " files added out of " + countAll, true);
} else if (countAddFilesSuccess > 0) {
// success, but partial:
userNotificationService.sendNotification((AuthenticatedUser) authUser,
new Timestamp(new Date().getTime()),
UserNotification.Type.GLOBUSUPLOADCOMPLETEDWITHERRORS, dataset.getId(),
countSuccess + " files added out of " + countAll + notificationErrorMessage, true);
} else {
notificationErrorMessage = "".equals(notificationErrorMessage)
? " No additional information is available." : notificationErrorMessage;
userNotificationService.sendNotification((AuthenticatedUser) authUser,
new Timestamp(new Date().getTime()),
UserNotification.Type.GLOBUSUPLOADLOCALFAILURE, dataset.getId(),
notificationErrorMessage, true);
}

}

@Asynchronous
Expand Down Expand Up @@ -1140,7 +1158,7 @@ public void globusDownload(String jsonData, Dataset dataset, User authUser) thro
logger.warning("ruleId not found for taskId: " + taskIdentifier);
}
task = globusStatusCheck(endpoint, taskIdentifier, globusLogger);
// @todo null check
// @todo null check?
String taskStatus = GlobusUtil.getTaskStatus(task);

// Transfer is done (success or failure) so delete the rule
Expand Down Expand Up @@ -1427,13 +1445,13 @@ public List<ExternalFileUploadInProgress> findExternalUploadsByTaskId(String tas
return em.createNamedQuery("ExternalFileUploadInProgress.findByTaskId").setParameter("taskId", taskId).getResultList();
}

// @todo duplicated code, merge with the code handling the "classic" upload workflow
public void processCompletedTask(GlobusTaskInProgress globusTask, boolean taskSuccess, String taskStatus, Logger taskLogger) {
String ruleId = globusTask.getRuleId();
Dataset dataset = globusTask.getDataset();
AuthenticatedUser authUser = authSvc.lookupUser(globusTask.getApiToken());
if (authUser == null) {
// @todo log error message; do nothing
// (the fields in GlobusTaskInProgress are not nullable though - ?)
return;
}

Expand All @@ -1442,6 +1460,7 @@ public void processCompletedTask(GlobusTaskInProgress globusTask, boolean taskSu

if (fileUploadsInProgress == null || fileUploadsInProgress.size() < 1) {
// @todo log error message; do nothing
// (will this ever happen though?)
return;
}

Expand All @@ -1455,10 +1474,9 @@ public void processCompletedTask(GlobusTaskInProgress globusTask, boolean taskSu

JsonArray filesJsonArray = filesJsonArrayBuilder.build();

//processCompletedUploadTask(dataset, filesJsonArray, authUser, ruleId, globusLogger, fileHandler, taskSuccess, taskStatus);
processCompletedUploadTask(dataset, filesJsonArray, authUser, ruleId, taskLogger, null, taskSuccess, taskStatus);
processCompletedUploadTask(dataset, filesJsonArray, authUser, ruleId, taskLogger, taskSuccess, taskStatus);
} else {
// @todo extend this async. framework to handle Glonus downloads as well
// @todo eventually, extend this async. framework to handle Glonus downloads as well
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ public void init() {
/**
* This method will be executed on a timer-like schedule, continuously
* monitoring all the ongoing external Globus tasks (transfers).
* @todo make sure the executions do not overlap/stack up
*/
public void checkOngoingTasks() {
logger.info("Performing a scheduled external Globus task check");
Expand All @@ -90,7 +89,7 @@ public void checkOngoingTasks() {

if (taskLogHandler != null) {
// @todo it should be prudent to cache these loggers and handlers
// between monitoring runs
// between monitoring runs (should be fairly easy to do)
taskLogHandler.close();
}
});
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/util/MailUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,23 @@ public static String getSubjectTextBasedOnNotification(UserNotification userNoti
} catch (Exception e) {
return BundleUtil.getStringFromBundle("notification.email.globus.uploadCompletedWithErrors.subject", rootDvNameAsList);
}
case GLOBUSUPLOADREMOTEFAILURE:
try {
DatasetVersion version = (DatasetVersion)objectOfNotification;
List<String> dsNameAsList = Arrays.asList(version.getDataset().getDisplayName());
return BundleUtil.getStringFromBundle("notification.email.globus.uploadFailedRemotely.subject", dsNameAsList);

} catch (Exception e) {
return BundleUtil.getStringFromBundle("notification.email.globus.uploadFailedRemotely.subject", rootDvNameAsList);
}
case GLOBUSUPLOADLOCALFAILURE:
try {
DatasetVersion version = (DatasetVersion)objectOfNotification;
List<String> dsNameAsList = Arrays.asList(version.getDataset().getDisplayName());
return BundleUtil.getStringFromBundle("notification.email.globus.uploadFailedLocally.subject", dsNameAsList);
} catch (Exception e) {
return BundleUtil.getStringFromBundle("notification.email.globus.uploadFailedLocally.subject", rootDvNameAsList);
}
case GLOBUSDOWNLOADCOMPLETEDWITHERRORS:
try {
DatasetVersion version = (DatasetVersion)objectOfNotification;
Expand Down
Loading

0 comments on commit 8cdff8d

Please sign in to comment.