ledger-api-client: Generate a submission id if it's empty in the CommandClient [KVL-1104] (#10926)

* Throw an exception if the submission id is empty in `CommandTracker`

CHANGELOG_BEGIN
CHANGELOG_END

* Generate a submission ID in the `CommandClient` if it's empty

CHANGELOG_BEGIN
CHANGELOG_END
This commit is contained in:
Hubert Slojewski 2021-09-20 10:00:57 +02:00 committed by GitHub
parent 04d8f753b2
commit fc2c87d950
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 2 deletions

View File

@ -236,6 +236,11 @@ private[commands] class CommandTracker[Context](
val submissionId = commands.submissionId
val commandId = commands.commandId
logger.trace(s"Begin tracking of command $commandId for submission $submissionId.")
if (commands.submissionId.isEmpty) {
throw new IllegalArgumentException(
s"The submission id for the command $commandId is empty. This should not happen."
)
}
if (pendingCommands.contains(TrackedCommandKey(submissionId, commandId))) {
// TODO return an error identical to the server side duplicate command error once that's defined.
throw new IllegalStateException(

View File

@ -8,6 +8,7 @@ import akka.stream.Materializer
import akka.stream.scaladsl.{Flow, Keep, Sink, Source}
import com.codahale.metrics.Counter
import com.daml.grpc.adapter.ExecutionSequencerFactory
import com.daml.ledger.api.SubmissionIdGenerator
import com.daml.ledger.api.domain.LedgerId
import com.daml.ledger.api.v1.command_completion_service.CommandCompletionServiceGrpc.CommandCompletionServiceStub
import com.daml.ledger.api.v1.command_completion_service.{
@ -64,6 +65,8 @@ private[daml] final class CommandClient(
],
]
private val submissionIdGenerator: SubmissionIdGenerator = SubmissionIdGenerator.Random
/** Submit a single command. Successful result does not guarantee that the resulting transaction has been written to
* the ledger. In order to get that semantic, use [[trackCommands]] or [[trackCommandsUnbounded]].
*/
@ -198,10 +201,15 @@ private[daml] final class CommandClient(
throw new IllegalArgumentException(
s"Failing fast on submission request of command ${commands.commandId} with invalid ledger ID ${commands.ledgerId} (client expected $ledgerIdToUse)"
)
else if (commands.applicationId != applicationId)
if (commands.applicationId != applicationId)
throw new IllegalArgumentException(
s"Failing fast on submission request of command ${commands.commandId} with invalid application ID ${commands.applicationId} (client expected $applicationId)"
)
val nonEmptySubmissionId = if (commands.submissionId.isEmpty) {
submissionIdGenerator.generate()
} else {
commands.submissionId
}
val updatedDeduplicationPeriod = commands.deduplicationPeriod match {
case DeduplicationPeriod.Empty =>
DeduplicationPeriod.DeduplicationTime(
@ -213,7 +221,12 @@ private[daml] final class CommandClient(
)
case existing => existing
}
submission.copy(commands = commands.copy(deduplicationPeriod = updatedDeduplicationPeriod))
submission.copy(commands =
commands.copy(
submissionId = nonEmptySubmissionId,
deduplicationPeriod = updatedDeduplicationPeriod,
)
)
})
def submissionFlow[Context](

View File

@ -152,6 +152,20 @@ class CommandTrackerFlowTest
}
}
"a command is submitted without a submission id" should {
"throw an exception" in {
val Handle(submissions, results, _, _) =
runCommandTrackingFlow(allSubmissionsSuccessful)
submissions.sendNext(newSubmission("", commandId))
val actualException = results.expectError()
actualException shouldBe an[IllegalArgumentException]
actualException.getMessage shouldBe s"The submission id for the command $commandId is empty. This should not happen."
}
}
"the stream fails" should {
"expose internal state as materialized value" in {
@ -328,6 +342,7 @@ class CommandTrackerFlowTest
CommandSubmission(
Commands(
commandId = commandId,
submissionId = submissionId,
deduplicationPeriod =
Commands.DeduplicationPeriod.DeduplicationTime(deduplicationTime),
)