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

feat(Orchestrator): ignore resolutions for already resolved steps #1091

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ For changes to the BPDM Helm charts please consult the [changelog](charts/bpdm/C
- BPDM Gate: Fixed logic for identifiers to retrieve only generic type on output business partner
- BPDM Gate: Fixed construction logic for states and identifiers by enabling business partner type
- BPDM Pool: When processing golden record tasks the Pool now ignores isCatenaXMemberData field if it is set to null. ([#1069](https://github.com/eclipse-tractusx/bpdm/issues/1069))
- BPDM Orchestrator: When trying to resolve tasks for a step that have has been resolved before, the request is ignored. A HTTP OK instead of a BadRequest will be returned.

## [6.1.0] - [2024-07-15]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,14 @@ class GoldenRecordTaskStateMachine(
logger.debug { "Executing doResolveTaskToSuccess() with parameters $task // $step and $resultBusinessPartner" }
val state = task.processingState

if (isResolvableForStep(state, step)) {
throw BpdmIllegalStateException(task.uuid, state)
if (!isResolvableForStep(state, step)) {
if(hasAlreadyResolvedStep(state, step))
{
logger.debug { "Task ${task.uuid} has already been processed for step $step. Result is ignored" }
return task
}else{
throw BpdmIllegalStateException(task.uuid, state)
}
}

val nextStep = getNextStep(state.mode, state.step)
Expand All @@ -114,8 +120,14 @@ class GoldenRecordTaskStateMachine(
logger.debug { "Executing doResolveTaskToError() with parameters $task // $step and $errors" }
val state = task.processingState

if (isResolvableForStep(state, step)) {
throw BpdmIllegalStateException(task.uuid, state)
if (!isResolvableForStep(state, step)) {
if(hasAlreadyResolvedStep(state, step))
{
logger.debug { "Task ${task.uuid} has already been processed for step $step. Result is ignored" }
return task
}else{
throw BpdmIllegalStateException(task.uuid, state)
}
}

task.processingState.toError(errors.map { requestMapper.toTaskError(it) })
Expand Down Expand Up @@ -187,9 +199,21 @@ class GoldenRecordTaskStateMachine(
.firstOrNull() // return next step
}

private fun hasAlreadyResolvedStep(state: GoldenRecordTaskDb.ProcessingState, step: TaskStep): Boolean{
if(state.step == step) return state.stepState != GoldenRecordTaskDb.StepState.Reserved
return isStepBefore(step, state.step, state.mode)
}

private fun isStepBefore(stepBefore: TaskStep, stepAfter: TaskStep, mode: TaskMode): Boolean{
val modeSteps = stateMachineConfigProperties.modeSteps[mode]!!
return modeSteps.contains(stepBefore) && modeSteps.indexOf(stepBefore) <= modeSteps.indexOf(stepAfter)
}

private fun isResolvableForStep(state: GoldenRecordTaskDb.ProcessingState, step: TaskStep): Boolean{
return state.resultState != GoldenRecordTaskDb.ResultState.Pending
|| state.stepState != GoldenRecordTaskDb.StepState.Reserved
|| state.step != step
return state.resultState == GoldenRecordTaskDb.ResultState.Pending
&& state.stepState == GoldenRecordTaskDb.StepState.Reserved
&& state.step == step
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,6 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
* THEN expect a BAD_REQUEST
* WHEN trying to resolve a task with empty content
* THEN expect a BAD_REQUEST
* WHEN trying to resolve a task twice
* THEN expect a BAD_REQUEST
*/
@ParameterizedTest
@EnumSource(TaskMode::class)
Expand Down Expand Up @@ -376,19 +374,6 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
)
)

// post task twice
assertBadRequestException {
resolveTasks(
firstStep,
listOf(
TaskStepResultEntryDto(
taskId = tasksIds[0],
businessPartner = defaultBusinessPartner1
)
)
)
}

// post correct task id with error content
resolveTasks(
firstStep,
Expand Down Expand Up @@ -581,6 +566,58 @@ class GoldenRecordTaskControllerIT @Autowired constructor(
}
}

@ParameterizedTest
@EnumSource(TaskMode::class)
fun `ignore resolution for already resolved steps`(taskMode: TaskMode){
val allSteps = stateMachineConfigProperties.modeSteps[taskMode]!!

// create tasks
val createdTasks = createTasksWithoutRecordId(mode = taskMode, businessPartners = listOf(defaultBusinessPartner1, defaultBusinessPartner2)).createdTasks

var expectedBusinessPartners = createdTasks.map { it.businessPartnerResult }
allSteps.forEach { step ->
val reservedTasks = reserveTasks(step, 2).reservedTasks

val resolvedBusinessPartners = reservedTasks.map {
TaskStepResultEntryDto(
taskId = it.taskId,
businessPartner = testDataFactory.createFullBusinessPartner("${it.taskId} $step Resolved")
)
}
resolveTasks(step, resolvedBusinessPartners)
expectedBusinessPartners = resolvedBusinessPartners.map { it.businessPartner }

val stepsSoFar = stateMachineConfigProperties.modeSteps[taskMode]!!.takeWhile { it != step } + step
stepsSoFar.forEach { previousStep ->
// accept and ignore resolving already resolved tasks
reservedTasks.map {
TaskStepResultEntryDto(
taskId = it.taskId,
businessPartner = testDataFactory.createFullBusinessPartner("${it.taskId} $previousStep Resolved Again")
)
}
resolveTasks(step, resolvedBusinessPartners)
}
}

// final step -> now in stepState==Success
val finalTaskStates = createdTasks.searchTaskStates(createdTasks.map { it.taskId }).tasks
finalTaskStates.forEach { task ->
assertProcessingStateDto(
task.processingState,
ResultState.Success, stateMachineConfigProperties.modeSteps[taskMode]!!.last(), StepState.Success
)
}
// check returned BP
assertThat(finalTaskStates.map { it.businessPartnerResult })
.usingRecursiveComparison()
.ignoringCollectionOrder()
.isEqualTo(expectedBusinessPartners)


}


private fun createTasks(mode: TaskMode,
entries: List<TaskCreateRequestEntry>? = null
): TaskCreateResponse{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,6 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
* GIVEN a task with initial TaskProcessingState
* WHEN reserving and resolving
* THEN expect the TaskProcessingState to walk through all the steps/states until final state Success
* WHEN trying to reserve or resolve twice
* THEN expect an error
*/
@ParameterizedTest
@EnumSource(TaskMode::class)
Expand Down Expand Up @@ -134,10 +132,8 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
// resolve
goldenRecordTaskStateMachine.resolveTaskStepToSuccess(task, step, businessPartnerFull)

// resolve again!
assertThatThrownBy {
goldenRecordTaskStateMachine.resolveTaskStepToSuccess(task, step, businessPartnerFull)
}.isInstanceOf(BpdmIllegalStateException::class.java)
// resolve again ignored
goldenRecordTaskStateMachine.resolveTaskStepToSuccess(task, step, businessPartnerFull)
}

val finalStep = stateMachineConfigProperties.modeSteps[taskMode]!!.last()
Expand All @@ -150,14 +146,12 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
WITHIN_ALLOWED_TIME_OFFSET
)

// Can't resolve again!
assertThatThrownBy {
goldenRecordTaskStateMachine.doResolveTaskToError(
task,
finalStep,
listOf(TaskErrorDto(TaskErrorType.Unspecified, "error"))
)
}.isInstanceOf(BpdmIllegalStateException::class.java)
// Second resolve ignored
goldenRecordTaskStateMachine.doResolveTaskToError(
task,
finalStep,
listOf(TaskErrorDto(TaskErrorType.Unspecified, "error"))
)
}


Expand Down Expand Up @@ -202,10 +196,8 @@ class GoldenRecordTaskStateMachineIT @Autowired constructor(
goldenRecordTaskStateMachine.doReserve(task)
}.isInstanceOf(BpdmIllegalStateException::class.java)

// Can't resolve now!
assertThatThrownBy {
goldenRecordTaskStateMachine.resolveTaskStepToSuccess(task, expectedStep, businessPartnerFull)
}.isInstanceOf(BpdmIllegalStateException::class.java)
// Resolve again ignored
goldenRecordTaskStateMachine.resolveTaskStepToSuccess(task, expectedStep, businessPartnerFull)
}

private fun assertProcessingState(processingState: GoldenRecordTaskDb.ProcessingState,
Expand Down
Loading