Skip to content

Commit

Permalink
feat(orchestrator-api): Extend TaskStepResultRequest with step as pre…
Browse files Browse the repository at this point in the history
…condition for authorization
  • Loading branch information
martinfkaeser committed Oct 18, 2023
1 parent 599e98c commit cdee404
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ interface GoldenRecordTaskApi {

@Operation(
summary = "Post step results for reserved golden record tasks in the given step queue",
description = "Post business partner step results for the given tasks. " +
description = "Post business partner step results for the given tasks in the given step queue. " +
"In order to post a result for a task it needs to be reserved first, has to currently be in the given step queue and the time limit is not exceeded. " +
"The number of results you can post at a time does not need to match the original number of reserved tasks. " +
"Results are accepted via strategy 'all or nothing'. " +
Expand All @@ -114,7 +114,11 @@ interface GoldenRecordTaskApi {
responseCode = "204",
description = "If the results could be processed"
),
ApiResponse(responseCode = "400", description = "On malformed task create requests or reaching upsert limit", content = [Content()]),
ApiResponse(
responseCode = "400",
description = "On malformed requests, reaching upsert limit or posting results for tasks which are missing or in the wrong step queue",
content = [Content()]
),
]
)
@Tag(name = TagWorker)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,8 @@ import io.swagger.v3.oas.annotations.media.Schema
@Schema(description = "Request object for posting step results of previously reserved tasks")
data class TaskStepResultRequest(

@get:Schema(description = "The step queue containing the tasks for which results are posted", required = true)
val step: TaskStep,

val results: List<TaskStepResultEntryDto>
)
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ class GoldenRecordTaskService(
.forEach { resultEntry ->
val task = taskStorage.getTask(resultEntry.taskId)
?: throw BpdmTaskNotFoundException(resultEntry.taskId)

val step = resultRequest.step
val errors = resultEntry.errors
val resultBusinessPartner = resultEntry.businessPartner

if (errors.isNotEmpty()) {
goldenRecordTaskStateMachine.doResolveFailed(task, errors)
goldenRecordTaskStateMachine.doResolveFailed(task, step, errors)
} else if (resultBusinessPartner != null) {
goldenRecordTaskStateMachine.doResolveSuccessful(task, resultBusinessPartner)
goldenRecordTaskStateMachine.doResolveSuccessful(task, step, resultBusinessPartner)
} else {
throw BpdmEmptyResultException(resultEntry.taskId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ class GoldenRecordTaskStateMachine(
state.taskModifiedAt = now
}

fun doResolveSuccessful(task: GoldenRecordTask, resultBusinessPartner: BusinessPartnerFullDto) {
fun doResolveSuccessful(task: GoldenRecordTask, step: TaskStep, resultBusinessPartner: BusinessPartnerFullDto) {
val state = task.processingState
val now = Instant.now()

if (state.resultState != ResultState.Pending || state.stepState != StepState.Reserved) {
if (state.resultState != ResultState.Pending || state.stepState != StepState.Reserved || state.step != step) {
throw BpdmIllegalStateException(task.taskId, state)
}

Expand All @@ -92,11 +92,11 @@ class GoldenRecordTaskStateMachine(
task.businessPartner = resultBusinessPartner
}

fun doResolveFailed(task: GoldenRecordTask, errors: List<TaskErrorDto>) {
fun doResolveFailed(task: GoldenRecordTask, step: TaskStep, errors: List<TaskErrorDto>) {
val state = task.processingState
val now = Instant.now()

if (state.resultState != ResultState.Pending || state.stepState != StepState.Reserved) {
if (state.resultState != ResultState.Pending || state.stepState != StepState.Reserved || state.step != step) {
throw BpdmIllegalStateException(task.taskId, state)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
taskId = taskId,
businessPartner = businessPartnerFull1
)
resolveTasks(listOf(resultEntry1))
resolveTasks(TaskStep.CleanAndSync, listOf(resultEntry1))

// now in next step and stepState==Queued
assertProcessingStateDto(
Expand Down Expand Up @@ -235,7 +235,7 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
taskId = taskId,
businessPartner = businessPartnerFull2
)
resolveTasks(listOf(resultEntry2))
resolveTasks(TaskStep.PoolSync, listOf(resultEntry2))

// final step -> now in stepState==Success
val finalStateDto = searchTaskStates(listOf(taskId)).tasks.single()
Expand Down Expand Up @@ -270,7 +270,7 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
taskId = taskId,
errors = listOf(errorDto)
)
resolveTasks(listOf(resultEntry))
resolveTasks(TaskStep.CleanAndSync, listOf(resultEntry))

// now in error state
val stateDto = searchTaskStates(listOf(taskId)).tasks.single()
Expand Down Expand Up @@ -335,7 +335,7 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
)

assertBadRequestException {
resolveTasks(resultEntries)
resolveTasks(TaskStep.CleanAndSync, resultEntries)
}
}

Expand All @@ -360,6 +360,7 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
// post wrong task ids
assertBadRequestException {
resolveTasks(
TaskStep.CleanAndSync,
listOf(
TaskStepResultEntryDto(
taskId = "WRONG-ID"
Expand All @@ -368,9 +369,10 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
)
}

// post correct task id but neither empty content
// post correct task id but empty content
assertBadRequestException {
resolveTasks(
TaskStep.CleanAndSync,
listOf(
TaskStepResultEntryDto(
taskId = tasksIds[0]
Expand All @@ -379,8 +381,22 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
)
}

// post correct task id but wrong step (Clean)
assertBadRequestException {
resolveTasks(
TaskStep.Clean,
listOf(
TaskStepResultEntryDto(
taskId = tasksIds[0],
businessPartner = BusinessPartnerTestValues.businessPartner1Full
)
)
)
}

// post correct task id with business partner content
resolveTasks(
TaskStep.CleanAndSync,
listOf(
TaskStepResultEntryDto(
taskId = tasksIds[0],
Expand All @@ -392,6 +408,7 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
// post task twice
assertBadRequestException {
resolveTasks(
TaskStep.CleanAndSync,
listOf(
TaskStepResultEntryDto(
taskId = tasksIds[0],
Expand All @@ -404,6 +421,7 @@ class GoldenRecordTaskControllerIT @Autowired constructor(

// post correct task id with error content
resolveTasks(
TaskStep.CleanAndSync,
listOf(
TaskStepResultEntryDto(
tasksIds[1], errors = listOf(
Expand All @@ -430,11 +448,9 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
)
)

private fun resolveTasks(results: List<TaskStepResultEntryDto>) =
private fun resolveTasks(step: TaskStep, results: List<TaskStepResultEntryDto>) =
orchestratorClient.goldenRecordTasks.resolveStepResults(
TaskStepResultRequest(
results = results
)
TaskStepResultRequest(step, results)
)

private fun searchTaskStates(taskIds: List<String>) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,26 +91,31 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
}.isInstanceOf(BpdmIllegalStateException::class.java)

// 1st resolve
goldenRecordTaskStateMachine.doResolveSuccessful(task, BusinessPartnerTestValues.businessPartner1Full)
goldenRecordTaskStateMachine.doResolveSuccessful(task, TaskStep.CleanAndSync, BusinessPartnerTestValues.businessPartner1Full)
assertProcessingStateDto(task.processingState, ResultState.Pending, TaskStep.PoolSync, StepState.Queued)
assertThat(task.processingState.reservationTimeout).isNull()

// Can't resolve again!
assertThatThrownBy {
goldenRecordTaskStateMachine.doResolveSuccessful(task, BusinessPartnerTestValues.businessPartner1Full)
goldenRecordTaskStateMachine.doResolveSuccessful(task, TaskStep.CleanAndSync, BusinessPartnerTestValues.businessPartner1Full)
}.isInstanceOf(BpdmIllegalStateException::class.java)

// 2nd reserve
goldenRecordTaskStateMachine.doReserve(task)
assertProcessingStateDto(task.processingState, ResultState.Pending, TaskStep.PoolSync, StepState.Reserved)

// Can't resolve with wrong step (CleanAndSync)!
assertThatThrownBy {
goldenRecordTaskStateMachine.doResolveSuccessful(task, TaskStep.CleanAndSync, BusinessPartnerTestValues.businessPartner1Full)
}.isInstanceOf(BpdmIllegalStateException::class.java)

// 2nd resolve
goldenRecordTaskStateMachine.doResolveSuccessful(task, BusinessPartnerTestValues.businessPartner1Full)
goldenRecordTaskStateMachine.doResolveSuccessful(task, TaskStep.PoolSync, BusinessPartnerTestValues.businessPartner1Full)
assertProcessingStateDto(task.processingState, ResultState.Success, TaskStep.PoolSync, StepState.Success)

// Can't resolve again!
assertThatThrownBy {
goldenRecordTaskStateMachine.doResolveFailed(task, listOf(TaskErrorDto(TaskErrorType.Unspecified, "error")))
goldenRecordTaskStateMachine.doResolveFailed(task, TaskStep.PoolSync, listOf(TaskErrorDto(TaskErrorType.Unspecified, "error")))
}.isInstanceOf(BpdmIllegalStateException::class.java)
}

Expand Down Expand Up @@ -140,7 +145,7 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
Thread.sleep(10)

// resolve
goldenRecordTaskStateMachine.doResolveSuccessful(task, BusinessPartnerTestValues.businessPartner1Full)
goldenRecordTaskStateMachine.doResolveSuccessful(task, TaskStep.Clean, BusinessPartnerTestValues.businessPartner1Full)
assertProcessingStateDto(task.processingState, ResultState.Success, TaskStep.Clean, StepState.Success)
val modified2 = task.processingState.taskModifiedAt
assertThat(modified2).isAfter(modified1)
Expand All @@ -167,7 +172,7 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
TaskErrorDto(TaskErrorType.Unspecified, "Unspecific error"),
TaskErrorDto(TaskErrorType.Timeout, "Timeout")
)
goldenRecordTaskStateMachine.doResolveFailed(task, errors)
goldenRecordTaskStateMachine.doResolveFailed(task, TaskStep.Clean, errors)
assertProcessingStateDto(task.processingState, ResultState.Error, TaskStep.Clean, StepState.Error)
assertThat(task.processingState.errors).isEqualTo(errors)

Expand All @@ -176,9 +181,9 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
goldenRecordTaskStateMachine.doReserve(task)
}.isInstanceOf(BpdmIllegalStateException::class.java)

// Can't reserve now!
// Can't resolve now!
assertThatThrownBy {
goldenRecordTaskStateMachine.doResolveSuccessful(task, BusinessPartnerTestValues.businessPartner1Full)
goldenRecordTaskStateMachine.doResolveSuccessful(task, TaskStep.Clean, BusinessPartnerTestValues.businessPartner1Full)
}.isInstanceOf(BpdmIllegalStateException::class.java)
}

Expand Down

0 comments on commit cdee404

Please sign in to comment.