Duplicated command submission did not return status - ALREADY_EXISTS

I was trying deduplication service but I couldn’t see and status return from the commandCompletionResponse.

I submitted the same command twice (i.e. same party and same command id) and received OK from the first submission. I was expecting ALREADY_EXISTS from the second submission but there was no status returned. Below is the code I used

Flowable response = client.getCommandCompletionClient().completionStream(CoinMain.APP_ID, p);

    Disposable t = response.subscribeWith(new DisposableSubscriber<CompletionStreamResponse>(){
        @Override
        public void onNext(CompletionStreamResponse completionStreamResponse) {
            completionStreamResponse.getCompletions()
                    .forEach(completion -> {
                        if (completion.getStatus().equals(Status.OK)){
                            commandSubmissionQueue.remove(completion.getCommandId());
                        }
                        logger.info(
                                "Completion for cid:{}/party:{}/Status:{}/{}",
                                completion.getCommandId(),
                                party,
                                completion.getStatus().getCode(),
                                completion.getStatus().getMessage()
                        );
                    });
        }

        @Override
        public void onError(Throwable throwable) {
            logger.error("onError observed in completionService for party " + party, throwable.getMessage());
        }

        @Override
        public void onComplete() {
            logger.info("Completion stream completed for party " + party);
        }
    });
1 Like

Does the command submission succeed? Even on the asynchronous command submission service there are two ways in which a command can fail:

  1. Either the command fails immediately and the submit call returns an error code.
  2. Or the submit call succeeds but you get a failed completion.
1 Like

This is the command submission part. I didn’t get any exception from it in the second submission. Did I missed anything?

    String commandId = UUID.randomUUID().toString();
    String workflowId = UUID.randomUUID().toString();

    client.getCommandSubmissionClient().submit(
            workflowId,
            CoinMain.APP_ID,
            commandId,
            party,
            Collections.singletonList(c));
    logger.info("Commmand Submission - Ref: {} Command Submission ID: {}", ref, commandId);
1 Like

If I’m reading your code correctly, you’re listening to the completion service responses. You should receive an ALREADY_EXISTS back from the submission service, not the completion service. Deduplication happens before execution and you can only get completions for executed commands.

3 Likes

I’m not sure how to do that from submission service. Can you help? Do I need to use blockingGet() and catch exception? Is there any other way of doing it without catching exceptions.

    public void submit(Command c, String ref, String commandId) {
        String workflowId = UUID.randomUUID().toString();

        client.getCommandSubmissionClient().submit(
                workflowId,
                CoinMain.APP_ID,
                commandId,
                party,
                Collections.singletonList(c));
        logger.info("Commmand Submission - Ref: {} Command Submission ID: {}", ref, commandId);
    }
1 Like

I found a way of doing it. Is it correct? Also how do I get status code from the throwable?

    DisposableSingleObserver<Empty> res = client.getCommandSubmissionClient().submit(
            workflowId,
            CoinMain.APP_ID,
            commandId,
            party,
            Collections.singletonList(c)).subscribeWith(new DisposableSingleObserver<Empty>() {
        @Override
        public void onSuccess(Empty empty) {
            logger.info(
                    "Submission success for command id {}",
                    commandId
            );
        }

        @Override
        public void onError(Throwable throwable) {
            logger.error("Summission failed {}", throwable.getMessage());
        }
    });
1 Like

That looks correct to me. You should be able to get the status code using Status.fromThrowable, see https://grpc.github.io/grpc-java/javadoc/io/grpc/Status.html#fromThrowable-java.lang.Throwable-.

3 Likes