/** {@inheritDoc} */
  @Override
  protected final void handleMessages(List<T> messages) {
    long start = System.nanoTime();
    // Create a batch of message that we want to write.
    List<RegularStatement> statements = new ArrayList<>();
    for (T t : messages) {
      try {
        handleMessage(statements, t);
      } catch (RuntimeException e) {
        LOG.warn("Failed to write message: " + t, e); // Just in case we cannot process a message
      }
    }

    // Try writing the batch
    try {
      Batch batch = QueryBuilder.batch(statements.toArray(new RegularStatement[statements.size()]));

      long beforeSend = System.nanoTime();

      ResultSetFuture f = connection.getSession().executeAsync(batch);
      f.getUninterruptibly(); // throws QueryValidationExecption etc

      long total = System.nanoTime();
      // Is this an abnormal slow batch?
      boolean isSlow =
          TimeUnit.MILLISECONDS.convert(total - start, TimeUnit.NANOSECONDS) > 200
              || messages.size() >= getBatchSize();
      if (isSlow || lastSlowBatch > 0) {
        LOG.info(
            "Total time: "
                + DurationFormatter.DEFAULT.formatNanos(total - start)
                + ", prepping="
                + DurationFormatter.DEFAULT.formatNanos(beforeSend - start)
                + ", sending="
                + DurationFormatter.DEFAULT.formatNanos(total - beforeSend)
                + ", size="
                + messages.size());
        // makes sure we write 10 info statements after the last slow batch we insert
        lastSlowBatch = isSlow ? 10 : lastSlowBatch - 1;
      }
      persistedCount.mark(messages.size());
      // sink.onSucces(messages);
    } catch (QueryValidationException e) {
      LOG.error("Could not execute query, this is an internal error", e);
    } catch (Exception e) {
      onFailure(messages, e);
      try {
        sleepUntilShutdown(2, TimeUnit.SECONDS);
      } catch (InterruptedException ignore) {
        Thread.interrupted();
      }
    }
  }
  /*
   * (non-Javadoc)
   *
   * @see dal.SchoolDAL#list()
   */
  @Override
  public List<School> list() {

    final ResultSetFuture schoolListFuture =
        listAllInTable(School.class.getSimpleName().toLowerCase());
    final List<Row> schoolRowList = schoolListFuture.getUninterruptibly().all();

    final List<School> schoolList = new ArrayList<>();

    School school;
    for (Row row : schoolRowList) {
      school = createSchoolForRow(row);
      schoolList.add(school);
    }

    return schoolList;
  }
  /*
   * (non-Javadoc)
   *
   * @see dal.SchoolDAL#getById(java.lang.String)
   */
  @Override
  public School getById(String id) {

    final PreparedStatement statement = session.prepare("SELECT * FROM school WHERE school_id = ?");
    final BoundStatement boundedStatement = statement.bind(id);

    final ResultSetFuture schoolFuture = session.executeAsync(boundedStatement);
    final Row schoolRow = schoolFuture.getUninterruptibly().one();

    School school;
    if (schoolRow != null) {
      school = createSchoolForRow(schoolRow);
    } else {
      school = null;
    }

    return school;
  }
  @Override
  public void onQueryComplete(ResultSetFuture rsf) {
    log.info("QueryCompleted");
    Row row;
    try {
      row = rsf.get().one();
    } catch (Exception e) {
      throw new RuntimeException("Failed to get ResultSet from ResultSetFuture", e);
    }
    book = new Book();
    book.setIsbn(row.getString("isbn"));
    book.setTitle(row.getString("title"));
    book.setAuthor(row.getString("author"));
    book.setPages(row.getInt("pages"));

    done = true;
    log.info("DONE");
  }
 @Override
 public void cancel() {
   rsf.cancel(true);
 }