예제 #1
0
 /**
  * Submit a list of jobs to Cook scheduler. It will <br>
  * -- firstly associate each job with the provided {@link JobListener}<br>
  * -- secondly submit these jobs to Cook scheduler and track them until they complete.
  *
  * @param jobs The list of jobs expected to submit.
  * @param listener specifies an instance of {@link JobListener} listening all job status updates.
  * @throws JobClientException
  */
 public void submit(List<Job> jobs, JobListener listener) throws JobClientException {
   // It is ok to change the listeners map even if the actual submission fails because it won't
   // update the internal status map {@code _activeUUIDTOJob}.
   for (Job job : jobs) {
     _activeUUIDToListener.put(job.getUUID(), listener);
   }
   submit(jobs);
 }
예제 #2
0
 /**
  * Query jobs for a given list of job {@link UUID}s. If the list size is larger that the {@code
  * _batchRequestSize}, it will partition the list into smaller lists and query them respectively
  * and return all query results together.
  *
  * @param uuids specifies a list of job {@link UUID}s expected to query.
  * @return a {@link ImmutableMap} from job {@link UUID} to {@link Job}.
  * @throws JobClientException
  */
 public ImmutableMap<UUID, Job> query(Collection<UUID> uuids) throws JobClientException {
   final List<NameValuePair> allParams = new ArrayList<NameValuePair>(uuids.size());
   for (UUID uuid : uuids) {
     allParams.add(new BasicNameValuePair("job", uuid.toString()));
   }
   final ImmutableMap.Builder<UUID, Job> UUIDToJob = ImmutableMap.builder();
   // Partition a large query into small queries.
   for (final List<NameValuePair> params : Lists.partition(allParams, _batchRequestSize)) {
     HttpResponse httpResponse;
     HttpRequestBase httpRequest;
     try {
       URIBuilder uriBuilder = new URIBuilder(_uri);
       uriBuilder.addParameters(params);
       httpRequest = new HttpGet(uriBuilder.build());
       httpResponse = _httpClient.execute(httpRequest);
     } catch (IOException | URISyntaxException e) {
       throw releaseAndCreateException(
           null, "Can not submit GET request " + params + " via uri " + _uri, e);
     }
     // Check status code.
     final StatusLine statusLine = httpResponse.getStatusLine();
     // Base on the decision graph
     // http://clojure-liberator.github.io/liberator/tutorial/decision-graph.html
     // The status code for the proper GET response is 200.
     if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
       throw releaseAndCreateException(
           httpRequest,
           "The response of GET request "
               + params
               + " via uri "
               + _uri
               + ": "
               + statusLine.getReasonPhrase()
               + ", "
               + statusLine.getStatusCode(),
           null);
     }
     // Parse the response.
     String response = null;
     try {
       // parse the response to string.
       final HttpEntity entity = httpResponse.getEntity();
       response = EntityUtils.toString(entity);
       // Ensure that the entity content has been fully consumed and the underlying stream has been
       // closed.
       EntityUtils.consume(entity);
       for (Job job : Job.parseFromJSON(response, _instanceDecorator)) {
         UUIDToJob.put(job.getUUID(), job);
       }
     } catch (JSONException | ParseException | IOException e) {
       throw new JobClientException(
           "Can not parse the response = "
               + response
               + " for GET request "
               + params
               + " via uri "
               + _uri,
           e);
     } finally {
       httpRequest.releaseConnection();
     }
   }
   return UUIDToJob.build();
 }
예제 #3
0
  /**
   * Submit a list of jobs to Cook scheduler and start to track these jobs until they complete. Note
   * that jobs submitted through this API will not be listened by any listener.
   *
   * @param jobs specifies a list of {@link Job}s to be submitted.
   * @return the response string from Cook scheduler rest endpoint.
   * @throws JobClientException
   */
  public void submit(List<Job> jobs) throws JobClientException {
    JSONObject json;
    try {
      json = Job.jsonizeJob(jobs);
    } catch (JSONException e) {
      throw new JobClientException("Can not jsonize jobs to submit.", e);
    }
    HttpResponse httpResponse;
    HttpRequestBase httpRequest = makeHttpPost(_uri, json);
    try {
      httpResponse = executeWithRetries(httpRequest, 5, 10);
    } catch (IOException e) {
      throw releaseAndCreateException(
          httpRequest, "Can not submit POST request " + json + " via uri " + _uri, e);
    }

    // Get the response string.
    StatusLine statusLine = httpResponse.getStatusLine();
    HttpEntity entity = httpResponse.getEntity();
    if (entity == null) {
      throw releaseAndCreateException(httpRequest, "The response entity is null!", null);
    }
    String response = null;
    try {
      response = EntityUtils.toString(entity);
      // Ensure that the entity content has been fully consumed and the underlying stream has been
      // closed.
      EntityUtils.consume(entity);
    } catch (ParseException | IOException e) {
      throw releaseAndCreateException(
          httpRequest,
          "Can not parse the response for POST request " + json + " via uri " + _uri,
          e);
    }
    if (_log.isDebugEnabled()) {
      _log.debug("Response String for submitting jobs" + json.toString() + " is " + response);
    }

    // Base on the decision graph
    // http://clojure-liberator.github.io/liberator/tutorial/decision-graph.html
    // If the jobs are submitted successfully, the status code is 201.
    // If a job uses a UUID which has been used before, the returned status code is 400 and the
    // return message is something like:
    // clojure.lang.ExceptionInfo: UUID 26719da8-194f-44f9-9e6d-8a17500f5109 already used {:uuid
    // #uuid "26719da8-194f-44f9-9e6d-8a17500f5109"}

    // A flag to indicate if the submission is successful.
    boolean isSuccess = false;
    if (null != statusLine && statusLine.getStatusCode() == HttpStatus.SC_CREATED) {
      isSuccess = true;
      _log.info("Successfully execute POST request with data " + json + " via uri " + _uri);
    } else if (null != statusLine && statusLine.getStatusCode() >= HttpStatus.SC_BAD_REQUEST) {
      final Pattern patternUUID =
          Pattern.compile(
              "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12} already used");
      final Matcher matchUUID = patternUUID.matcher(response);
      if (matchUUID.find()) {
        _log.info(
            "Successfully execute POST request with several retries " + json + " via uri " + _uri);
        isSuccess = true;
      } else {
        _log.warn(
            "Failed to execute POST request with several retries " + json + " via uri " + _uri);
      }
    }
    if (null != httpRequest) {
      httpRequest.releaseConnection();
    }
    if (isSuccess) {
      // Update status map.
      for (Job job : jobs) {
        _activeUUIDToJob.put(job.getUUID(), job);
      }
    } else {
      _log.error("Failed to submit jobs " + json.toString());
      throw new JobClientException(
          "The response of POST request "
              + json
              + " via uri "
              + _uri
              + ": "
              + statusLine.getReasonPhrase()
              + ", "
              + statusLine.getStatusCode());
    }
  }