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

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

// Copyright (c) Alibaba, Inc. and its affiliates.

package com.alibaba.dashscope.api;

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

import com.alibaba.dashscope.base.AsyncTaskListParam;
import com.alibaba.dashscope.base.AsyncTaskParam;
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.AsyncTaskOption;
import com.alibaba.dashscope.protocol.ClientOptions;
import com.alibaba.dashscope.protocol.ClientProviders;
import com.alibaba.dashscope.protocol.HalfDuplexClient;
import com.alibaba.dashscope.protocol.HalfDuplexRequest;
import com.alibaba.dashscope.protocol.HttpMethod;
import com.alibaba.dashscope.protocol.Protocol;
import com.alibaba.dashscope.protocol.ServiceOption;
import com.google.gson.JsonObject;
import java.net.HttpURLConnection;

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

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

  /**
   * Create custom http client
   *
   * @param clientOptions The client option.
   */
  public AsynchronousApi(ClientOptions clientOptions) {
    this.client = ClientProviders.getHalfDuplexClient(clientOptions);
    this.clientOptions = clientOptions;
  }

  /**
   * 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());
  }

  /**
   * 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.
   * @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) throws ApiException, NoApiKeyException {
    AsyncTaskOption serviceOption =
        AsyncTaskOption.builder()
            .protocol(Protocol.HTTP)
            .httpMethod(HttpMethod.GET)
            .url(String.format("/tasks/%s", taskId))
            .build();

    AsyncTaskParam getParam = AsyncTaskParam.builder().taskId(taskId).apiKey(apiKey).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;
        }
      }
    }
  }

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

  /**
   * 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)
      throws ApiException, NoApiKeyException {
    AsyncTaskOption serviceOption =
        AsyncTaskOption.builder()
            .protocol(Protocol.HTTP)
            .httpMethod(HttpMethod.GET)
            .url(String.format("/tasks/%s", taskId))
            .build();

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

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

  public DashScopeResult cancel(String taskId, String apiKey)
      throws ApiException, NoApiKeyException {
    AsyncTaskParam param = AsyncTaskParam.builder().taskId(taskId).apiKey(apiKey).build();
    AsyncTaskOption taskOption =
        AsyncTaskOption.builder().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)
      throws ApiException, NoApiKeyException {
    return cancel(getTaskId(taskInfo), apiKey);
  }

  public DashScopeResult list(AsyncTaskListParam param) throws ApiException, NoApiKeyException {
    AsyncTaskOption taskOption =
        AsyncTaskOption.builder().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)
      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);
  }

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




© 2015 - 2025 Weber Informatics LLC | Privacy Policy