Long-running operations (LROs)

  • Long-running operations (LROs) track the status of jobs that execute over an extended period.

  • The OperationFuture class is used to interact with LROs.

  • When using OperationFuture, ensure the service client is not destroyed.

  • It is recommended to use OperationFuture only while the service client is in scope.

Several calls to the Google Ads API return long-running operations (LROs). These track the status of a job that executes over an extended period of time without requiring a single blocking RPC.

OperationFuture class

You interact with LROs in the Java client library using the OperationFuture class. Because OperationFuture relies on the underlying service client to poll the API for status updates, make sure that the service client remains open and active until the operation completes.

Not recommended:

private void executeOperation(String jobName) throws Exception {
  OperationFuture<Empty, OfflineUserDataJobMetadata> future =
      startLongRunningOperation(jobName);
  // FAILS: The service client was already closed when
  // startLongRunningOperation() exited its try-with-resources block, so
  // future.get() fails when polling.
  future.get();
}

private OperationFuture<Empty, OfflineUserDataJobMetadata>
    startLongRunningOperation(String jobToStart) {
  try (OfflineUserDataJobServiceClient offlineUserDataJobServiceClient =
      googleAdsClient
          .getLatestVersion()
          .createOfflineUserDataJobServiceClient()) {
    // Issues an asynchronous request to run the offline user data job.
    return offlineUserDataJobServiceClient.runOfflineUserDataJobAsync(
        jobToStart);
  }
}

Recommended:

private void executeOperation(String jobName) throws Exception {
  try (OfflineUserDataJobServiceClient offlineUserDataJobServiceClient =
      googleAdsClient
          .getLatestVersion()
          .createOfflineUserDataJobServiceClient()) {
    OperationFuture<Empty, OfflineUserDataJobMetadata> future =
        startLongRunningOperation(offlineUserDataJobServiceClient, jobName);
    // Waits for the operation to complete (with a timeout) while the client is
    // still open.
    future.get(5, TimeUnit.MINUTES);
  }
}

private OperationFuture<Empty, OfflineUserDataJobMetadata>
    startLongRunningOperation(
        OfflineUserDataJobServiceClient offlineUserDataJobServiceClient,
        String jobToStart) {
  return offlineUserDataJobServiceClient.runOfflineUserDataJobAsync(jobToStart);
}

Notice how the OperationFuture is only used while the OfflineUserDataJobServiceClient remains open within the try-with-resources block.