Java源码示例:com.google.appengine.api.taskqueue.TransientFailureException

示例1
/** Leases and returns all tasks from the queue with the specified tag tld, in batches. */
List<TaskHandle> loadAllTasks(Queue queue, String tld) {
  ImmutableList.Builder<TaskHandle> allTasks = new ImmutableList.Builder<>();
  while (true) {
    List<TaskHandle> tasks =
        retrier.callWithRetry(
            () ->
                queue.leaseTasks(
                    LeaseOptions.Builder.withTag(tld)
                        .leasePeriod(LEASE_PERIOD.getMillis(), TimeUnit.MILLISECONDS)
                        .countLimit(TaskQueueUtils.getBatchSize())),
            TransientFailureException.class,
            DeadlineExceededException.class);
    if (tasks.isEmpty()) {
      return allTasks.build();
    }
    allTasks.addAll(tasks);
  }
}
 
示例2
/** Deletes a list of tasks from the given queue using a retrier. */
private static void deleteTasksWithRetry(
    final List<DnsRefreshRequest> refreshRequests,
    final Queue queue,
    AsyncTaskMetrics asyncTaskMetrics,
    Retrier retrier,
    OperationResult result) {
  if (refreshRequests.isEmpty()) {
    return;
  }
  final List<TaskHandle> tasks =
      refreshRequests.stream().map(DnsRefreshRequest::task).collect(toImmutableList());
  retrier.callWithRetry(() -> queue.deleteTask(tasks), TransientFailureException.class);
  refreshRequests.forEach(
      r -> asyncTaskMetrics.recordAsyncFlowResult(DNS_REFRESH, result, r.requestedTime()));
}
 
示例3
@Test
public void testTransact_transientFailureException_retries() {
  assertThat(
          tm().transact(
                  new Supplier<Integer>() {

                    int count = 0;

                    @Override
                    public Integer get() {
                      count++;
                      if (count == 3) {
                        return count;
                      }
                      throw new TransientFailureException("");
                    }
                  }))
      .isEqualTo(3);
}
 
示例4
void doReadOnlyRetryTest(final RuntimeException e) {
  assertThat(
          tm().transactNewReadOnly(
                  new Supplier<Integer>() {

                    int count = 0;

                    @Override
                    public Integer get() {
                      count++;
                      if (count == 3) {
                        return count;
                      }
                      throw new TransientFailureException("");
                    }
                  }))
      .isEqualTo(3);
}
 
示例5
/**
 * Adds tasks to an App Engine task queue in a reliable manner.
 *
 * <p>This is the same as {@link Queue#add(Iterable)} except it'll automatically retry with
 * exponential backoff if {@link TransientFailureException} is thrown.
 *
 * @throws TransientFailureException if retrying failed for the maximum period of time, or an
 *     {@link InterruptedException} told us to stop trying
 * @return successfully enqueued tasks
 */
public List<TaskHandle> enqueue(final Queue queue, final Iterable<TaskOptions> tasks) {
  return retrier.callWithRetry(
      () -> {
        for (TaskOptions task : tasks) {
          logger.atInfo().log(
              "Enqueuing queue='%s' endpoint='%s'", queue.getQueueName(), task.getUrl());
        }
        return queue.add(tasks);
      },
      TransientFailureException.class);
}
 
示例6
/** Deletes the specified tasks from the queue in batches, with retrying. */
public void deleteTasks(Queue queue, List<TaskHandle> tasks) {
  Lists.partition(tasks, BATCH_SIZE)
      .stream()
      .forEach(
          batch ->
              retrier.callWithRetry(
                  () -> queue.deleteTask(batch), TransientFailureException.class));
}
 
示例7
/**
 * Transact with commit logs and retry with exponential backoff.
 *
 * <p>This method is broken out from {@link #transactNew(Work)} for testing purposes.
 */
@VisibleForTesting
<R> R transactCommitLoggedWork(CommitLoggedWork<R> work) {
  long baseRetryMillis = getBaseOfyRetryDuration().getMillis();
  for (long attempt = 0, sleepMillis = baseRetryMillis;
      true;
      attempt++, sleepMillis *= 2) {
    try {
      ofy().transactNew(() -> {
        work.run();
        return null;
      });
      return work.getResult();
    } catch (TransientFailureException
        | TimestampInversionException
        | DatastoreTimeoutException
        | DatastoreFailureException e) {
      // TransientFailureExceptions come from task queues and always mean nothing committed.
      // TimestampInversionExceptions are thrown by our code and are always retryable as well.
      // However, Datastore exceptions might get thrown even if the transaction succeeded.
      if ((e instanceof DatastoreTimeoutException || e instanceof DatastoreFailureException)
          && checkIfAlreadySucceeded(work)) {
        return work.getResult();
      }
      if (attempt == NUM_RETRIES) {
        throw e;  // Give up.
      }
      sleeper.sleepUninterruptibly(Duration.millis(sleepMillis));
      logger.atInfo().withCause(e).log(
          "Retrying %s, attempt %d", e.getClass().getSimpleName(), attempt);
    }
  }
}
 
示例8
@Override
public final void map(@Nullable final DomainBase domain) {
  if (domain == null) {
    // Emit a single value so that the reducer always runs.  The key and value don't matter.
    emit(true, true);
    return;
  }
  Key<HostResource> referencingHostKey = null;
  for (DnsRefreshRequest request : refreshRequests) {
    if (isActive(domain, request.lastUpdateTime())
        && domain.getNameservers().contains(VKey.from(request.hostKey()))) {
      referencingHostKey = request.hostKey();
      break;
    }
  }
  if (referencingHostKey != null) {
    retrier.callWithRetry(
        () -> dnsQueue.addDomainRefreshTask(domain.getDomainName()),
        TransientFailureException.class);
    logger.atInfo().log(
        "Enqueued DNS refresh for domain %s referenced by host %s.",
        domain.getDomainName(), referencingHostKey);
    getContext().incrementCounter("domains refreshed");
  } else {
    getContext().incrementCounter("domains not refreshed");
  }

  // Don't catch errors -- we allow the mapreduce to terminate on any errors that can't be
  // resolved by retrying the transaction. The reducer only fires if the mapper completes
  // without errors, meaning that it is acceptable to delete all tasks.
}
 
示例9
/**
 * Deletes a list of tasks associated with deletion requests from the async delete queue using a
 * retrier.
 */
private void deleteStaleTasksWithRetry(final List<DeletionRequest> deletionRequests) {
  if (deletionRequests.isEmpty()) {
    return;
  }
  final List<TaskHandle> tasks =
      deletionRequests.stream().map(DeletionRequest::task).collect(toImmutableList());
  retrier.callWithRetry(() -> queue.deleteTask(tasks), TransientFailureException.class);
  deletionRequests.forEach(
      deletionRequest ->
          asyncTaskMetrics.recordAsyncFlowResult(
              deletionRequest.getMetricOperationType(),
              OperationResult.STALE,
              deletionRequest.requestedTime()));
}
 
示例10
/** Returns handles for a batch of tasks, leased for the specified duration. */
public List<TaskHandle> leaseTasks(Duration leaseDuration) {
  try {
    rateLimiter.acquire();
    int numTasks = queue.fetchStatistics().getNumTasks();
    logger.at((numTasks >= leaseTasksBatchSize) ? Level.WARNING : Level.INFO).log(
        "There are %d tasks in the DNS queue '%s'.", numTasks, DNS_PULL_QUEUE_NAME);
    return queue.leaseTasks(leaseDuration.getMillis(), MILLISECONDS, leaseTasksBatchSize);
  } catch (TransientFailureException | DeadlineExceededException e) {
    logger.atSevere().withCause(e).log("Failed leasing tasks too fast");
    return ImmutableList.of();
  }
}
 
示例11
/** Delete a list of tasks, removing them from the queue permanently. */
public void deleteTasks(List<TaskHandle> tasks) {
  try {
    queue.deleteTask(tasks);
  } catch (TransientFailureException | DeadlineExceededException e) {
    logger.atSevere().withCause(e).log("Failed deleting tasks too fast");
  }
}
 
示例12
@SuppressWarnings("unchecked")
@Test
public void test_loadAllTasks_retryLogic_thirdTrysTheCharm() {
  Queue queue = mock(Queue.class);
  TaskHandle task = new TaskHandle(TaskOptions.Builder.withTaskName("blah"), "blah");
  when(queue.leaseTasks(any(LeaseOptions.class)))
      .thenThrow(TransientFailureException.class)
      .thenThrow(DeadlineExceededException.class)
      .thenReturn(ImmutableList.of(task), ImmutableList.of());
  assertThat(action.loadAllTasks(queue, "tld")).containsExactly(task);
}
 
示例13
@Test
public void test_loadAllTasks_retryLogic_allFailures() {
  Queue queue = mock(Queue.class);
  when(queue.leaseTasks(any(LeaseOptions.class)))
      .thenThrow(new TransientFailureException("some transient error"));
  RuntimeException thrown =
      assertThrows(TransientFailureException.class, () -> action.loadAllTasks(queue, "tld"));
  assertThat(thrown).hasMessageThat().isEqualTo("some transient error");
}
 
示例14
@Test
public void testEnqueue_twoTransientErrorsThenSuccess_stillWorksAfterSleeping() {
  when(queue.add(ImmutableList.of(task)))
      .thenThrow(new TransientFailureException(""))
      .thenThrow(new TransientFailureException(""))
      .thenReturn(ImmutableList.of(handle));
  assertThat(taskQueueUtils.enqueue(queue, task)).isSameInstanceAs(handle);
  verify(queue, times(3)).add(ImmutableList.of(task));
  assertThat(clock.nowUtc()).isEqualTo(DateTime.parse("2000-01-01T00:00:00.6Z"));  // 200 + 400ms
}
 
示例15
@Test
public void testEnqueue_maxRetries_givesUp() {
  when(queue.add(ImmutableList.of(task)))
      .thenThrow(new TransientFailureException("one"))
      .thenThrow(new TransientFailureException("two"))
      .thenThrow(new TransientFailureException("three"))
      .thenThrow(new TransientFailureException("four"));
  TransientFailureException thrown =
      assertThrows(TransientFailureException.class, () -> taskQueueUtils.enqueue(queue, task));
  assertThat(thrown).hasMessageThat().contains("three");
}
 
示例16
@Test
public void testEnqueue_transientErrorThenInterrupt_throwsTransientError() {
  when(queue.add(ImmutableList.of(task))).thenThrow(new TransientFailureException(""));
  try {
    Thread.currentThread().interrupt();
    assertThrows(TransientFailureException.class, () -> taskQueueUtils.enqueue(queue, task));
  } finally {
    Thread.interrupted();  // Clear interrupt state so it doesn't pwn other tests.
  }
}
 
示例17
RuntimeException constructApiException(String packageName, String methodName) {
  String message = "RCP Failure for API call: " + packageName + " " + methodName;

  switch (packageName) {
    case "taskqueue":
      return new TransientFailureException(message);
    case "app_identity_service":
      return new AppIdentityServiceFailureException(message);
    case "blobstore":
      return new BlobstoreFailureException(message);
    case "channel":
      return new ChannelFailureException(message);
    case "images":
      return new ImagesServiceFailureException(message);
    case "logservice":
      return constructException(
          LogServiceException.class.getName(), message, packageName, methodName);
    case "memcache":
      return new MemcacheServiceException(message);
    case "modules":
      return constructException(
          ModulesException.class.getName(), message, packageName, methodName);
    case "search":
      return new SearchException(message);
    case "user":
      return new UserServiceFailureException(message);
    case "xmpp":
      return new XMPPFailureException(message);
    default:

      // Cover all datastore versions:
      if (packageName.startsWith("datastore")) {
        return new DatastoreFailureException(message);
      } else {
        return new RPCFailedException(packageName, methodName);
      }
  }
}
 
示例18
@Test
public void testTransactNewReadOnly_transientFailureException_retries() {
  doReadOnlyRetryTest(new TransientFailureException(""));
}
 
示例19
/**
 * @return List<TaskHandle> the accumulated list of tasks up to count.
 */
private List<TaskHandle> leaseTasksByOptions(String groupTag, int count,
                                             boolean zeroSizeAcceptable, LeaseOptions options,
                                             int retry, int interval) {
    List<TaskHandle> handleList = null;
    List<TaskHandle> masterHandleList = new ArrayList<>();

    int retryCount = retry;
    int retryCounter = 0;
    int retryInterval = interval;
    while (masterHandleList.size() < count) {
        sync(retryInterval);  // first iteration gives time for tasks to activate.
        try {
            handleList = queue.leaseTasks(options);
        } catch (TransientFailureException tfe) {  // This is common.
            sync(retryInterval);
            log.warning(tfe.toString());
            handleList = null;
            continue;
        }

        if (handleList.size() > 0) {
            masterHandleList.addAll(handleList);
        }

        if (handleList.size() >= 0 && zeroSizeAcceptable) {
            return masterHandleList;  // even zero tasks okay, return what we got.
        }

        if (masterHandleList.size() >= count) {
            return masterHandleList;  // Success, got all tasks requested.
        }

        if (retryCounter++ > retryCount) {
            break;
        }
    }

    String errMsg = "Couldn't lease " + Integer.toString(count) + " tag:" +
        groupTag + " after " + retryCount + " attempts.";
    log.warning(errMsg);
    if (handleList == null) {  // Couldn't communicate with Task service.
        throw new TransientFailureException(errMsg);
    }

    return masterHandleList;  // Return what we've got, could be partial.
}
 
示例20
/**
 * @return List<TaskHandle> the accumulated list of tasks up to count.
 */
private List<TaskHandle> leaseTasksByOptions(String groupTag, int count,
                                             boolean zeroSizeAcceptable, LeaseOptions options,
                                             int retry, int interval) {
    List<TaskHandle> handleList = null;
    List<TaskHandle> masterHandleList = new ArrayList<TaskHandle>();

    int retryCount = retry;
    int retryCounter = 0;
    int retryInterval = interval;
    while (masterHandleList.size() < count) {
        sleep(retryInterval);  // first iteration gives time for tasks to activate.
        try {
            handleList = queue.leaseTasks(options);
        } catch (TransientFailureException tfe) {  // This is common.
            sleep(retryInterval);
            log.warning(tfe.toString());
            handleList = null;
            continue;
        }

        if (handleList.size() > 0) {
            masterHandleList.addAll(handleList);
        }

        if (handleList.size() >= 0 && zeroSizeAcceptable) {
            return masterHandleList;  // even zero tasks okay, return what we got.
        }

        if (masterHandleList.size() >= count) {
            return masterHandleList;  // Success, got all tasks requested.
        }

        if (retryCounter++ > retryCount) {
            break;
        }
    }

    String errMsg = "Couldn't lease " + Integer.toString(count) + " tag:" + groupTag + " after " + retryCount + " attempts.";
    log.warning(errMsg);
    if (handleList == null) {  // Couldn't communicate with Task service.
        throw new TransientFailureException(errMsg);
    }

    return masterHandleList;  // Return what we've got, could be partial.
}
 
示例21
/**
 * Adds a task to a queue with retrying, to avoid aborting the entire flow over a transient issue
 * enqueuing a task.
 */
private void addTaskToQueueWithRetry(final Queue queue, final TaskOptions task) {
  retrier.callWithRetry(() -> queue.add(task), TransientFailureException.class);
}