Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 20 Next »

Brief introduction

Example of scenario with a deployed instance with two elements:

  • user call undeploy command
  • first instance element success with UNDEPLOYED state
  • second instance element fail with DEPLOYED state
  • user call undeploy command again
  • first instance element does not know that the element is already UNDEPLOYED

Add support for the participant to understand what was the last state.

Allowed state from the participant perspective

Action

state

stChResult

Description

Prime

PRIMED

NO_ERROR

Prime is completed

COMMISSIONED

FAILED

Prime is failed

Deprime

COMMISSIONED

NO_ERROR

Deprime is completed

DEPRIMED

FAILED

Deprime is failed

Action

deployState

lockState

stChResult

Description

Deploy

DEPLOYED


NO_ERROR

Deploy is completed

UNDEPLOYED


FAILED

Deploy is failed

Undeploy

UNDEPLOYED


NO_ERROR

Undeploy is completed

DEPLOYED


FAILED

Undeploy is failed

Lock


LOCKED

NO_ERROR

Lock is completed


UNLOCKED

FAILED

Lock is failed

Unlock


UNLOCKED

NO_ERROR

Unlock is completed


LOCKED

FAILED

Unlock is failed

Update

DEPLOYED


NO_ERROR

Update is completed

DEPLOYED


FAILED

Update is failed

Migrate

DEPLOYED


NO_ERROR

Migrate is completed

DEPLOYED


FAILED

Migrate is failed

Delete

DELETED


NO_ERROR

Delete is completed

UNDEPLOYED


FAILED

Delete is failed

Additional comments

It is important to make distinction between the state of the instance/element in the flow, and the state of the application involved. A deployed element means that a participant has completed a deploy action, and should not be confused with a deployed application.

There are scenarios where it make sense when a process is failed, all elements should repeat the action, but in other scenarios it could be different, it depends on the context. Anyway, a participant could implement idempotent operations.  

The responsibility to know what it needs to be done is delegated to the participant.

When a participant cannot implement idempotent operations, in order to cover the scenario with failed process with more than one element involved, it has to know what was the previous state.

Solutions

A simple solution from participant side is that it can use "outProperties" to save information related to the deployment process.

"outProperties" is controlled by the participant side, and saved into ACM-r Db by status message (by sendAcElementInfo method). Each participant replica will be synchronized as well.

The examples below are suggestions.

  • Below a simple example:
    @Override
    public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {

        if ("DEPLOYED".equals(instanceElement.outProperties().get("state"))) {
            // deploy process already done
            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Already Deployed");
            return;
        }
         
        // deployment process
        .......................................
        .......................................
        // end of the deployment process
        
        if (isDeploySuccess()) {
            instanceElement.outProperties().put("state", "DEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());
 
            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
        } else {
            instanceElement.outProperties().put("state", "UNDEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());
 
            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!");
        } 
    }


    @Override
    public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {

        if ("DEPLOYED".equals(instanceElement.outProperties().get("state"))) {
            // undeploy process already done

            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Already Undeployed");
            return;
        }

        // undeployment process
        .......................................
        .......................................
        // end of the undeployment process        
        
        if (isUndeploySuccess()) {
             instanceElement.outProperties().put("state", "UNDEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());

            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed");
        } else {
            instanceElement.outProperties().put("state", "DEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());

            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!");
        }
    }


  • Below other suggestion when a process is failed, all elements can repeat the action and do some clean up
    @Override
    public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {

        var state = instanceElement.outProperties().get("state");
        if ("DEPLOYED".equals(state)) {
            // clean up deployment
        
        } else if ("DEPLOYING".equals(state) || "UNDEPLOYING".equals(state)) {
            // check and clean up

        }

        // deployment process
        instanceElement.outProperties().put("state", "DEPLOYING");
        intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties()); 
        
        .......................................
        .......................................
        .......................................
        // end of the deployment process        
        
         if (isDeploySuccess()) {
            instanceElement.outProperties().put("state", "DEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());
 
            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
        } else {
            instanceElement.outProperties().put("state", "UNDEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());
 
            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!");
        } 
     }


    @Override
    public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {

         var state = instanceElement.outProperties().get("state");
        if ("UNDEPLOYED".equals(state)) {
            // clean up undeployment
        
        } else if ("DEPLOYING".equals(state) || "UNDEPLOYING".equals(state)) {
            // check and clean up

        }
 
        // undeployment process
 
        instanceElement.outProperties().put("state", "UNDEPLOYING");
        intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties()); 

        .......................................
        .......................................
        .......................................
        .......................................
        // end of the undeployment process        
        
         if (isUndeploySuccess()) {
            instanceElement.outProperties().put("state", "UNDEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());

            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, "Undeployed");
        } else {
            instanceElement.outProperties().put("state", "DEPLOYED");
            intermediaryApi.sendAcElementInfo(instanceElement.instanceId(), instanceElement.elementId(), null, null, instanceElement.outProperties());

            intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(), instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Undeploy failed!");
        }
    }

Final consideration: In all suggestions before we have used labels as "DEPLOY", "UNDEPLOY", "DEPLOYING", "UNDEPLOYING" but the developer can change them as better suit with the context of the participant.

  • No labels