My understanding is submit on the CommandSubmissionClient is supposed to be asynchronous, and must be used in conjunction with the CommandCompletionService, while submitAndWait on the CommandService is supposed to be synchronous and should wait for the response to be returned from the ledger.
Why is it then that submitAndWait also returns a Single instead of blocking until the actual result of the Daml transaction is available? Conversely, if both are non-blocking, where would I want to use submit versus submitAndWait?
submit returns after the transaction was submitted to the ledger. Ie a status 0 response means your request was valid and there’s a chance it’ll result in a committed transaction. But to find out whether it actually commits (as opposed to times out of fails due to contention), you have to monitor ledger state or subscribe to completions.
submitAndWait returns only once the transaction was committed or rejected. A status code 0 means your transaction was committed. Different status codes will contains the details of the rejection.
Just some extra detail in case it isn’t clear: when @bernhard mentions “returns”, this is “when the Single is fulfilled”. Both functions “return”, in the Java sense, very quickly; you need to use that return value no matter what. The choice of function determines what has already happened by the time that Single is fulfilled.
@Stephen Thank you for clarifying - so basically both are non-blocking calls, with one fulfilled on tx submission, the other on tx commit.
Since the Java application does not have to spend any time waiting for a response (and can do other things like submit other commands almost immediately) in both cases, would that then mean they are both equivalent from both a latency and throughput perspective?
When you ask the server to track a command’s progress for you (submitAndWait), that puts an additional load on the participant server. It can manage that load by throwing ABORTED “if the number of in-flight commands reached the maximum (if a limit is configured)”, or DEADLINE_EXCEEDED “if the request failed to receive its completion within the predefined timeout”. The point is, that additional load is not free.
The reason that most clients do this is, as you wrote, “[submit] must be used in conjunction with the CommandCompletionService”. The extra complexity can be worth it in very-high-throughput applications where you can explicitly manage your in-flight commands above and beyond what submitAndWait will do for you.
The point is that it is not a question of whether completions need to be managed, but of whether you want the participant server to manage completions, or you want to do it yourself. The vast majority of applications should choose the former, though.