From 813c5612fcf780f121beaff39efb3b70715bd4f7 Mon Sep 17 00:00:00 2001
From: jameshall1999 <67314983+jameshall1999@users.noreply.github.com>
Date: Wed, 3 Mar 2021 12:55:59 +0000
Subject: [PATCH] APID-85: Store records with status insead of _type as
discriminator
---
.../models/OutboundSoapMessage.scala | 33 ++++++++++++-------
.../repositories/MongoFormatter.scala | 10 +++++-
.../OutboundMessageRepository.scala | 4 +--
.../OutboundMessageRepositoryISpec.scala | 24 +++++++++++++-
4 files changed, 55 insertions(+), 16 deletions(-)
diff --git a/app/uk/gov/hmrc/apiplatformoutboundsoap/models/OutboundSoapMessage.scala b/app/uk/gov/hmrc/apiplatformoutboundsoap/models/OutboundSoapMessage.scala
index 09db38b..200b194 100644
--- a/app/uk/gov/hmrc/apiplatformoutboundsoap/models/OutboundSoapMessage.scala
+++ b/app/uk/gov/hmrc/apiplatformoutboundsoap/models/OutboundSoapMessage.scala
@@ -21,6 +21,7 @@ import org.joda.time.DateTime
import java.util.UUID
import scala.collection.immutable
+import scala.reflect.classTag
sealed trait OutboundSoapMessage {
val globalId: UUID
@@ -32,6 +33,22 @@ sealed trait OutboundSoapMessage {
val ccnHttpStatus: Int
}
+object OutboundSoapMessage {
+
+ def typeToStatus (fullyQualifiedName: String): SendingStatus = {
+
+ if (fullyQualifiedName == classTag[SentOutboundSoapMessage].runtimeClass.getCanonicalName) {
+ SendingStatus.SENT
+ } else if (fullyQualifiedName == classTag[FailedOutboundSoapMessage].runtimeClass.getCanonicalName) {
+ SendingStatus.FAILED
+ } else if (fullyQualifiedName == classTag[RetryingOutboundSoapMessage].runtimeClass.getCanonicalName) {
+ SendingStatus.RETRYING
+ } else {
+ throw new IllegalArgumentException
+ }
+ }
+}
+
case class SentOutboundSoapMessage(globalId: UUID,
messageId: Option[String],
soapMessage: String,
@@ -63,23 +80,15 @@ case class RetryingOutboundSoapMessage(globalId: UUID,
def toSent = SentOutboundSoapMessage(globalId, messageId, soapMessage, createDateTime, ccnHttpStatus, notificationUrl)
}
-sealed trait SendingStatus extends EnumEntry {
- val soapMessageType: String
-}
+sealed trait SendingStatus extends EnumEntry
object SendingStatus extends Enum[SendingStatus] with PlayJsonEnum[SendingStatus] {
val values: immutable.IndexedSeq[SendingStatus] = findValues
- case object SENT extends SendingStatus {
- override val soapMessageType: String = "uk.gov.hmrc.apiplatformoutboundsoap.models.SentOutboundSoapMessage"
- }
+ case object SENT extends SendingStatus
- case object FAILED extends SendingStatus {
- override val soapMessageType: String = "uk.gov.hmrc.apiplatformoutboundsoap.models.FailedOutboundSoapMessage"
- }
+ case object FAILED extends SendingStatus
- case object RETRYING extends SendingStatus {
- override val soapMessageType: String = "uk.gov.hmrc.apiplatformoutboundsoap.models.RetryingOutboundSoapMessage"
- }
+ case object RETRYING extends SendingStatus
}
diff --git a/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/MongoFormatter.scala b/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/MongoFormatter.scala
index 61e90bf..1d05984 100644
--- a/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/MongoFormatter.scala
+++ b/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/MongoFormatter.scala
@@ -17,11 +17,19 @@
package uk.gov.hmrc.apiplatformoutboundsoap.repositories
import org.joda.time.DateTime
-import play.api.libs.json.{Format, Json, OFormat}
+import play.api.libs.json.{Format, Json, JsonConfiguration, JsonNaming, OFormat}
import uk.gov.hmrc.apiplatformoutboundsoap.models.{FailedOutboundSoapMessage, OutboundSoapMessage, RetryingOutboundSoapMessage, SentOutboundSoapMessage}
import uk.gov.hmrc.mongo.json.ReactiveMongoFormats
private[repositories] object MongoFormatter {
+
+ implicit val cfg = JsonConfiguration(
+ discriminator = "status",
+
+ typeNaming = JsonNaming { fullName =>
+ OutboundSoapMessage.typeToStatus(fullName).entryName
+ })
+
implicit val dateFormat: Format[DateTime] = ReactiveMongoFormats.dateTimeFormats
implicit val outboundSoapMessageFormatter: OFormat[OutboundSoapMessage] = Json.format[OutboundSoapMessage]
implicit val retryingSoapMessageFormatter: OFormat[RetryingOutboundSoapMessage] = Json.format[RetryingOutboundSoapMessage]
diff --git a/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepository.scala b/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepository.scala
index d0721bc..b6177bb 100644
--- a/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepository.scala
+++ b/app/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepository.scala
@@ -63,7 +63,7 @@ class OutboundMessageRepository @Inject()(mongoComponent: ReactiveMongoComponent
import uk.gov.hmrc.apiplatformoutboundsoap.repositories.MongoFormatter.retryingSoapMessageFormatter
collection
- .find(Json.obj("_type" -> SendingStatus.RETRYING.soapMessageType,
+ .find(Json.obj("status" -> SendingStatus.RETRYING.entryName,
"retryDateTime" -> Json.obj("$lte" -> now(UTC))), Option.empty[OutboundSoapMessage])
.sort(Json.obj("retryDateTime" -> 1))
.cursor[RetryingOutboundSoapMessage](ReadPreference.primaryPreferred)
@@ -80,7 +80,7 @@ class OutboundMessageRepository @Inject()(mongoComponent: ReactiveMongoComponent
def updateStatus(globalId: UUID, newStatus: SendingStatus): Future[Option[OutboundSoapMessage]] = {
findAndUpdate(Json.obj("globalId" -> globalId),
- Json.obj("$set" -> Json.obj("_type" -> newStatus.soapMessageType)), fetchNewObject = true)
+ Json.obj("$set" -> Json.obj("status" -> newStatus.entryName)), fetchNewObject = true)
.map(_.result[OutboundSoapMessage])
}
}
diff --git a/it/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepositoryISpec.scala b/it/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepositoryISpec.scala
index c3d22eb..1d245ff 100644
--- a/it/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepositoryISpec.scala
+++ b/it/uk/gov/hmrc/apiplatformoutboundsoap/repositories/OutboundMessageRepositoryISpec.scala
@@ -10,11 +10,14 @@ import org.scalatest.wordspec.AnyWordSpec
import org.scalatestplus.play.guice.GuiceOneAppPerSuite
import play.api.Application
import play.api.inject.guice.GuiceApplicationBuilder
+import play.api.libs.json.{JsObject, Json}
+import play.api.test.Helpers.contentAsJson
import reactivemongo.api.ReadPreference
import reactivemongo.bson.BSONLong
import reactivemongo.core.errors.DatabaseException
import uk.gov.hmrc.apiplatformoutboundsoap.models.{FailedOutboundSoapMessage, RetryingOutboundSoapMessage, SendingStatus, SentOutboundSoapMessage}
import uk.gov.hmrc.mongo.RepositoryPreparation
+import reactivemongo.play.json.ImplicitBSONHandlers.JsObjectDocumentWriter
import java.util.UUID.randomUUID
@@ -36,13 +39,18 @@ class OutboundMessageRepositoryISpec extends AnyWordSpec with Matchers with Repo
}
val retryingMessage = RetryingOutboundSoapMessage(randomUUID, Some("MessageId-A1"), "payload", DateTime.now(UTC), DateTime.now(UTC), ccnHttpStatus)
- val sentMessage = SentOutboundSoapMessage(randomUUID, Some("MessageId-A1"), "payload", DateTime.now(UTC), ccnHttpStatus)
+ val sentMessage = SentOutboundSoapMessage(randomUUID, Some("MessageId-A2"), "payload", DateTime.now(UTC), ccnHttpStatus)
+ val failedMessage = FailedOutboundSoapMessage(randomUUID, Some("MessageId-A3"), "payload", DateTime.now(UTC), ccnHttpStatus)
"persist" should {
"insert a retrying message when it does not exist" in {
await(repo.persist(retryingMessage))
val fetchedRecords = await(repo.findAll(ReadPreference.primaryPreferred))
+ val Some(jsonRecord) = await(repo.collection.find(Json.obj()).one[JsObject])
+ (jsonRecord \ "status").as[String] shouldBe "RETRYING"
+
+
fetchedRecords.size shouldBe 1
fetchedRecords.head shouldBe retryingMessage
}
@@ -51,10 +59,24 @@ class OutboundMessageRepositoryISpec extends AnyWordSpec with Matchers with Repo
await(repo.persist(sentMessage))
val fetchedRecords = await(repo.findAll(ReadPreference.primaryPreferred))
+ val Some(jsonRecord) = await(repo.collection.find(Json.obj()).one[JsObject])
+ (jsonRecord \ "status").as[String] shouldBe "SENT"
+
fetchedRecords.size shouldBe 1
fetchedRecords.head shouldBe sentMessage
}
+ "insert a failed message when it does not exist" in {
+ await(repo.persist(failedMessage))
+
+ val fetchedRecords = await(repo.findAll(ReadPreference.primaryPreferred))
+ val Some(jsonRecord) = await(repo.collection.find(Json.obj()).one[JsObject])
+ (jsonRecord \ "status").as[String] shouldBe "FAILED"
+
+ fetchedRecords.size shouldBe 1
+ fetchedRecords.head shouldBe failedMessage
+ }
+
"message is persisted with TTL" in {
await(repo.persist(sentMessage))