From 043a8dc72cc33a55d868874dfd486238aedfa5fc Mon Sep 17 00:00:00 2001 From: Mateusz Warowny Date: Mon, 28 Feb 2022 17:16:09 +0100 Subject: [PATCH] JAL-3878 Separate server job handle from task's sub jobs. The former is represented by WebServiceJobHandle class which is a immutable container of data identifying the job on the server. The latter, represented by JobI interface, stores the current state of the job. In principle, a service job does not need to be tied to a web service client. --- .../ws2/actions/alignment/AlignmentProviderI.java | 4 +- src/jalview/ws2/actions/api/JobI.java | 35 ++++ src/jalview/ws2/actions/api/TaskEventListener.java | 59 +++--- src/jalview/ws2/actions/api/TaskI.java | 22 ++- src/jalview/ws2/api/WebServiceJob.java | 189 -------------------- src/jalview/ws2/api/WebServiceJobHandle.java | 74 ++++++++ src/jalview/ws2/client/api/WebServiceClientI.java | 52 ++++-- 7 files changed, 191 insertions(+), 244 deletions(-) create mode 100644 src/jalview/ws2/actions/api/JobI.java delete mode 100644 src/jalview/ws2/api/WebServiceJob.java create mode 100644 src/jalview/ws2/api/WebServiceJobHandle.java diff --git a/src/jalview/ws2/actions/alignment/AlignmentProviderI.java b/src/jalview/ws2/actions/alignment/AlignmentProviderI.java index caba526..4ed5c55 100644 --- a/src/jalview/ws2/actions/alignment/AlignmentProviderI.java +++ b/src/jalview/ws2/actions/alignment/AlignmentProviderI.java @@ -4,7 +4,7 @@ import java.io.IOException; import jalview.datamodel.AlignmentI; -import jalview.ws2.api.WebServiceJob; +import jalview.ws2.api.WebServiceJobHandle; import jalview.ws2.client.api.AlignmentWebServiceClientI; import jalview.ws2.client.api.WebServiceClientI; @@ -28,5 +28,5 @@ public interface AlignmentProviderI * @throws IOException * server communication error */ - public AlignmentI getAlignemnt(WebServiceJob job) throws IOException; + public AlignmentI getAlignemnt(WebServiceJobHandle job) throws IOException; } diff --git a/src/jalview/ws2/actions/api/JobI.java b/src/jalview/ws2/actions/api/JobI.java new file mode 100644 index 0000000..a2643f0 --- /dev/null +++ b/src/jalview/ws2/actions/api/JobI.java @@ -0,0 +1,35 @@ +package jalview.ws2.actions.api; + +import jalview.util.MathUtils; +import jalview.ws2.api.JobStatus; + +public interface JobI +{ + /** + * Get a unique job id used internally by jalview. + * + * @return unique job id + */ + long getInternalId(); + + /** + * Get the status of this job + * + * @return job status + */ + JobStatus getStatus(); + + /** + * Get the log for this job + * + * @return sub job log + */ + String getLog(); + + /** + * Get the error log for this job. + * + * @return sub job error log + */ + String getErrorLog(); +} diff --git a/src/jalview/ws2/actions/api/TaskEventListener.java b/src/jalview/ws2/actions/api/TaskEventListener.java index 3dda2a4..94de9d0 100644 --- a/src/jalview/ws2/actions/api/TaskEventListener.java +++ b/src/jalview/ws2/actions/api/TaskEventListener.java @@ -3,7 +3,7 @@ package jalview.ws2.actions.api; import java.util.List; import jalview.ws2.api.JobStatus; -import jalview.ws2.api.WebServiceJob; +import jalview.ws2.api.WebServiceJobHandle; /** * The listener interface for receiving relevant job progress and state change @@ -22,35 +22,34 @@ public interface TaskEventListener /** * Invoked when the task has been started. The {@code subJobs} parameter * contains a complete list of sub-jobs for that run. Note that restartable - * tasks may invoke this method multiple times with different set of - * sub-jobs. + * tasks may invoke this method multiple times with different set of sub-jobs. * * @param source - * task this event originates from + * task this event originates from * @param subJobs - * list of sub-jobs for this run + * list of sub-jobs for this run */ - void taskStarted(TaskI source, List subJobs); + void taskStarted(TaskI source, List subJobs); /** * Invoked when the global task status has changed. * * @param source - * task this event originates from + * task this event originates from * @param status - * new task status + * new task status */ void taskStatusChanged(TaskI source, JobStatus status); /** * Invoked when the task has completed. If the task completed with a result, - * that result is passed in the call argument, otherwise, a {@code null} - * value is given. + * that result is passed in the call argument, otherwise, a {@code null} value + * is given. * * @param source - * task this event originates from + * task this event originates from * @param result - * computation result or null if result not present + * computation result or null if result not present */ void taskCompleted(TaskI source, T result); @@ -58,19 +57,19 @@ public interface TaskEventListener * Invoked when an unhandled exception has occurred during task execution. * * @param source - * task this event originates from + * task this event originates from * @param e - * exception + * exception */ void taskException(TaskI source, Exception e); /** - * Invoked when the task had been restarted. This event is only applicable - * to restartable tasks and will precede each {@link #taskStarted} after - * the first one. + * Invoked when the task had been restarted. This event is only applicable to + * restartable tasks and will precede each {@link #taskStarted} after the + * first one. * * @param source - * task this event originates from + * task this event originates from */ void taskRestarted(TaskI source); @@ -78,35 +77,35 @@ public interface TaskEventListener * Invoked when the status of a sub-job has changed. * * @param source - * task this event originates form + * task this event originates form * @param job - * sub-job that has been updated + * sub-job that has been updated * @param status - * new job status + * new job status */ - void subJobStatusChanged(TaskI source, WebServiceJob job, JobStatus status); + void subJobStatusChanged(TaskI source, JobI job, JobStatus status); /** * Invoked when a log string of the sub-job has changed. * * @param source - * task this event originates form + * task this event originates form * @param job - * sub-job that has been updated + * sub-job that has been updated * @param log - * new log string + * new log string */ - void subJobLogChanged(TaskI source, WebServiceJob job, String log); + void subJobLogChanged(TaskI source, JobI job, String log); /** * Invoked when an error log string of the sub-job has changed. * * @param source - * task this event originates form + * task this event originates form * @param job - * sub-job that has been updated + * sub-job that has been updated * @param log - * new log string + * new log string */ - void subJobErrorLogChanged(TaskI source, WebServiceJob job, String log); + void subJobErrorLogChanged(TaskI source, JobI job, String log); } diff --git a/src/jalview/ws2/actions/api/TaskI.java b/src/jalview/ws2/actions/api/TaskI.java index cd83604..874f5a6 100644 --- a/src/jalview/ws2/actions/api/TaskI.java +++ b/src/jalview/ws2/actions/api/TaskI.java @@ -4,7 +4,7 @@ import java.util.List; import jalview.viewmodel.AlignmentViewport; import jalview.ws2.api.JobStatus; -import jalview.ws2.api.WebServiceJob; +import jalview.ws2.api.WebServiceJobHandle; /** * {@code TaskI} objects represent running services. Tasks are created by @@ -19,25 +19,31 @@ import jalview.ws2.api.WebServiceJob; public interface TaskI { /** - * Get the current status of the task. The resultant status should be - * a combination of individual sub-job statuses. + * Get the current status of the task. The resultant status should be a + * combination of individual sub-job statuses. * - * @return global status of + * @return global status of */ JobStatus getStatus(); /** * Get the current list of sub-jobs of that task. - * + * * @return sub-jobs */ - List getSubJobs(); + List getSubJobs(); /** - * Get the last result of the task or {@code null} if not present. - * Note that the result is subject to change for restartable tasks. + * Get the last result of the task or {@code null} if not present. Note that + * the result is subject to change for restartable tasks. * * @return last task result */ T getResult(); + + /** + * Cancel the task, stop all sub-jobs running on a server and stop all threads + * managing this task. + */ + void cancel(); } diff --git a/src/jalview/ws2/api/WebServiceJob.java b/src/jalview/ws2/api/WebServiceJob.java deleted file mode 100644 index 79fda55..0000000 --- a/src/jalview/ws2/api/WebServiceJob.java +++ /dev/null @@ -1,189 +0,0 @@ -package jalview.ws2.api; - -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.Date; - -import jalview.util.MathUtils; - -/** - * {@code WebServiceJob} represents a job running on a remote server. The object - * contains all the information needed to associate the job with an originating - * client and url, service being run and to poll the job and retrieve the - * results from the server. The {@code WebServiceJob} object is provided by the - * {@link WebServiceClientI#submit} method when the job is created. - * - * @see WebServiceClientI - * - * @author mmwarowny - */ -public class WebServiceJob -{ - /** Unique id used internally by Jalview */ - private final long internalId = MathUtils.getUID(); - - /** Name of the related client */ - private final String serviceClient; - - /** Name of the related service */ - private final String serviceName; - - /** URL the job is valid for */ - private final String url; - - /** External job id as given by the server */ - private final String jobId; - - /** Current status of the job */ - private JobStatus status = JobStatus.READY; - - private String log = ""; - - private String errorLog = ""; - - private Date creationTime = new Date(); - - public WebServiceJob(String serviceClient, String serviceName, - String url, String jobId) - { - this.serviceClient = serviceClient; - this.serviceName = serviceName; - this.url = url; - this.jobId = jobId; - } - - /** - * Get a unique job id used internally by Jalview. - * - * @return unique job id - */ - public long getInternalId() - { - return internalId; - } - - /** - * Get a URL this job originates from. - * - * @return job URL - */ - public String getUrl() - { - return url; - } - - /** - * Get an id assigned to the job by the server. - * - * @return job id handle - */ - public String getJobId() - { - return jobId; - } - - /** - * @return job status - */ - public JobStatus getStatus() - { - return status; - } - - /** - * Update status of the job and notify the listeners. This method should only - * be used by {@link WebServiceClientI} implementations when polling the job. - * - * @param status - * new job status - */ - public void setStatus(JobStatus status) - { - JobStatus oldStatus = this.status; - this.status = status; - pcs.firePropertyChange("status", oldStatus, status); - } - - /** - * @return standard progress log - */ - public String getLog() - { - return log; - } - - /** - * Update log string with data received from the server and notify the - * listeners. This method should only be used by {@link WebServiceClientI} - * implementations when polling the job. - * - * @param log - * new log string - */ - public void setLog(String log) - { - String oldLog = this.log; - this.log = log; - pcs.firePropertyChange("log", oldLog, log); - } - - /** - * @return error log - */ - public String getErrorLog() - { - return errorLog; - } - - /** - * Update error log string with data received from the server and notify the - * listeners. This method should only be used by {@link WebServiceClientI} - * implementations when polling the job - * - * @param errorLog - * new error log string - */ - public void setErrorLog(String errorLog) - { - String oldLog = this.errorLog; - this.errorLog = errorLog; - pcs.firePropertyChange("errorLog", oldLog, errorLog); - } - - /** - * @return Job creation time - */ - public Date getCreationTime() - { - return creationTime; - } - - public String toString() - { - return String.format("%s:%s [%s] Created %s", serviceClient, serviceName, - jobId, creationTime); - } - - /* Methods related to bean listeners */ - private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); - - public void addPropertyChangeListener(PropertyChangeListener listener) - { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) - { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) - { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) - { - pcs.removePropertyChangeListener(propertyName, listener); - } -} diff --git a/src/jalview/ws2/api/WebServiceJobHandle.java b/src/jalview/ws2/api/WebServiceJobHandle.java new file mode 100644 index 0000000..58e2d63 --- /dev/null +++ b/src/jalview/ws2/api/WebServiceJobHandle.java @@ -0,0 +1,74 @@ +package jalview.ws2.api; + +import java.util.Date; + +/** + * {@code WebServiceJob} represents a job running on a remote server. The object + * contains all the information needed to associate the job with an originating + * client and url, service being run and to poll the job and retrieve the + * results from the server. The {@code WebServiceJob} object is provided by the + * {@link WebServiceClientI#submit} method when the job is created. + * + * @see WebServiceClientI + * + * @author mmwarowny + */ +public class WebServiceJobHandle +{ + /** Name of the related client */ + private final String serviceClient; + + /** Name of the related service */ + private final String serviceName; + + /** URL the job is valid for */ + private final String url; + + /** External job id as given by the server */ + private final String jobId; + + private Date creationTime = new Date(); + + public WebServiceJobHandle(String serviceClient, String serviceName, + String url, String jobId) + { + this.serviceClient = serviceClient; + this.serviceName = serviceName; + this.url = url; + this.jobId = jobId; + } + + /** + * Get a URL this job originates from. + * + * @return job URL + */ + public String getUrl() + { + return url; + } + + /** + * Get an id assigned to the job by the server. + * + * @return job id handle + */ + public String getJobId() + { + return jobId; + } + + /** + * @return Job creation time + */ + public Date getCreationTime() + { + return creationTime; + } + + public String toString() + { + return String.format("%s:%s [%s] Created %s", serviceClient, serviceName, + jobId, creationTime); + } +} diff --git a/src/jalview/ws2/client/api/WebServiceClientI.java b/src/jalview/ws2/client/api/WebServiceClientI.java index e62909e..49d097e 100644 --- a/src/jalview/ws2/client/api/WebServiceClientI.java +++ b/src/jalview/ws2/client/api/WebServiceClientI.java @@ -6,15 +6,16 @@ import java.util.List; import jalview.datamodel.SequenceI; import jalview.ws.params.ArgumentI; import jalview.ws2.api.Credentials; -import jalview.ws2.api.WebServiceJob; +import jalview.ws2.api.JobStatus; +import jalview.ws2.api.WebServiceJobHandle; /** - * A common interface for all web service clients that provide methods to - * get the URL of the server the client is talking to, submit new jobs to the - * server as well as poll or cancel the running jobs. This interface does not - * provide means to retrieve job results as those may differ between - * web services. Specialized sub-interfaces define methods to retrieve job - * results appropriate for specific service types. + * A common interface for all web service clients that provide methods to get + * the URL of the server the client is talking to, submit new jobs to the server + * as well as poll or cancel the running jobs. This interface does not provide + * means to retrieve job results as those may differ between web services. + * Specialized sub-interfaces define methods to retrieve job results appropriate + * for specific service types. * * @author mmwarowny * @@ -52,20 +53,41 @@ public interface WebServiceClientI * @throws IOException * submission failed due to a connection error */ - WebServiceJob submit(List sequences, List args, + WebServiceJobHandle submit(List sequences, List args, Credentials credentials) throws IOException; /** - * Poll the server and update the progress of the running job accordingly. - * Implementations should fetch the current job status from the server and - * update the status and log strings on the provided job object. + * Poll the server to get the current status of the job. * * @param job - * job to update + * web service job + * @return job status * @throws IOException - * server error occurred + * server communication error + */ + JobStatus getStatus(WebServiceJobHandle job) throws IOException; + + /** + * Retrieve log messages from the server for the job. + * + * @param job + * web service job + * @return log content + * @throws IOException + * server communication error + */ + String getLog(WebServiceJobHandle job) throws IOException; + + /** + * Retrieve error log messages from the server for the job. + * + * @param job + * web service job + * @return error log content + * @throws IOException + * server communication error */ - void updateProgress(WebServiceJob job) throws IOException; + String getErrorLog(WebServiceJobHandle job) throws IOException; /** * Send the cancellation request to the server for the specified job. @@ -77,5 +99,5 @@ public interface WebServiceClientI * @throws UnsupportedOperationException * server does not support job cancellation */ - void cancel(WebServiceJob job) throws IOException, UnsupportedOperationException; + void cancel(WebServiceJobHandle job) throws IOException, UnsupportedOperationException; } -- 1.7.10.2