src/agent/adu_core_interface/src/agent_workflow.c
static void ADUC_Workflow_WorkCompletionCallback(const void* workCompletionToken, ADUC_Result result)
{
    // We own these objects, so no issue making them non-const.
    ADUC_MethodCall_Data* methodCallData = (ADUC_MethodCall_Data*)workCompletionToken;
    ADUC_WorkflowData* workflowData = methodCallData->WorkflowData;

    // NOLINTNEXTLINE(misc-redundant-expression)
    if (AducResultCodeIndicatesInProgress(result.ResultCode))
    {
        Log_Error("WorkComplete received InProgress result code - should not happen!");
        goto done;
    }

    const ADUC_WorkflowHandlerMapEntry* entry = GetWorkflowHandlerMapEntryForAction(workflowData->CurrentAction);
    if (entry == NULL)
    {
        Log_Error("Invalid UpdateAction %u -- ignoring", workflowData->CurrentAction);
        goto done;
    }

    if (entry->Action == ADUCITF_UpdateAction_Cancel)
    {
        Log_Error("Cancel received in completion callback - should not happen!");
        goto done;
    }

    Log_Info(
        "Action '%s' complete. Result: %d, %d",
        ADUCITF_UpdateActionToString(entry->Action),
        result.ResultCode,
        result.ExtendedResultCode);

    entry->OperationCompleteFunc(methodCallData, result);

    if (IsAducResultCodeSuccess(result.ResultCode))
    {
        // Operation succeeded -- go to next state.

        const ADUCITF_State nextUpdateState = entry->NextState;

        Log_Info(
            "WorkCompletionCallback: %s succeeded. Going to state %s",
            ADUCITF_UpdateActionToString(entry->Action),
            ADUCITF_StateToString(nextUpdateState));

        ADUC_SetUpdateState(workflowData, nextUpdateState);
    }
    else
    {
        // Operation (e.g. Download) failed or was cancelled - both are considered AducResult failure codes.

        if (workflowData->OperationCancelled)
        {
            // Operation cancelled.
            //
            // We are now at the completion of the operation that was cancelled and will just return to Idle state,
            // Ignore the result of the operation, which most likely is cancelled, e.g. ADUC_DownloadResult_Cancelled.

            Log_Error("Operation cancelled - returning to Idle state");

            const ADUC_Result result = { .ResultCode = ADUC_IdleResult_Success };
            ADUC_SetUpdateStateWithResult(workflowData, ADUCITF_State_Idle, result);
        }
        else
        {
            // Operation failed.
            //
            // Report back the result and set state to "Failed".
            // It's expected that the service will call us again with a "Cancel" action,
            // to indicate that it's received the operation result and state, at which time
            // we'll return back to idle state.

            Log_Error(
                "%s failed. error %d, %d - Expecting service to send Cancel action",
                ADUCITF_UpdateActionToString(entry->Action),
                result.ResultCode,
                result.ExtendedResultCode);

            ADUC_SetUpdateStateWithResult(workflowData, ADUCITF_State_Failed, result);
        }
    }

done:
    // Operation is now complete.
    workflowData->OperationInProgress = false;
    workflowData->OperationCancelled = false;

    free(methodCallData);
}
/**
 * @brief Called when work is complete.
 *
 * @param workCompletionToken ADUC_MethodCall_Data pointer.
 * @param result Result of work.
 */
@brief Called when work is complete.
@brief Called when work is complete .
static void ADUC_Workflow_WorkCompletionCallback(const void* workCompletionToken, ADUC_Result result)
{
    ADUC_MethodCall_Data* methodCallData = (ADUC_MethodCall_Data*)workCompletionToken;
    ADUC_WorkflowData* workflowData = methodCallData->WorkflowData;
    if (AducResultCodeIndicatesInProgress(result.ResultCode))
    {
        Log_Error("WorkComplete received InProgress result code - should not happen!");
        goto done;
    }
    const ADUC_WorkflowHandlerMapEntry* entry = GetWorkflowHandlerMapEntryForAction(workflowData->CurrentAction);
    if (entry == NULL)
    {
        Log_Error("Invalid UpdateAction %u -- ignoring", workflowData->CurrentAction);
        goto done;
    }
    if (entry->Action == ADUCITF_UpdateAction_Cancel)
    {
        Log_Error("Cancel received in completion callback - should not happen!");
        goto done;
    }
    Log_Info(
        "Action '%s' complete. Result: %d, %d",
        ADUCITF_UpdateActionToString(entry->Action),
        result.ResultCode,
        result.ExtendedResultCode);
    entry->OperationCompleteFunc(methodCallData, result);
    if (IsAducResultCodeSuccess(result.ResultCode))
    {
        const ADUCITF_State nextUpdateState = entry->NextState;
        Log_Info(
            "WorkCompletionCallback: %s succeeded. Going to state %s",
            ADUCITF_UpdateActionToString(entry->Action),
            ADUCITF_StateToString(nextUpdateState));
        ADUC_SetUpdateState(workflowData, nextUpdateState);
    }
    else
    {
        if (workflowData->OperationCancelled)
        {
             We are now at the completion of the operation that was cancelled and will just return to Idle state,
             Ignore the result of the operation, which most likely is cancelled, e.g. ADUC_DownloadResult_Cancelled.
            Log_Error("Operation cancelled - returning to Idle state");
            const ADUC_Result result = { .ResultCode = ADUC_IdleResult_Success };
            ADUC_SetUpdateStateWithResult(workflowData, ADUCITF_State_Idle, result);
        }
        else
        {
             Operation failed.
             Report back the result and set state to "Failed".
             It's expected that the service will call us again with a "Cancel" action,
             to indicate that it's received the operation result and state, at which time
             we'll return back to idle state.
            Log_Error(
                "%s failed. error %d, %d - Expecting service to send Cancel action",
                ADUCITF_UpdateActionToString(entry->Action),
                result.ResultCode,
                result.ExtendedResultCode);
            ADUC_SetUpdateStateWithResult(workflowData, ADUCITF_State_Failed, result);
        }
    }
done:
     Operation is now complete.
    workflowData->OperationInProgress = false;
    workflowData->OperationCancelled = false;
    free(methodCallData);
}
static void ADUC_Workflow_WorkCompletionCallback ( const void * workCompletionToken , ADUC_Result result ) { ADUC_MethodCall_Data * methodCallData = ( ADUC_MethodCall_Data * ) workCompletionToken ; ADUC_WorkflowData * workflowData = methodCallData -> WorkflowData ; if ( AducResultCodeIndicatesInProgress ( result . ResultCode ) ) { Log_Error ( " " ) ; goto done ; } const ADUC_WorkflowHandlerMapEntry * entry = GetWorkflowHandlerMapEntryForAction ( workflowData -> CurrentAction ) ; if ( entry == NULL ) { Log_Error ( " " , workflowData -> CurrentAction ) ; goto done ; } if ( entry -> Action == ADUCITF_UpdateAction_Cancel ) { Log_Error ( " " ) ; goto done ; } Log_Info ( " " , ADUCITF_UpdateActionToString ( entry -> Action ) , result . ResultCode , result . ExtendedResultCode ) ; entry -> OperationCompleteFunc ( methodCallData , result ) ; if ( IsAducResultCodeSuccess ( result . ResultCode ) ) { const ADUCITF_State nextUpdateState = entry -> NextState ; Log_Info ( " " , ADUCITF_UpdateActionToString ( entry -> Action ) , ADUCITF_StateToString ( nextUpdateState ) ) ; ADUC_SetUpdateState ( workflowData , nextUpdateState ) ; } else { if ( workflowData -> OperationCancelled ) { Log_Error ( " " ) ; const ADUC_Result result = { . ResultCode = ADUC_IdleResult_Success } ; ADUC_SetUpdateStateWithResult ( workflowData , ADUCITF_State_Idle , result ) ; } else { Log_Error ( " " , ADUCITF_UpdateActionToString ( entry -> Action ) , result . ResultCode , result . ExtendedResultCode ) ; ADUC_SetUpdateStateWithResult ( workflowData , ADUCITF_State_Failed , result ) ; } } done : workflowData -> OperationInProgress = false ; workflowData -> OperationCancelled = false ; free ( methodCallData ) ; }
@brief Called when work is complete.
@brief Called when work is complete .
// We own these objects, so no issue making them non-const. // NOLINTNEXTLINE(misc-redundant-expression) // Operation succeeded -- go to next state. // Operation (e.g. Download) failed or was cancelled - both are considered AducResult failure codes. // Operation cancelled. // // We are now at the completion of the operation that was cancelled and will just return to Idle state, // Ignore the result of the operation, which most likely is cancelled, e.g. ADUC_DownloadResult_Cancelled. // Operation failed. // // Report back the result and set state to "Failed". // It's expected that the service will call us again with a "Cancel" action, // to indicate that it's received the operation result and state, at which time // we'll return back to idle state. // Operation is now complete.