All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alibaba.dashscope.api.AsynchronousApi Maven / Gradle / Ivy

The newest version!
// Copyright (c) Alibaba, Inc. and its affiliates.

package com.alibaba.dashscope.api;

import static com.alibaba.dashscope.utils.ApiKeywords.TASK_STATUS;

import com.alibaba.dashscope.base.HalfDuplexParamBase;
import com.alibaba.dashscope.common.DashScopeResult;
import com.alibaba.dashscope.common.TaskStatus;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.protocol.*;
import com.alibaba.dashscope.task.AsyncTaskListParam;
import com.alibaba.dashscope.task.AsyncTaskParam;
import com.google.gson.JsonObject;
import java.net.HttpURLConnection;
import java.util.HashMap;
import java.util.Map;

/** Support DashScope async task CRUD. */
public final class AsynchronousApi {
  final HalfDuplexClient client;
  ConnectionOptions connectionOptions;

  /** Create default http client. */
  public AsynchronousApi() {
    this.client = ClientProviders.getHalfDuplexClient("https");
    this.connectionOptions = null;
  }

  /**
   * Create custom http client
   *
   * @param connectionOptions The client option.
   */
  public AsynchronousApi(ConnectionOptions connectionOptions) {
    this.client = ClientProviders.getHalfDuplexClient(connectionOptions, "https");
    this.connectionOptions = connectionOptions;
  }

  /**
   * Call the server to get the whole result.
   *
   * @param param The input param, should be the subclass of `Param`.
   * @param serviceOption The service option.
   * @throws NoApiKeyException Can not find api key
   * @throws ApiException The request failed, possibly due to a network or data error.
   * @return The output structure, should be the subclass of `Result`.
   */
  public DashScopeResult call(ParamT param, ServiceOption serviceOption)
      throws ApiException, NoApiKeyException {
    DashScopeResult task = this.asyncCall(param, serviceOption);
    return this.wait(getTaskId(task), param.getApiKey(), serviceOption.getBaseHttpUrl());
  }

  /**
   * Call async interface and return async task info.
   *
   * @param param The input param, should be the subclass of `Param`
   * @param serviceOption The service option.
   * @return The output task information, should be the subclass of `Result`
   * @throws NoApiKeyException Can not find api key
   * @throws ApiException The request failed, possibly due to a network or data error.
   */
  public DashScopeResult asyncCall(ParamT param, ServiceOption serviceOption)
      throws ApiException, NoApiKeyException {
    HalfDuplexRequest req = new HalfDuplexRequest(param, serviceOption);
    return client.send(req);
  }

  /**
   * Wait for async task completed and return task result.
   *
   * @param taskId The async task id.
   * @param apiKey The api-key.
   * @param baseUrl The base http url.
   * @param customHeaders The custom headers.
   * @return The task result.
   * @throws NoApiKeyException Can not find api key
   * @throws ApiException The request failed, possibly due to a network or data error.
   */
  public DashScopeResult wait(
      String taskId, String apiKey, String baseUrl, Map customHeaders)
      throws ApiException, NoApiKeyException {
    AsyncTaskOption serviceOption =
        AsyncTaskOption.builder()
            .protocol(Protocol.HTTP)
            .httpMethod(HttpMethod.GET)
            .url(String.format("/tasks/%s", taskId))
            .baseHttpUrl(baseUrl)
            .build();

    AsyncTaskParam getParam =
        AsyncTaskParam.builder().taskId(taskId).apiKey(apiKey).headers(customHeaders).build();
    HalfDuplexRequest req = new HalfDuplexRequest(getParam, serviceOption);
    int waitMilliseconds = 1000;
    int maxWaitMilliseconds = 5 * 1000;
    int incrementSteps = 3;
    int step = 0;
    while (true) {
      try {
        DashScopeResult taskResult = client.send(req);
        JsonObject output = (JsonObject) taskResult.getOutput();
        String taskStatus =
            output.get(TASK_STATUS) == null ? null : output.get(TASK_STATUS).getAsString();
        if (TaskStatus.FAILED.getValue().equals(taskStatus)
            || TaskStatus.CANCELED.getValue().equals(taskStatus)
            || TaskStatus.UNKNOWN.getValue().equals(taskStatus)) {
          return taskResult;
        } else if (TaskStatus.SUCCEEDED.getValue().equals(taskStatus)) {
          return taskResult;
        } else {
          // we start by querying once every second, and double the query interval after
          // every 3(increment_steps) intervals, until we hit the max waiting interval of 5(seconds)
          // TODO: investigate if we can use long-poll (server side return immediately when ready)
          step += 1;
          if (waitMilliseconds < maxWaitMilliseconds && step % incrementSteps == 0) {
            waitMilliseconds =
                waitMilliseconds * 2 > maxWaitMilliseconds
                    ? maxWaitMilliseconds
                    : waitMilliseconds * 2;
          }
          try {
            Thread.sleep(waitMilliseconds);
          } catch (InterruptedException ignored) {
          }
        }
      } catch (ApiException e) {
        if (e.getStatus().getStatusCode() != HttpURLConnection.HTTP_UNAVAILABLE
            && e.getStatus().getStatusCode() != HttpURLConnection.HTTP_GATEWAY_TIMEOUT) {
          throw e;
        }
      }
    }
  }

  /**
   * Wait for async task completed and return task result.
   *
   * @param taskId The async task id.
   * @param apiKey The api-key.
   * @return The task result.
   * @throws NoApiKeyException Can not find api key
   * @throws ApiException The request failed, possibly due to a network or data error.
   */
  public DashScopeResult wait(String taskId, String apiKey, String baseUrl)
      throws ApiException, NoApiKeyException {
    return wait(taskId, apiKey, baseUrl, new HashMap<>());
  }

  public DashScopeResult wait(DashScopeResult taskInfo, String apiKey, String baseUrl)
      throws ApiException, NoApiKeyException {
    return wait(getTaskId(taskInfo), apiKey, baseUrl);
  }

  /**
   * Get the async task information, if the is completed will return the result, otherwise return
   * task status.
   *
   * @param taskId The async task id.
   * @param apiKey The api key.
   * @param baseUrl The base http url.
   * @param customHeaders The custom headers.
   * @return The task result or status information.
   * @throws NoApiKeyException Can not find api key
   * @throws ApiException The request failed, possibly due to a network or data error.
   */
  public DashScopeResult fetch(
      String taskId, String apiKey, String baseUrl, Map customHeaders)
      throws ApiException, NoApiKeyException {
    AsyncTaskOption serviceOption =
        AsyncTaskOption.builder()
            .protocol(Protocol.HTTP)
            .httpMethod(HttpMethod.GET)
            .baseHttpUrl(baseUrl)
            .url(String.format("/tasks/%s", taskId))
            .build();

    AsyncTaskParam getParam =
        AsyncTaskParam.builder().taskId(taskId).apiKey(apiKey).headers(customHeaders).build();
    HalfDuplexRequest req = new HalfDuplexRequest(getParam, serviceOption);
    DashScopeResult taskResult = client.send(req);
    return taskResult;
  }

  /**
   * Get the async task information, if the is completed will return the result, otherwise return
   * task status.
   *
   * @param taskId The async task id.
   * @param apiKey The api key.
   * @return The task result or status information.
   * @throws NoApiKeyException Can not find api key
   * @throws ApiException The request failed, possibly due to a network or data error.
   */
  public DashScopeResult fetch(String taskId, String apiKey, String baseUrl)
      throws ApiException, NoApiKeyException {
    return fetch(taskId, apiKey, baseUrl, new HashMap<>());
  }

  public DashScopeResult fetch(DashScopeResult taskInfo, String apiKey, String baseUrl)
      throws ApiException, NoApiKeyException {
    return fetch(getTaskId(taskInfo), apiKey, baseUrl);
  }

  public DashScopeResult cancel(String taskId, String apiKey, String baseUrl)
      throws ApiException, NoApiKeyException {
    AsyncTaskParam param = AsyncTaskParam.builder().taskId(taskId).apiKey(apiKey).build();
    AsyncTaskOption taskOption =
        AsyncTaskOption.builder()
            .baseHttpUrl(baseUrl)
            .url(String.format("/tasks/%s/cancel", taskId))
            .build();
    DashScopeResult result = client.send(new HalfDuplexRequest(param, taskOption));
    return result;
  }

  public DashScopeResult cancel(DashScopeResult taskInfo, String apiKey, String baseUrl)
      throws ApiException, NoApiKeyException {
    return cancel(getTaskId(taskInfo), apiKey, baseUrl);
  }

  public DashScopeResult list(AsyncTaskListParam param, String baseUrl)
      throws ApiException, NoApiKeyException {
    AsyncTaskOption taskOption =
        AsyncTaskOption.builder()
            .baseHttpUrl(baseUrl)
            .url("/tasks")
            .httpMethod(HttpMethod.GET)
            .build();
    DashScopeResult result = client.send(new HalfDuplexRequest(param, taskOption));
    return result;
  }

  public DashScopeResult list(
      String startTime,
      String endTime,
      String modelName,
      String apiKeyId,
      String region,
      String status,
      Integer pageNo,
      Integer pageSize,
      String baseUrl)
      throws ApiException, NoApiKeyException {
    AsyncTaskListParam.AsyncTaskListParamBuilder builder = AsyncTaskListParam.builder();
    if (startTime != null) {
      builder.parameter("start_time", startTime);
    }
    if (endTime != null) {
      builder.parameter("end_time", endTime);
    }
    if (modelName != null) {
      builder.parameter("model_name", modelName);
    }
    if (apiKeyId != null) {
      builder.parameter("api_key_id", apiKeyId);
    }
    if (region != null) {
      builder.parameter("region", region);
    }
    if (status != null) {
      builder.parameter("status", status);
    }
    if (pageNo != null) {
      builder.parameter("page_no", pageNo);
    }
    if (pageSize != null) {
      builder.parameter("page_size", pageSize);
    }
    AsyncTaskListParam param = builder.build();
    return list(param, baseUrl);
  }

  public String getTaskId(DashScopeResult task) {
    JsonObject output = (JsonObject) (task.getOutput());
    return output.get("task_id").getAsString();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy