Skip to content

Commit

Permalink
Add function to get offender info in batches
Browse files Browse the repository at this point in the history
  • Loading branch information
davidatkinsuk committed Jan 6, 2025
1 parent 8af458a commit 5adca1e
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package uk.gov.justice.digital.hmpps.approvedpremisesapi.service

import org.apache.commons.collections4.ListUtils
import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
Expand Down Expand Up @@ -47,6 +48,7 @@ import uk.gov.justice.digital.hmpps.approvedpremisesapi.transformer.PersonTransf
import uk.gov.justice.digital.hmpps.approvedpremisesapi.util.asCaseSummary
import java.io.OutputStream
import java.time.LocalDate
import java.util.stream.Collectors

@Service
class OffenderService(
Expand Down Expand Up @@ -109,6 +111,32 @@ class OffenderService(
data class ReturnRestrictedIfLimitedAccess(val deliusUsername: String) : LimitedAccessStrategy
}

/**
* The [getPersonSummaryInfoResults] function is limited to providing information for up to 500 CRNs
*
* If information is required about more than 500 CRNs, this function should be used instead
*
* Note - this should be used with care and only used for infrequently ran operations, e.g. monthly
* reports, seed jobs as this should not be a typical operation
*/
fun getPersonSummaryInfoResultsInBatches(
crns: Set<String>,
limitedAccessStrategy: LimitedAccessStrategy,
batchSize: Int = 500,
): List<PersonSummaryInfoResult> {
if (batchSize > MAX_OFFENDER_REQUEST_COUNT) {
throw InternalServerErrorProblem("Cannot request more than $MAX_OFFENDER_REQUEST_COUNT CRNs. A batch size of $batchSize has been requested.")
}

return ListUtils.partition(crns.toList(), batchSize)
.stream()
.map { crnSubset ->
getPersonSummaryInfoResults(crnSubset.toSet(), limitedAccessStrategy)
}
.flatMap { it.stream() }
.collect(Collectors.toList())
}

fun getPersonSummaryInfoResults(
crns: Set<String>,
limitedAccessStrategy: LimitedAccessStrategy,
Expand All @@ -117,6 +145,10 @@ class OffenderService(
return emptyList()
}

if (crns.size > MAX_OFFENDER_REQUEST_COUNT) {
throw InternalServerErrorProblem("Cannot request more than $MAX_OFFENDER_REQUEST_COUNT CRNs. ${crns.size} have been provided.")
}

val crnsList = crns.toList()

val caseSummariesByCrn = when (val result = apDeliusContextApiClient.getSummariesForCrns(crnsList)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2098,6 +2098,58 @@ class OffenderServiceTest {
}
}

@Nested
inner class GetPersonSummaryInfoResultsInBatches {

@Test
fun `error if batch size greater than 500`() {
assertThatThrownBy {
offenderService.getPersonSummaryInfoResultsInBatches(
crns = emptySet(),
batchSize = 501,
limitedAccessStrategy = LimitedAccessStrategy.IgnoreLimitedAccess,
)
}.isInstanceOf(InternalServerErrorProblem::class.java)
.hasMessage("Internal Server Error: Cannot request more than 500 CRNs. A batch size of 501 has been requested.")
}

@Test
fun `request offender info in batches of 400`() {
val crns = (1..750).map { "CRN$it" }
val offenderSummaries = crns.map { CaseSummaryFactory().withCrn(it).produce() }
val caseAccesses = crns.map { CaseAccessFactory().withCrn(it).produce() }

every {
mockApDeliusContextApiClient.getSummariesForCrns((1..400).map { "CRN$it" })
} returns ClientResult.Success(HttpStatus.OK, CaseSummaries(offenderSummaries.subList(0, 400)))

every {
mockApDeliusContextApiClient.getSummariesForCrns((401..750).map { "CRN$it" })
} returns ClientResult.Success(HttpStatus.OK, CaseSummaries(offenderSummaries.subList(400, 750)))

every {
mockApDeliusContextApiClient.getUserAccessForCrns(USERNAME, (1..400).map { "CRN$it" })
} returns ClientResult.Success(HttpStatus.OK, UserAccess(caseAccesses.subList(0, 400)))

every {
mockApDeliusContextApiClient.getUserAccessForCrns(USERNAME, (401..750).map { "CRN$it" })
} returns ClientResult.Success(HttpStatus.OK, UserAccess(caseAccesses.subList(401, 750)))

val results = offenderService.getPersonSummaryInfoResultsInBatches(
crns = crns.toSet(),
limitedAccessStrategy = ReturnRestrictedIfLimitedAccess(USERNAME),
batchSize = 400,
)

assertThat(results).hasSize(750)
(0..749).forEach {
val result = results[it]
assertThat(result).isInstanceOf(PersonSummaryInfoResult.Success.Full::class.java)
assertThat((result as PersonSummaryInfoResult.Success.Full).summary).isEqualTo(offenderSummaries[it])
}
}
}

private fun clientResultSuccess(
userRestricted: Boolean,
userExcluded: Boolean,
Expand Down

0 comments on commit 5adca1e

Please sign in to comment.