microsoft / durabletask-java

Java SDK for Durable Functions and the Durable Task Framework
MIT License
13 stars 7 forks source link

DurableTaskGrpcClient.getInstanceMetadata does not return null when no instance found. #77

Closed YusukeTobo closed 1 year ago

YusukeTobo commented 2 years ago

Regarding the API, getInstanceMetadata should return null when there are no instances found. https://github.com/microsoft/durabletask-java/blob/bfbd7a8a69e7467bc3d30f7831b76941530a4044/client/src/main/java/com/microsoft/durabletask/DurableTaskClient.java#L128

     * @return a metadata record that describes the orchestration instance and its execution status, or
     *         <code>null</code> if no such instance is found.
     */
    @Nullable
    public abstract OrchestrationMetadata getInstanceMetadata(String instanceId, boolean getInputsAndOutputs);

However, In that case, I found that DurableTaskGrpcClient.getInstanceMetadata returns DEFAULTINSTANCE with orchestrationState=0 (ORCHESTRATION_STATUS_RUNNING).

// Protobuf code.

    /**
     * <code>.OrchestrationState orchestrationState = 2;</code>
     * @return The orchestrationState.
     */
    @java.lang.Override
    public com.microsoft.durabletask.implementation.protobuf.OrchestratorService.OrchestrationState getOrchestrationState() {
      return orchestrationState_ == null ? com.microsoft.durabletask.implementation.protobuf.OrchestratorService.OrchestrationState.getDefaultInstance() : orchestrationState_;
    }

    // @@protoc_insertion_point(class_scope:OrchestrationState)
    private static final com.microsoft.durabletask.implementation.protobuf.OrchestratorService.OrchestrationState DEFAULT_INSTANCE;
    static {
      DEFAULT_INSTANCE = new com.microsoft.durabletask.implementation.protobuf.OrchestratorService.OrchestrationState();
    }
    public static com.microsoft.durabletask.implementation.protobuf.OrchestratorService.OrchestrationState getDefaultInstance() {
      return DEFAULT_INSTANCE;
    }

This issue prevents us from invoking client.scheduleNewOrchestrationInstance in Singleton pattern described the official document here. That also means the library users cannot tell the accurate state of instance.

https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-singletons?tabs=java#singleton-example

@FunctionName("HttpStartSingle")
public HttpResponseMessage runSingle(
        @HttpTrigger(name = "req") HttpRequestMessage<?> req,
        @DurableClientInput(name = "durableContext") DurableClientContext durableContext) {

    String instanceID = "StaticID";
    DurableTaskClient client = durableContext.getClient();

    // Check to see if an instance with this ID is already running
    OrchestrationMetadata metadata = client.getInstanceMetadata(instanceID, false);
    if (metadata.isRunning()) {
        return req.createResponseBuilder(HttpStatus.CONFLICT)
                .body("An instance with ID '" + instanceID + "' already exists.")
                .build();
    }

    // No such instance exists - create a new one. De-dupe is handled automatically
    // in the storage layer if another function tries to also use this instance ID.
    client.scheduleNewOrchestrationInstance("MyOrchestration", null, instanceID);
    return durableContext.createCheckStatusResponse(req, instanceID);
}