private int executeCountQuery(String tableId, String countQuery) throws SynapseException {
   String jobToken =
       synapseAdmin.queryTableEntityBundleAsyncStart(countQuery, 0L, 1L, true, 1, tableId);
   QueryResultBundle qrb = null;
   long backoff = 100L;
   for (int i = 0; i < 100; i++) {
     try {
       qrb = synapseAdmin.queryTableEntityBundleAsyncGet(jobToken, tableId);
       break;
     } catch (SynapseResultNotReadyException e) {
       // keep waiting
       try {
         Thread.sleep(backoff);
       } catch (InterruptedException ie) {
         // continue
       }
       backoff *= 2L;
     }
   }
   if (qrb == null) throw new RuntimeException("Query failed to return");
   List<Row> rows = qrb.getQueryResult().getQueryResults().getRows();
   if (rows.size() != 1)
     throw new RuntimeException(
         "Expected one row for count query result but found " + rows.size());
   Row row = rows.get(0);
   List<String> rowValues = row.getValues();
   if (rowValues.size() != 1)
     throw new RuntimeException(
         "Expected one column for count query result but found " + rows.size());
   return Integer.parseInt(rowValues.get(0));
 }
  /**
   * Note: There are two types of scoring, that in which each submission is scored alone and that in
   * which the entire set of submissions is rescored whenever a new one arrives.
   *
   * @throws SynapseException
   * @throws JSONObjectAdapterException
   */
  public void execute() throws SynapseException, IOException, JSONObjectAdapterException {
    long startTime = System.currentTimeMillis();
    long total = Integer.MAX_VALUE;
    int started = 0;
    for (int offset = 0; offset < total; offset += PAGE_SIZE) {
      PaginatedResults<SubmissionBundle> submissionPGs = null;
      submissionPGs =
          synapseAdmin.getAllSubmissionBundlesByStatus(
              evaluation.getId(), SubmissionStatusEnum.RECEIVED, offset, PAGE_SIZE);
      total = (int) submissionPGs.getTotalNumberOfResults();
      List<SubmissionBundle> page = submissionPGs.getResults();
      for (int i = 0; i < page.size(); i++) {
        SubmissionBundle bundle = page.get(i);
        Submission sub = bundle.getSubmission();
        FileHandle fileHandle = getFileHandleFromEntityBundle(sub.getEntityBundleJSON());
        SubmissionStatus status = bundle.getSubmissionStatus();
        // Retrieve and run COUNT_QUERY.  If > 0 then execute Docker image
        String tableId = readStringAnnotation(status, TABLE_ID_ANNOTATION_NAME);
        String countQuery = readStringAnnotation(status, COUNT_QUERY_ANNOTATION_NAME);
        if (tableId != null && countQuery != null) {
          int count = executeCountQuery(tableId, countQuery);
          if (count == 0) {
            System.out.println("Count query returned 0: " + countQuery);
            continue; // nothing to process, so skip this submission
          }
        }
        // if no tableId or no countQuery then run the image
        // it's then the image's job to put this information in the annotations
        try {
          String dockerReference = getDockerReferenceFromFileHandle(fileHandle);
          if (readStringAnnotation(status, DOCKER_REPOSITORY_ANNOTATION_NAME) == null)
            addAnnotation(status, DOCKER_REPOSITORY_ANNOTATION_NAME, dockerReference, false);
          status.setStatus(SubmissionStatusEnum.EVALUATION_IN_PROGRESS);
          status = synapseAdmin.updateSubmissionStatus(status);
          // we run the image if either (1) there are new rows to process of (2) it hasn't been run
          // before
          runOneImage(fileHandle, sub.getId());
          // make sure that the Docker reference is in an annotation so it can be displayed
          started++;
        } catch (Exception e) {
          status = synapseAdmin.getSubmissionStatus(sub.getId());
          if (status.getStatus() != SubmissionStatusEnum.RECEIVED) {
            status.setStatus(SubmissionStatusEnum.RECEIVED);
            status = synapseAdmin.updateSubmissionStatus(status);
          }
          // TODO send failure notification to submitter
          e.printStackTrace();
        }
      }
    }

    long delta = System.currentTimeMillis() - startTime;
    System.out.println("Started " + started + " jobs.  Elapsed time: " + formatInterval(delta));
  }
 public void setUp() throws SynapseException, UnsupportedEncodingException {
   evaluation = synapseAdmin.getEvaluation(getProperty("EVALUATION_ID"));
 }
 public TableTrigger() throws SynapseException {
   synapseAdmin = createSynapseClient();
   String adminUserName = getProperty("ADMIN_USERNAME");
   String adminPassword = getProperty("ADMIN_PASSWORD");
   synapseAdmin.login(adminUserName, adminPassword);
 }
 private void sendMessage(String userId, String subject, String body) throws SynapseException {
   MessageToUser messageMetadata = new MessageToUser();
   messageMetadata.setRecipients(Collections.singleton(userId));
   messageMetadata.setSubject(subject);
   synapseAdmin.sendStringMessage(messageMetadata, body);
 }