Task

Asynchronous jobs are handled via an intermediate Task resource. A resource, submitting an asynchronous job should return the URI of the task.        

REST operations

Description Method URI Parameters Result Status codes
Get a list of all available tasks GET /task [?query=task status as in opentox.owl] List of URIs  text/uri-list
RDF representation  application/rdf+xml
200,503,401
Get the representation of a running task GET /task/{id}   Task representation in application/rdf+xml 200,201,202,404,503,401
Delete (cancel) a task DELETE /task/{id}     200, 404, 503,401

Creating a task (POST call to another OpenTox web service)

An asynchronous task is returned from services that initiate a propably long running job (e.g. large dataset upload, model creation, model prediction). The return value of these POST calls is specified in the API as 'returns TASK or <result> URI' (<result> could be for example a model, created by an algorithm). The client can distinguish the result value type via http status code.

The result of a POST call to an OpenTox web service:

HTTP status code
(returned by service)
Accept header
(specified by the client)
HTTP result body
(returned by service)
202 text/uri-list Task URI
  application/rdf+xml Task object in RDF/XML format
200 text/uri-list <result> URI
  application/rdf+xml Task object in RDF/XML format

Background info on status code 202:

http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html10.2.3 202 Accepted
 The 202 response is intentionally non-committal. Its purpose is to allow a server to accept a request for some other 
 process (perhaps a batch-oriented process that is only run once per day) without requiring that the user agent's connection
 to the server persist until the process is completed. The entity returned with this response SHOULD include an indication of
 the request's current status and either a pointer to a status monitor or some estimate of when the user can expect the
 request to be fulfilled.

Accessing a task (GET)

After a task was created, the state of the job that is running in the background can be requested via GET call. The result URI of the job can be found in the resultURI field of the task as soon as the task has finished. The status code indicates whether the task is still running (202), another task resumes the job (201) or the task is completed (200).

The result of a GET /task/{id}:

Task state HTTP status code
(returned by Task service)
Accept header
(specified by the client)
HTTP result body
(returned by Task service)
Task is not completed 202 text/uri-list Task URI
    application/rdf+xml Task object in RDF/XML format
Another task resumes the job 201 text/uri-list URI of the other task that resumes the job (value of resultURI)
    application/rdf+xml Task object in RDF/XML format
Task is completed 200 text/uri-list <result> URI (value of resultURI)
    application/rdf+xml Task object in RDF/XML format

RDF representation

The asynchronous task is represented by OpenTox Task object, as defined in OpenTox ontology http://www.opentox.org/api/1.1/opentox.owl#Task

A task object has the following properties:

  • dc:date - specifies when the task has been created; of type xsd:dateTime ;
  • dc:creator - specifying the URI of the resource, where the task has been created,  of type xsd:anyURI ;
  • dc:title - human readable title of the task, of type xsd:string;
  • dc:description (optional , eventually might be used for error reporting ?)
  • ot:hasStatus  - one of "Cancelled", "Completed", "Running", "Error", "Queued"
  • ot:percentageCompleted - of type xsd:float
  • ot:resultURI - specifies the URI(s) of the newly created resource, of type xsd:anyURI ; present only if status is "Completed"

 

Incompleted task (N3 notation)

@prefix ot:      <http://www.opentox.org/api/1.1#> .
@prefix dc:      <http://purl.org/dc/elements/1.1/> .
@prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:     <http://www.w3.org/2002/07/owl#> .
@prefix xsd:     <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .


[]    a       ot:Task ;
      dc:date "1269258300474"^^xsd:dateTime ;
      dc:creator "http://host/model/149389"^^xsd:anyURI ;
      dc:title "Apply Classification: Decision tree J48 to http://host/dataset/1"^^xsd:string ;
      ot:hasStatus "Running"^^xsd:string ;
      ot:percentageCompleted
              "50.0"^^xsd:float .

Completed task  (N3 notation)

@prefix ot:      <http://www.opentox.org/api/1.1#> .
@prefix dc:      <http://purl.org/dc/elements/1.1/> .
@prefix rdfs:    <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl:     <http://www.w3.org/2002/07/owl#> .
@prefix xsd:     <http://www.w3.org/2001/XMLSchema#> .
@prefix rdf:     <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .

[]    a       ot:Task ;
      dc:date "1269258300474"^^xsd:dateTime ;
      dc:creator "http://host/model/149389"^^xsd:anyURI ;
      dc:title "Apply Classification: Decision tree J48 to http://host/dataset/1"^^xsd:string ;
      ot:hasStatus "Completed"^^xsd:string ;
      ot:resultURI "http://host/dataset/666"^^xsd:anyURI ;
      ot:percentageCompleted
              "100.0"^^xsd:float .

HTTP status codes

Interpretation Nr Name
Success 200 OK The task is completed, the representation contains URI of the result
Pointer to other Task 201 Task has finished, another Task resumes the Job (URI is specified in result)
Processing 202 Accepted, processing has not completed
task_id is wrong 400 Bad Request
Not Authorized 401 Not Authorized
Task for specific id not found 404 Not Found
Error 500 Internal server error
Service not available 503 Service unavailable

Progression Of Task States [ot:hasStatus]

A task object undergoes the following sequence of status changes :
 
Submit task -> Queued -> Rejected (server overload) -> Stop
Submit task -> Queued -> Running -> Cancelled (by user) -> Stop
Submit task -> Queued -> Running -> Error (error in task execution) -> Stop
Submit task -> Queued -> Running -> Completed -> Stop
 

Error Reporting: a human+machine-friendly aspect

When a task fails, there must be a way to communicate to the client the reason of this failure and which side of the communication (server or client) is to blame. OpenTox, being a distributed computing system, has to provide a clear insight on what happens in the background and the same holds for cases of exceptional events. An exceptional event might occur during the execution of an asynchronous task (when the task will have the status 'Error') or outside the context of a task (e.g. a user asks for a non-existing resource). In what follows we provide details regarding the RDF representation of Error Reports and explain how error reports are related to tasks.

Motivation

Proper formal error reporting is essential for helping services understand the reason something went wrong and take proper actions. The main issues encountered so far are summarized as follows:

•HTTP status codes have been proved ambiguous and do not provide enough information to the client. A status code 400 (Client Error, Bad request) tells the client that there was something wrong with the
request and it should not be repeated but provides no information about the error itself.

•The status code 502 tells the client that is received an error while acting as a client (or proxy) but does not reproduce the error it received, nor tells which is the remote server that threw the error. So a 502 might mask a 400, 404, 500, or any other kind of error.

•Explanatory messages may be included in the body of the response providing information about the exception. On the one hand this human-readable report facilitates the debugging and provides valuable information
to the developers but is not much help towards automating subsequent actions (its not easily machine-readable).

Requirements

Taking these into account we conclude that there is a need for an error reporting API meeting the following requirements:

•Error reporting should be machine readable and include all details needed to understand what exactly went wrong.

•Human readable messages should be available as well.

•Services that receive an error report should replicate it, that is provide a new error report including the information they received from the remote service. The
status code in that case should be 502, but the error report will provide the details needed.

•Error reports should be available in both plain text and RDF/XML format. The latter (rdf) is intended to be used as a machine readable object thus should be properly documented/specified in the API.

First steps

The first question to be addressed is what information should  an error report contain and how could these be provided in a structured way to meet the requirements stated above. So, an error report should contain at least the following information:

  1. The error code: An element of a standard enumeration. The error code can be identified by a simple keyword or an integer (eg. NoSuchFeatureInDataset  or 121 ).
  2. URI of the service: The URI of the service throwing the exception
  3. Message: An brief explanatory message for the error code (e.g. "the prediction feature you provided is not included in the training dataset" )
  4. Details: Details about the error message. If the error was caused by the some bad request or bad input data a hint can be provided to the client. For example if the client provided the tuning parameter gamma=-1 while
    gamma should be positive, a hint can be something like "The value you provided for the parameter gamma is negative while it accepts only positive values".
  5. Cause: Another error report. If the service was acting as a client and received an error report it should include the error report it received.

An RDF representation of the error report can be easily obtained by a proper extension of the API.

Error Reports in RDF

 Here are some examples of how an error report may look like:

  • A client invokes a model training service providing a dataset uri and a prediction feature not included in that set:
    x a ot:ErrorReport;
      ot:errorCode err:PredictionFeatureNotInDataset;
      ot:actor <http://opentox.ntua.gr:3000/algorithm/svm>;
      ot:message "The prediction feature you provided is not contained in the dataset"^^xsd:string;
      ot:errorDetails "The prediction feature you provided (http://someserver.com/feature/100) is not contained 
                       in the dataset. Available features are:
                       ** List of features goes here **"^^xsd:string .
    
  • A model training service receives an acceptable request but receives an error from the feature service while trying to create the prediction feature
    x a ot:ErrorReport;
      ot:errorCode err:CannotGeneratePredictrionFeature;
      ot:actor <http://opentox.ntua.gr:3000/algorithm/svm>;
      ot:message "An error was received from the feature service and the prediction feature could not be created";
      ot:errorDetails "The remote server at http://some.opentox_server.net/feature"^^xsd:string;
      ot:errorCause y .
    y a ot:ErrorReport;
      ot:errorCode err:ServiceUnavailable;
      ot:actor <http://some.opentox_server.net/feature>;
      ot:message "The service is temporarily unavailable. Please try again after 10 minutes"^^xsd:string .
    
  • Consider the case where there exist multiple feature services. Let A be a model training service and B and C two feature services. The service A posts a feature to the service B and receives an error. Then attempts to post the feature to service C. If the request succeeds, then the error received from service B is omitted. But if both requests fail then the error report returned to the client should include the error reports produced by both remote services B and C. Here is an example of such a representation:
    x a ot:ErrorReport;
      ot:errorCode err:CannotGeneratePredictrionFeature;
      ot:actor <http://opentox.ntua.gr:3000/algorithm/svm>;
      ot:message "An error was received from the feature service and the prediction feature could not be created";
      ot:errorDetails "The remote server at http://some.opentox_server_A.net/feature"^^xsd:string;
      ot:errorCause [y z] .
    y a ot:ErrorReport;
      ot:errorCode err:ServiceUnavailable;
      ot:actor <http://some.opentox_server_A.net/feature>;
      ot:message "The service is temporarily unavailable. Please try again after 10 minutes"^^xsd:string .
    z a ot:ErrorReport;
      ot:errorCode err:NotAFeatureRepresentation;
      ot:actor <http://some.opentox_server_B.net/feature>;
      ot:message "The RDF representation you posted is not recognized as the representation of a feature"^^xsd:string 
      ot:details "The posted RDF is syntactically correct but no feature resource was found in it."^^xsd:string.
    

An hierarchical structure can be also adopted for the error codes. For example:

err:NotAFeatureRepresentation rdf:subclassOf err:ImproperRDFRepresentation
err:ImproperRDFRepresentation rdf:subclassOf err:BadRDFContent
err:BadRDFContent rdf:subclassOf err:SomeOtherException

Current Challenges

 As a first step towards the implementation of Error Reporting API is to make a list of all possible errors a service might encounter and establish an enumeration of error codes. These should be followed by a corresponding HTTP status code and a brief explanation. For example:

 

Error Code Description HTTP Status Code
PredictionFeatureNotInDataset The prediction feature provided by the client is not included in the training dataset 400

 

References/Links

  1. Restful Error Handling (A must-read article)
  2. Exception Handling in Web Services [Article from developer.com]
  3. Handling and Throwing Exceptions in XML Web Services
  4. Exception Handling and Recovery of Semantic Web Service
  5. Implementation of Error Report in ToxOtis: Check out the classes ErrorReport and ErrorCause
  6. Example of using ToxOtis error reports in a web application based on Restlet: Check out Jaqpot and in particular the source code for the class JaqpotResource.