private synchronized void scheduleUpdate() {
    // don't update if the task hasn't been started yet or if it is already finished
    if (!needsUpdate.get() || taskInfo.get().getState().isDone()) {
      return;
    }

    // if we have an old request outstanding, cancel it
    if (currentRequest != null
        && Duration.nanosSince(currentRequestStartNanos).compareTo(new Duration(2, SECONDS)) >= 0) {
      needsUpdate.set(true);
      currentRequest.cancel(true);
      currentRequest = null;
      currentRequestStartNanos = 0;
    }

    // if there is a request already running, wait for it to complete
    if (this.currentRequest != null && !this.currentRequest.isDone()) {
      return;
    }

    // if throttled due to error, asynchronously wait for timeout and try again
    ListenableFuture<?> errorRateLimit = updateErrorTracker.acquireRequestPermit();
    if (!errorRateLimit.isDone()) {
      errorRateLimit.addListener(this::scheduleUpdate, executor);
      return;
    }

    List<TaskSource> sources = getSources();
    TaskUpdateRequest updateRequest =
        new TaskUpdateRequest(
            session.toSessionRepresentation(), planFragment, sources, outputBuffers.get());

    Request request =
        preparePost()
            .setUri(uriBuilderFrom(taskInfo.get().getSelf()).addParameter("summarize").build())
            .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.JSON_UTF_8.toString())
            .setBodyGenerator(jsonBodyGenerator(taskUpdateRequestCodec, updateRequest))
            .build();

    updateErrorTracker.startRequest();

    ListenableFuture<JsonResponse<TaskInfo>> future =
        httpClient.executeAsync(request, createFullJsonResponseHandler(taskInfoCodec));
    currentRequest = future;
    currentRequestStartNanos = System.nanoTime();

    // The needsUpdate flag needs to be set to false BEFORE adding the Future callback since
    // callback might change the flag value
    // and does so without grabbing the instance lock.
    needsUpdate.set(false);

    Futures.addCallback(
        future,
        new SimpleHttpResponseHandler<>(new UpdateResponseHandler(sources), request.getUri()),
        executor);
  }
Esempio n. 2
0
  private synchronized void sendDelete() {
    HttpResponseFuture<StatusResponse> resultFuture =
        httpClient.executeAsync(
            prepareDelete().setUri(location).build(), createStatusResponseHandler());
    future = resultFuture;
    Futures.addCallback(
        resultFuture,
        new FutureCallback<StatusResponse>() {
          @Override
          public void onSuccess(@Nullable StatusResponse result) {
            checkNotHoldsLock();
            synchronized (HttpPageBufferClient.this) {
              closed = true;
              if (future == resultFuture) {
                future = null;
                errorDelayMillis = 0;
              }
              lastUpdate = DateTime.now();
            }
            requestsCompleted.incrementAndGet();
            clientCallback.clientFinished(HttpPageBufferClient.this);
          }

          @Override
          public void onFailure(Throwable t) {
            checkNotHoldsLock();

            log.error("Request to delete %s failed %s", location, t);
            Duration errorDuration = elapsedErrorDuration();
            if (!(t instanceof PrestoException) && errorDuration.compareTo(minErrorDuration) > 0) {
              String message =
                  format(
                      "Error closing remote buffer (%s - requests failed for %s)",
                      location, errorDuration);
              t = new PrestoException(REMOTE_BUFFER_CLOSE_FAILED, message, t);
            }
            handleFailure(t, resultFuture);
          }
        },
        executor);
  }
  private void scheduleAsyncCleanupRequest(Backoff cleanupBackoff, Request request, String action) {
    Futures.addCallback(
        httpClient.executeAsync(request, createStatusResponseHandler()),
        new FutureCallback<StatusResponse>() {
          @Override
          public void onSuccess(StatusResponse result) {
            // assume any response is good enough
          }

          @Override
          public void onFailure(Throwable t) {
            if (t instanceof RejectedExecutionException) {
              // client has been shutdown
              return;
            }

            // record failure
            if (cleanupBackoff.failure()) {
              logError(t, "Unable to %s task at %s", action, request.getUri());
              return;
            }

            // reschedule
            long delayNanos = cleanupBackoff.getBackoffDelayNanos();
            if (delayNanos == 0) {
              scheduleAsyncCleanupRequest(cleanupBackoff, request, action);
            } else {
              errorScheduledExecutor.schedule(
                  () -> scheduleAsyncCleanupRequest(cleanupBackoff, request, action),
                  delayNanos,
                  NANOSECONDS);
            }
          }
        },
        executor);
  }
Esempio n. 4
0
  private synchronized void sendGetResults() {
    URI uri = HttpUriBuilder.uriBuilderFrom(location).appendPath(String.valueOf(token)).build();
    HttpResponseFuture<PagesResponse> resultFuture =
        httpClient.executeAsync(
            prepareGet().setHeader(PRESTO_MAX_SIZE, maxResponseSize.toString()).setUri(uri).build(),
            new PageResponseHandler(blockEncodingSerde));

    future = resultFuture;
    Futures.addCallback(
        resultFuture,
        new FutureCallback<PagesResponse>() {
          @Override
          public void onSuccess(PagesResponse result) {
            checkNotHoldsLock();

            resetErrors();

            List<Page> pages;
            try {
              synchronized (HttpPageBufferClient.this) {
                if (taskInstanceId == null) {
                  taskInstanceId = result.getTaskInstanceId();
                }

                if (!isNullOrEmpty(taskInstanceId)
                    && !result.getTaskInstanceId().equals(taskInstanceId)) {
                  // TODO: update error message
                  throw new PrestoException(REMOTE_TASK_MISMATCH, REMOTE_TASK_MISMATCH_ERROR);
                }

                if (result.getToken() == token) {
                  pages = result.getPages();
                  token = result.getNextToken();
                } else {
                  pages = ImmutableList.of();
                }
              }
            } catch (PrestoException e) {
              handleFailure(e, resultFuture);
              return;
            }

            // add pages
            if (clientCallback.addPages(HttpPageBufferClient.this, pages)) {
              pagesReceived.addAndGet(pages.size());
              rowsReceived.addAndGet(pages.stream().mapToLong(Page::getPositionCount).sum());
            } else {
              pagesRejected.addAndGet(pages.size());
              rowsRejected.addAndGet(pages.stream().mapToLong(Page::getPositionCount).sum());
            }

            synchronized (HttpPageBufferClient.this) {
              // client is complete, acknowledge it by sending it a delete in the next request
              if (result.isClientComplete()) {
                completed = true;
              }
              if (future == resultFuture) {
                future = null;
                errorDelayMillis = 0;
              }
              lastUpdate = DateTime.now();
            }
            requestsCompleted.incrementAndGet();
            clientCallback.requestComplete(HttpPageBufferClient.this);
          }

          @Override
          public void onFailure(Throwable t) {
            log.debug("Request to %s failed %s", uri, t);
            checkNotHoldsLock();

            Duration errorDuration = elapsedErrorDuration();

            t = rewriteException(t);
            if (!(t instanceof PrestoException) && errorDuration.compareTo(minErrorDuration) > 0) {
              String message =
                  format("%s (%s - requests failed for %s)", WORKER_NODE_ERROR, uri, errorDuration);
              t = new PageTransportTimeoutException(message, t);
            }
            handleFailure(t, resultFuture);
          }
        },
        executor);
  }