Add documentation annotations to KV self-service errors [KVL-1144] (#11385)

* KV: port V2 errors to self-service errors framework

CHANGELOG_BEGIN
CHANGELOG_END

* Fix ConversionsSpec compiling

* Use a valid ID for ValidationFailure

* Fix error details in Conversions

* Relax and simplify checks in KeyValueConsumptionSpec

* Fix formatting

* Fix definite answer in deduplication v2

* Try and make Scala 2.12 happy

* Fix typos in comments

* Use NOT_FOUND for unknown parties and provide them as resources

* Race (group) -> SubmissionRaces

* Don't deprecate resource exhausted (ABORTED) error

* Add documentation annotations to KV self-service errors

CHANGELOG_BEGIN
CHANGELOG_END

* Update ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/errors/KVCompletionErrors.scala

Co-authored-by: Samir Talwar <samir.talwar@digitalasset.com>

* Address review comments

* Reword `InvalidLedgerTime`'s explanation

* Reword `CausalMonotonicityViolated`'s explanation

* Fix formatting

* Fix merge

* Fix explanation of InvalidLedgerTime

* Fix formatting

* Document groups

* Fix typo in group documentation

Co-authored-by: tudor-da <tudor.voicu@digitalasset.com>

* Fix typo in group documentation

Co-authored-by: tudor-da <tudor.voicu@digitalasset.com>

Co-authored-by: Samir Talwar <samir.talwar@digitalasset.com>
Co-authored-by: tudor-da <tudor.voicu@digitalasset.com>
This commit is contained in:
fabiotudone-da 2021-10-27 16:39:05 +02:00 committed by GitHub
parent 46d31d5d48
commit d86eca0b05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 119 additions and 6 deletions

View File

@ -3,6 +3,7 @@
package com.daml.ledger.participant.state.kvutils
import java.io.StringWriter
import java.time.{Duration, Instant}
import com.daml.error.{ContextualizedErrorLogger, ValueSwitch}
@ -52,6 +53,7 @@ import com.daml.lf.value.Value.{ContractId, VersionedValue}
import com.daml.lf.value.{Value, ValueCoder, ValueOuterClass}
import com.daml.lf.{crypto, data}
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.protobuf.Empty
import com.google.rpc.status.Status
@ -528,6 +530,13 @@ private[state] object Conversions {
rejectionReasonNotSetStatus(entry, errorVersionSwitch)
})
private[kvutils] def objectToJsonString(obj: Object): String = {
val stringWriter = new StringWriter
val objectMapper = new ObjectMapper
objectMapper.writeValue(stringWriter, obj)
stringWriter.toString
}
private def encodeParties(parties: Set[Ref.Party]): List[String] =
(parties.toList: List[String]).sorted

View File

@ -4,13 +4,14 @@
package com.daml.ledger.participant.state.kvutils.errors
import java.time.Instant
import com.daml.error.{
ContextualizedErrorLogger,
ErrorCategory,
ErrorCode,
ErrorGroup,
ErrorResource,
Explanation,
Resolution,
}
import com.daml.error.definitions.ErrorGroups.ParticipantErrorGroup.TransactionErrorGroup.LedgerApiErrorGroup
import com.daml.ledger.participant.state.kvutils.committer.transaction.Rejection.{
@ -18,10 +19,21 @@ import com.daml.ledger.participant.state.kvutils.committer.transaction.Rejection
InternallyInconsistentTransaction,
}
@Explanation(
"Errors that are specific to ledgers based on the KV architecture." +
"Note that this section will soon cover all ledgers due to an ongoing error consolidation effort."
)
object KVErrors extends LedgerApiErrorGroup {
@Explanation("Errors that relate to the Daml concepts of time.")
object Time extends ErrorGroup() {
@Explanation(
"The record time is not within bounds for reasons other than deduplication, such as " +
"excessive latency. Excessive clock skew between the participant and the committer " +
"or a time model that is too restrictive may also produce this rejection."
)
@Resolution("Retry the submission or contact the participant operator.")
object InvalidRecordTime
extends ErrorCode(
id = "INVALID_RECORD_TIME",
@ -37,6 +49,12 @@ object KVErrors extends LedgerApiErrorGroup {
extends KVLoggingTransactionErrorImpl(cause)
}
@Explanation(
"The record time is not within bounds for reasons other than deduplication, such as " +
"excessive latency. Excessive clock skew between the participant and the committer " +
"or a time model that is too restrictive may also produce this rejection."
)
@Resolution("Retry the transaction submission or contact the participant operator.")
object RecordTimeOutOfRange
extends ErrorCode(
id = "RECORD_TIME_OUT_OF_RANGE",
@ -52,6 +70,10 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation(
"At least one input contract's ledger time is later than that of the submitted transaction."
)
@Resolution("Retry the transaction submission.")
object CausalMonotonicityViolated
extends ErrorCode(
id = "CAUSAL_MONOTONICITY_VIOLATED",
@ -66,8 +88,18 @@ object KVErrors extends LedgerApiErrorGroup {
}
@Explanation(
"Errors that can arise due to concurrent processing of transactions in the participant."
)
object SubmissionRaces extends ErrorGroup() {
@Explanation(
"A contract with the same key has already been created by a concurrent transaction submission."
)
@Resolution(
"The correct resolution depends on the business flow, " +
"for example using the existing contract or retrying after it has been archived."
)
object ExternallyDuplicateKeys
extends ErrorCode(
id = "EXTERNALLY_DUPLICATE_KEYS",
@ -80,6 +112,10 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation(
"An input contract key was re-assigned to a different contract by a concurrent transaction submission."
)
@Resolution("Retry the transaction submission.")
object ExternallyInconsistentKeys
extends ErrorCode(
id = "EXTERNALLY_INCONSISTENT_KEYS",
@ -93,6 +129,11 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation("An input contract has been archived by a concurrent transaction submission.")
@Resolution(
"The correct resolution depends on the business flow, for example it may be possible to " +
"proceed without the archived contract as an input, or a different contract could be used."
)
object ExternallyInconsistentContracts
extends ErrorCode(
id = "EXTERNALLY_INCONSISTENT_CONTRACTS",
@ -108,8 +149,14 @@ object KVErrors extends LedgerApiErrorGroup {
}
@Explanation("Errors that relate to parties.")
object Parties extends ErrorGroup {
@Explanation("The submitting party has not been allocated.")
@Resolution(
"Check that the party identifier is correct, allocate the submitting party, " +
"request its allocation or wait for it to be allocated before retrying the transaction submission."
)
object SubmittingPartyNotKnownOnLedger
extends ErrorCode(
id = "SUBMITTING_PARTY_NOT_KNOWN_ON_LEDGER",
@ -127,6 +174,11 @@ object KVErrors extends LedgerApiErrorGroup {
}
}
@Explanation("One or more informee parties have not been allocated.")
@Resolution(
"Check that all the informee party identifiers are correct, allocate all the informee parties, " +
"request their allocation or wait for them to be allocated before retrying the transactiomn submission."
)
object PartiesNotKnownOnLedger
extends ErrorCode(
id = "PARTIES_NOT_KNOWN_ON_LEDGER",
@ -145,8 +197,13 @@ object KVErrors extends LedgerApiErrorGroup {
}
@Explanation("Errors that relate to system resources.")
object Resources extends ErrorGroup() {
@Explanation("A system resource has been exhausted.")
@Resolution(
"Retry the transaction submission or provide the details to the participant operator."
)
object ResourceExhausted
extends ErrorCode(
id = "RESOURCE_EXHAUSTED",
@ -162,8 +219,11 @@ object KVErrors extends LedgerApiErrorGroup {
}
@Explanation("Errors that arise due to insufficient authorization.")
object Unauthorized extends ErrorGroup() {
@Explanation("A submitting party is not authorized to act through the participant.")
@Resolution("Contact the participant operator or re-submit with an authorized party.")
object SubmitterCannotActViaParticipant
extends ErrorCode(
id = "SUBMITTER_CANNOT_ACT_VIA_PARTICIPANT",
@ -181,8 +241,11 @@ object KVErrors extends LedgerApiErrorGroup {
}
@Explanation("Errors that arise from an internal system misbehavior.")
object Internal extends ErrorGroup() {
@Explanation("A rejection reason has not been set.")
@Resolution("Contact support.")
object RejectionReasonNotSet
extends ErrorCode(
id = "REJECTION_REASON_NOT_SET",
@ -195,6 +258,8 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation("An invalid transaction submission was not detected by the participant.")
@Resolution("Contact support.")
object ValidationFailure
extends ErrorCode(
id = "VALIDATION_FAILURE",
@ -208,6 +273,8 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation("The participant didn't provide a necessary transaction submission input.")
@Resolution("Contact support.")
object MissingInputState
extends ErrorCode(
id = "MISSING_INPUT_STATE",
@ -221,6 +288,11 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation(
"The participant didn't detect an attempt by the transaction submission " +
"to use the same key for two active contracts."
)
@Resolution("Contact support.")
object InternallyDuplicateKeys
extends ErrorCode(
id = "INTERNALLY_DUPLICATE_KEYS",
@ -233,6 +305,11 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation(
"The participant didn't detect an attempt by the transaction submission " +
"to use a stale contract key."
)
@Resolution("Contact support.")
object InternallyInconsistentKeys
extends ErrorCode(
id = "INTERNALLY_INCONSISTENT_KEYS",
@ -245,6 +322,8 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation("An invalid participant state has been detected.")
@Resolution("Contact support.")
object InvalidParticipantState
extends ErrorCode(
id = "INVALID_PARTICIPANT_STATE",
@ -264,6 +343,11 @@ object KVErrors extends LedgerApiErrorGroup {
}
@Explanation(
"A command for the same ledger change has already been successfully processed " +
"within the current deduplication window."
)
@Resolution("Celebrate, as your command has already been processed.")
object DuplicateCommand
extends ErrorCode(
id = "DUPLICATE_COMMAND",
@ -277,11 +361,19 @@ object KVErrors extends LedgerApiErrorGroup {
)
}
@Explanation(
"Errors that are not going to be produced anymore but may still be encountered " +
"when subscribing to past offsets."
)
@deprecated
object Deprecated extends ErrorGroup() {
object Time extends ErrorGroup() {
@Explanation(
"The ledger time of the submission violated some constraint on the ledger time."
)
@Resolution("Retry the transaction submission.")
@deprecated(
"It was produced by submissions batching and it's not produced anymore by pre-execution."
)
@ -303,6 +395,11 @@ object KVErrors extends LedgerApiErrorGroup {
object Parties extends ErrorGroup() {
@Explanation("One or more informee parties have not been allocated.")
@Resolution(
"Check that all the informee party identifiers are correct, allocate all the informee parties, " +
"request their allocation or wait for them to be allocated before retrying the transactiomn submission."
)
@deprecated("Corresponds to transaction submission rejections that are not produced anymore.")
object PartyNotKnownOnLedger
extends ErrorCode(
@ -323,6 +420,8 @@ object KVErrors extends LedgerApiErrorGroup {
object Internal extends ErrorGroup() {
@Explanation("An invalid transaction submission was not detected by the participant.")
@Resolution("Contact support.")
@deprecated("Corresponds to transaction submission rejections that are not produced anymore.")
object Disputed
extends ErrorCode(
@ -339,6 +438,12 @@ object KVErrors extends LedgerApiErrorGroup {
}
@Explanation("At least one input has been altered by a concurrent transaction submission.")
@Resolution(
"The correct resolution depends on the business flow, for example it may be possible to proceed " +
"without an archived contract as an input, or the transaction submission may be retried " +
"to load the up-to-date value of a contract key."
)
@deprecated("Corresponds to transaction submission rejections that are not produced anymore.")
object Inconsistent
extends ErrorCode(

View File

@ -6,11 +6,6 @@ package com.daml.ledger.participant.state.kvutils.updates
import java.io.StringWriter
import java.time.Instant
import com.google.protobuf.any.{Any => AnyProto}
import com.google.rpc.code.Code
import com.google.rpc.error_details.ErrorInfo
import com.google.rpc.status.Status
import com.daml.error.{ContextualizedErrorLogger, ValueSwitch}
import com.daml.ledger.grpc.GrpcStatuses
import com.daml.ledger.participant.state.kvutils.Conversions.parseCompletionInfo
@ -26,6 +21,10 @@ import com.daml.lf.data.Time.Timestamp
import com.fasterxml.jackson.databind.ObjectMapper
import com.google.protobuf.ProtocolStringList
import com.google.protobuf.any.{Any => AnyProto}
import com.google.rpc.code.Code
import com.google.rpc.error_details.ErrorInfo
import com.google.rpc.status.Status
import scala.annotation.nowarn
import scala.jdk.CollectionConverters._