Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PI-1846 #550

Merged
merged 4 commits into from
Feb 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,18 @@ class DomainEventsListener(
}

"probation-case.merge.completed" -> {
calculateTier(message.crn)
calculateTier(message.crn, message.eventType)
message.sourceCrn?.also {
calculator.deleteCalculationsForCrn(it, message.eventType)
}
}

else -> calculateTier(message.crn)
else -> calculateTier(message.crn, message.eventType)
}
}

private fun calculateTier(crn: String?) = crn?.also {
calculator.calculateTierForCrn(it, RecalculationSource.DomainEventRecalculation, true)
private fun calculateTier(crn: String?, eventType: String) = crn?.also {
calculator.calculateTierForCrn(it, RecalculationSource.EventSource.DomainEventRecalculation(eventType), true)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory
import org.springframework.messaging.handler.annotation.MessageExceptionHandler
import org.springframework.stereotype.Service
import uk.gov.justice.digital.hmpps.hmppstier.service.RecalculationSource
import uk.gov.justice.digital.hmpps.hmppstier.service.RecalculationSource.EventSource.OffenderEventRecalculation
import uk.gov.justice.digital.hmpps.hmppstier.service.TierCalculationService

@Service
Expand All @@ -28,14 +29,17 @@ class TierCalculationRequiredEventListener(
val recalculation = getRecalculation(msg)
calculator.calculateTierForCrn(
recalculation.crn,
recalculation.recalculationSource ?: RecalculationSource.OffenderEventRecalculation,
RecalculationSource.of(
recalculation.recalculationSource ?: OffenderEventRecalculation::class.simpleName!!,
recalculation.eventType
),
!recalculation.dryRun
)
}

private fun getRecalculation(msg: String): TierCalculationMessage {
val (message) = objectMapper.readValue<SQSMessage>(msg)
return objectMapper.readValue<TierCalculationMessage>(message)
val (message, attributes) = objectMapper.readValue<SQSMessage>(msg)
return objectMapper.readValue<TierCalculationMessage>(message).forEventType(attributes.eventType)
}

companion object {
Expand All @@ -45,9 +49,17 @@ class TierCalculationRequiredEventListener(

data class TierCalculationMessage(
val crn: String,
val recalculationSource: RecalculationSource? = null,
val recalculationSource: String? = null,
val dryRun: Boolean = false
)
) {
var eventType: String? = null
private set

fun forEventType(eventType: String?): TierCalculationMessage {
this.eventType = eventType
return this
}
}

data class SQSMessage(
@JsonProperty("Message") val message: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
package uk.gov.justice.digital.hmpps.hmppstier.service

enum class RecalculationSource {
FullRecalculation, LimitedRecalculation, DomainEventRecalculation, OffenderEventRecalculation
sealed interface RecalculationSource {
data object FullRecalculation : RecalculationSource

data object LimitedRecalculation : RecalculationSource

data class Other(val type: String?) : RecalculationSource

sealed interface EventSource : RecalculationSource {
val type: String

data class DomainEventRecalculation(override val type: String) : EventSource
data class OffenderEventRecalculation(override val type: String) : EventSource
}

companion object {
fun of(value: String, eventType: String?): RecalculationSource = when (value) {
FullRecalculation::class.simpleName -> FullRecalculation
LimitedRecalculation::class.simpleName -> LimitedRecalculation
EventSource.OffenderEventRecalculation::class.simpleName -> EventSource.OffenderEventRecalculation(eventType!!)
EventSource.DomainEventRecalculation::class.simpleName -> EventSource.DomainEventRecalculation(eventType!!)
else -> Other(eventType)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,22 @@ class TelemetryService(@Autowired private val telemetryClient: TelemetryClient)
} else {
TIER_UNCHANGED
},
mapOf(
listOfNotNull(
"crn" to calculation.crn,
"protect" to calculation.data.protect.tier.value,
"change" to calculation.data.change.tier.value.toString(),
"version" to calculation.data.calculationVersion,
"recalculationReason" to recalculationSource.name,
),
"recalculationSource" to recalculationSource::class.simpleName,
recalculationSource.reason()?.let { "recalculationReason" to it },
).toMap(),
)
}

private fun RecalculationSource.reason() = when (this) {
is RecalculationSource.EventSource -> type
else -> null
}

fun trackEvent(eventType: TelemetryEventType, customDimensions: Map<String, String?>) {
telemetryClient.trackEvent(eventType.eventName, customDimensions, null)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package uk.gov.justice.digital.hmpps.hmppstier.service

import org.slf4j.LoggerFactory
import org.springframework.dao.DataIntegrityViolationException
import org.springframework.stereotype.Service
import uk.gov.justice.digital.hmpps.hmppstier.client.AssessmentForTier
import uk.gov.justice.digital.hmpps.hmppstier.client.NeedSection
Expand Down Expand Up @@ -33,11 +34,11 @@ class TierCalculationService(
mapOf("crn" to crn, "reason" to reason),
)
} catch (e: Exception) {
log.error("Unable to remove tier calculations for $crn")
telemetryService.trackEvent(
TIER_CALCULATION_REMOVAL_FAILED,
mapOf("crn" to crn, "reasonToDelete" to reason, "failureReason" to e.message),
)
throw e
}

fun calculateTierForCrn(crn: String, recalculationSource: RecalculationSource, allowUpdates: Boolean) {
Expand All @@ -61,7 +62,13 @@ class TierCalculationService(
val eventType = if (allowUpdates) TIER_CALCULATION_FAILED else TIER_RECALCULATION_DRY_RUN_FAILURE
telemetryService.trackEvent(
eventType,
mapOf("crn" to crn, "exception" to e.message, "recalculationReason" to recalculationSource.name),
mapOf(
"crn" to crn,
"exception" to e.message,
"recalculationSource" to recalculationSource::class.simpleName,
"recalculationReason" to if (recalculationSource is RecalculationSource.EventSource) recalculationSource.type else "",
"duplicateAttempt" to (e is DataIntegrityViolationException).toString()
),
)
if (allowUpdates) {
checkForCrnNotFound(crn, e)
Expand All @@ -70,10 +77,10 @@ class TierCalculationService(
}

private fun checkForCrnNotFound(crn: String, e: Exception) {
if (e is CrnNotFoundException) {
deleteCalculationsForCrn(crn, "Not Found in Delius")
} else {
throw e
when (e) {
is DataIntegrityViolationException -> return
is CrnNotFoundException -> deleteCalculationsForCrn(crn, "Not Found in Delius")
else -> throw e
}
}

Expand Down Expand Up @@ -128,8 +135,4 @@ class TierCalculationService(
).toMap()

private fun NeedSection.mapSeverity(): Pair<Need, NeedSeverity>? = severity?.let { section to it }

companion object {
private val log = LoggerFactory.getLogger(this::class.java)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,19 @@ class TierReader(

fun getLatestTierByCrn(crn: String): TierDto? =
tierSummaryRepository.findByIdOrNull(crn)?.let {
log.info("Found latest tier calculation for $crn")
TierDto.from(it)
}

fun getLatestTierDetailsByCrn(crn: String): TierDetailsDto? =
getLatestTierCalculation(crn)?.let {
log.info("Found latest tier calculation for $crn")
TierDetailsDto.from(it)
}

fun getTierByCalculationId(crn: String, calculationId: UUID): TierDto? =
tierCalculationRepository.findByCrnAndUuid(crn, calculationId)?.let {
log.info("Found tier for $crn and $calculationId")
TierDto.from(it)
}

private fun getLatestTierCalculation(crn: String): TierCalculationEntity? =
tierCalculationRepository.findFirstByCrnOrderByCreatedDesc(crn)

companion object {
private val log =
LoggerFactory.getLogger(this::class.java)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package uk.gov.justice.digital.hmpps.hmppstier.service

import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Propagation
import org.springframework.transaction.annotation.Transactional
import uk.gov.justice.digital.hmpps.hmppstier.jpa.entity.TierCalculationEntity
import uk.gov.justice.digital.hmpps.hmppstier.jpa.entity.TierSummary
Expand All @@ -14,6 +15,7 @@ class TierUpdater(
private val tierSummaryRepository: TierSummaryRepository,
) {

@Transactional(propagation = Propagation.REQUIRES_NEW)
fun removeTierCalculationsFor(crn: String) {
tierCalculationRepository.deleteAllByCrn(crn)
tierSummaryRepository.deleteById(crn)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class TriggerCalculationService(
dryRun: Boolean
): SQSMessage = SQSMessage(
objectMapper.writeValueAsString(
TierCalculationMessage(crn, recalculationSource, dryRun),
TierCalculationMessage(crn, recalculationSource::class.simpleName, dryRun),
),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import uk.gov.justice.digital.hmpps.hmppstier.integration.mockserver.tierToDeliu
import uk.gov.justice.digital.hmpps.hmppstier.integration.mockserver.tierToDeliusApi.response.domain.Registration
import uk.gov.justice.digital.hmpps.hmppstier.integration.mockserver.tierToDeliusApi.response.domain.TierDetails
import uk.gov.justice.digital.hmpps.hmppstier.integration.setup.IntegrationTestBase
import uk.gov.justice.digital.hmpps.hmppstier.service.RecalculationSource.DomainEventRecalculation
import uk.gov.justice.digital.hmpps.hmppstier.service.RecalculationSource

class DomainEventsListenerTest : IntegrationTestBase() {
@Test
Expand Down Expand Up @@ -61,7 +61,11 @@ class DomainEventsListenerTest : IntegrationTestBase() {
mapOf("sourceCRN" to source),
)
)
verify(tierCalculationService, timeout(5000)).calculateTierForCrn(target, DomainEventRecalculation, true)
verify(tierCalculationService, timeout(5000)).calculateTierForCrn(
target,
RecalculationSource.EventSource.DomainEventRecalculation(eventType),
true
)
verify(tierCalculationService, timeout(5000)).deleteCalculationsForCrn(source, eventType)
}

Expand All @@ -76,6 +80,10 @@ class DomainEventsListenerTest : IntegrationTestBase() {
)
)
verify(tierCalculationService, timeout(5000)).deleteCalculationsForCrn(crn, eventType)
verify(tierCalculationService, never()).calculateTierForCrn(crn, DomainEventRecalculation, true)
verify(tierCalculationService, never()).calculateTierForCrn(
crn,
RecalculationSource.EventSource.DomainEventRecalculation(eventType),
true
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ class CannotCalculateTierTest : IntegrationTestBase() {
mapOf(
"crn" to "X123456",
"exception" to "404 Not Found from GET http://localhost:8093/tier-details/X123456",
"recalculationReason" to "OffenderEventRecalculation",
"recalculationSource" to "OffenderEventRecalculation",
"recalculationReason" to "OFFENDER_MANAGEMENT_TIER_CALCULATION_REQUIRED",
"duplicateAttempt" to "false"
),
null,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class TriggerRecalculationsTest : IntegrationTestBase() {
"protect" to "A",
"change" to "1",
"version" to "2",
"recalculationReason" to "LimitedRecalculation",
"recalculationSource" to "LimitedRecalculation",
),
null,
)
Expand Down Expand Up @@ -88,7 +88,7 @@ class TriggerRecalculationsTest : IntegrationTestBase() {
"protect" to "A",
"change" to "1",
"version" to "2",
"recalculationReason" to "FullRecalculation",
"recalculationSource" to "FullRecalculation",
),
null,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import uk.gov.justice.digital.hmpps.hmppstier.domain.enums.ProtectLevel
import uk.gov.justice.digital.hmpps.hmppstier.jpa.entity.TierCalculationEntity
import uk.gov.justice.digital.hmpps.hmppstier.jpa.entity.TierCalculationResultEntity
import java.time.LocalDateTime
import java.util.UUID
import java.util.*

@ExtendWith(MockKExtension::class)
@DisplayName("Telemetry Service tests")
Expand Down Expand Up @@ -60,7 +60,12 @@ internal class TelemetryServiceTest {

@Test
fun `Should emit TierChanged event when tier HAS changed`() {
service.trackTierCalculated(tierCalculation, true, RecalculationSource.DomainEventRecalculation)
val eventType = "some.event.type"
service.trackTierCalculated(
tierCalculation,
true,
RecalculationSource.EventSource.DomainEventRecalculation(eventType)
)

verify {
client.trackEvent(
Expand All @@ -70,7 +75,8 @@ internal class TelemetryServiceTest {
"protect" to tierCalculation.data.protect.tier.value,
"change" to tierCalculation.data.change.tier.value.toString(),
"version" to tierCalculation.data.calculationVersion,
"recalculationReason" to "DomainEventRecalculation",
"recalculationSource" to "DomainEventRecalculation",
"recalculationReason" to eventType
),
null,
)
Expand All @@ -79,7 +85,12 @@ internal class TelemetryServiceTest {

@Test
fun `Should emit TierUnchanged event when tier HAS NOT changed`() {
service.trackTierCalculated(tierCalculation, false, RecalculationSource.DomainEventRecalculation)
val eventType = "some.event.type"
service.trackTierCalculated(
tierCalculation,
false,
RecalculationSource.EventSource.DomainEventRecalculation(eventType)
)

verify {
client.trackEvent(
Expand All @@ -89,7 +100,8 @@ internal class TelemetryServiceTest {
"protect" to tierCalculation.data.protect.tier.value,
"change" to tierCalculation.data.change.tier.value.toString(),
"version" to tierCalculation.data.calculationVersion,
"recalculationReason" to "DomainEventRecalculation",
"recalculationSource" to "DomainEventRecalculation",
"recalculationReason" to eventType
),
null,
)
Expand Down