diff --git a/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala b/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala index fc098fe3e1..ea7f59f529 100644 --- a/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala +++ b/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala @@ -46,6 +46,20 @@ object LedgerApiErrors extends LedgerApiErrorGroup { cause = message ) } + + @Explanation("This rejection is given when a package upload was rejected.") + @Resolution("Refer to the detailed message of the received error.") + object PackageUploadRejected + extends ErrorCode( + id = "PACKAGE_UPLOAD_REJECTED", + ErrorCategory.InvalidGivenCurrentSystemStateOther, + ) { + case class Reject(message: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = message + ) + } } object ReadErrors extends ErrorGroup() { diff --git a/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala b/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala index b86a255fb3..6860c0207d 100644 --- a/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala +++ b/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala @@ -269,6 +269,15 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch grpcError(statusBuilder.build()) } + def packageUploadRejected(message: String, definiteAnswer: Option[Boolean])(implicit + contextualizedErrorLogger: ContextualizedErrorLogger + ): StatusRuntimeException = { + errorCodesVersionSwitcher.choose( + v1 = invalidArgumentV1(definiteAnswer, message), + v2 = LedgerApiErrors.WriteErrors.PackageUploadRejected.Reject(message).asGrpcError, + ) + } + def configurationEntryRejected(message: String, definiteAnswer: Option[Boolean])(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = { diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServices.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServices.scala index 2d1cd9ffc6..6853af7cf1 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServices.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/ApiServices.scala @@ -284,6 +284,7 @@ private[daml] object ApiServices { writeService, managementServiceTimeout, engine, + errorsVersionsSwitcher, ) val apiConfigManagementService = ApiConfigManagementService.createApiService( diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiPackageManagementService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiPackageManagementService.scala index 8425c50c92..7ea831d39c 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiPackageManagementService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiPackageManagementService.scala @@ -8,7 +8,11 @@ import java.util.zip.ZipInputStream import akka.stream.Materializer import akka.stream.scaladsl.Source import com.daml.daml_lf_dev.DamlLf.Archive -import com.daml.error.{DamlContextualizedErrorLogger, ContextualizedErrorLogger} +import com.daml.error.{ + ContextualizedErrorLogger, + DamlContextualizedErrorLogger, + ErrorCodesVersionSwitcher, +} import com.daml.ledger.api.domain.{LedgerOffset, PackageEntry} import com.daml.ledger.api.v1.admin.package_management_service.PackageManagementServiceGrpc.PackageManagementService import com.daml.ledger.api.v1.admin.package_management_service._ @@ -47,6 +51,7 @@ private[apiserver] final class ApiPackageManagementService private ( engine: Engine, darReader: GenDarReader[Archive], submissionIdGenerator: String => Ref.SubmissionId, + errorCodesVersionSwitcher: ErrorCodesVersionSwitcher, )(implicit materializer: Materializer, executionContext: ExecutionContext, @@ -58,11 +63,14 @@ private[apiserver] final class ApiPackageManagementService private ( private implicit val contextualizedErrorLogger: ContextualizedErrorLogger = new DamlContextualizedErrorLogger(logger, loggingContext, None) + private val errorFactories = ErrorFactories(errorCodesVersionSwitcher) + private val synchronousResponse = new SynchronousResponse( new SynchronousResponseStrategy( transactionsService, packagesIndex, packagesWrite, + errorFactories, ), timeToLive = managementServiceTimeout, ) @@ -120,7 +128,7 @@ private[apiserver] final class ApiPackageManagementService private ( ValidationLogger .logFailureWithContext( request, - ErrorFactories.invalidArgument(None)(err.getMessage), + errorFactories.invalidArgument(None)(err.getMessage), ) ), Future.successful, @@ -146,6 +154,7 @@ private[apiserver] object ApiPackageManagementService { writeBackend: state.WritePackagesService, managementServiceTimeout: Duration, engine: Engine, + errorCodesVersionSwitcher: ErrorCodesVersionSwitcher, darReader: GenDarReader[Archive] = DarParser, submissionIdGenerator: String => Ref.SubmissionId = augmentSubmissionId, )(implicit @@ -161,12 +170,14 @@ private[apiserver] object ApiPackageManagementService { engine, darReader, submissionIdGenerator, + errorCodesVersionSwitcher, ) private final class SynchronousResponseStrategy( ledgerEndService: LedgerEndService, packagesIndex: IndexPackagesService, packagesWrite: state.WritePackagesService, + errorFactories: ErrorFactories, )(implicit executionContext: ExecutionContext, loggingContext: LoggingContext) extends SynchronousResponse.Strategy[ Dar[Archive], @@ -198,7 +209,7 @@ private[apiserver] object ApiPackageManagementService { submissionId: Ref.SubmissionId ): PartialFunction[PackageEntry, StatusRuntimeException] = { case PackageEntry.PackageUploadRejected(`submissionId`, _, reason) => - ErrorFactories.invalidArgument(None)(reason) + errorFactories.packageUploadRejected(reason, definiteAnswer = None) } } diff --git a/ledger/participant-integration-api/src/test/suite/scala/db/migration/translation/apiserver/services/admin/ApiPackageManagementServiceSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/db/migration/translation/apiserver/services/admin/ApiPackageManagementServiceSpec.scala index b8ec9bc1ea..42bd319522 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/db/migration/translation/apiserver/services/admin/ApiPackageManagementServiceSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/db/migration/translation/apiserver/services/admin/ApiPackageManagementServiceSpec.scala @@ -6,10 +6,10 @@ package com.daml.platform.apiserver.services.admin import java.time.{Duration, Instant} import java.util.concurrent.{CompletableFuture, CompletionStage} import java.util.zip.ZipInputStream - import akka.stream.scaladsl.Source import com.daml.daml_lf_dev.DamlLf import com.daml.daml_lf_dev.DamlLf.Archive +import com.daml.error.ErrorCodesVersionSwitcher import com.daml.ledger.api.domain.LedgerOffset.Absolute import com.daml.ledger.api.domain.PackageEntry import com.daml.ledger.api.testing.utils.AkkaBeforeAndAfterAll @@ -49,7 +49,9 @@ class ApiPackageManagementServiceSpec private implicit val loggingContext: LoggingContext = LoggingContext.ForTesting - "ApiPackageManagementService" should { + val errorCodesVersionSwitcher = mock[ErrorCodesVersionSwitcher] + + "ApiPackageManagementService $suffix" should { "propagate trace context" in { val apiService = createApiService() @@ -63,11 +65,13 @@ class ApiPackageManagementServiceSpec } .map { _ => spanExporter.finishedSpanAttributes should contain(anApplicationIdSpanAttribute) + verifyZeroInteractions(errorCodesVersionSwitcher) + succeed } } } - private def createApiService(): PackageManagementServiceGrpc.PackageManagementService = { + def createApiService(): PackageManagementServiceGrpc.PackageManagementService = { val mockDarReader = mock[GenDarReader[Archive]] when(mockDarReader.readArchive(any[String], any[ZipInputStream], any[Int])) .thenReturn(Right(new Dar[Archive](anArchive, List.empty))) @@ -95,6 +99,7 @@ class ApiPackageManagementServiceSpec TestWritePackagesService, Duration.ZERO, mockEngine, + errorCodesVersionSwitcher, mockDarReader, _ => Ref.SubmissionId.assertFromString("aSubmission"), )