@Override
    public void recordStateMachineFinished(StateMachineInstance machineInstance, ProcessContext context) {
        if (machineInstance != null) {
            try {
                // save to db
                Map<String, Object> endParams = machineInstance.getEndParams();
                if (endParams != null) {
                    endParams.remove(DomainConstants.VAR_NAME_GLOBAL_TX);
                }

                // if success, clear exception
                if (ExecutionStatus.SU.equals(machineInstance.getStatus()) && machineInstance.getException() != null) {
                    machineInstance.setException(null);
                }

                machineInstance.setSerializedEndParams(paramsSerializer.serialize(machineInstance.getEndParams()));
                machineInstance.setSerializedException(exceptionSerializer.serialize(machineInstance.getException()));
                int effect = executeUpdate(stateLogStoreSqls.getRecordStateMachineFinishedSql(dbType),
                        STATE_MACHINE_INSTANCE_TO_STATEMENT_FOR_UPDATE, machineInstance);
                if (effect < 1) {
                    LOGGER.warn("StateMachineInstance[{}] is recovery by server, skip recordStateMachineFinished.", machineInstance.getId());
                } else {
                    StateMachineConfig stateMachineConfig = (StateMachineConfig) context.getVariable(
                            DomainConstants.VAR_NAME_STATEMACHINE_CONFIG);
                    if (EngineUtils.isTimeout(machineInstance.getGmtUpdated(), stateMachineConfig.getTransOperationTimeout())) {
                        LOGGER.warn("StateMachineInstance[{}] is execution timeout, skip report transaction finished to server.", machineInstance.getId());
                    } else if (StringUtils.isEmpty(machineInstance.getParentId())) {
                        //if parentId is not null, machineInstance is a SubStateMachine, do not report global transaction.
                        reportTransactionFinished(machineInstance, context);
                    }
                }
            } finally {
                RootContext.unbind();
                RootContext.unbindBranchType();
            }
        }
    }
@Test
    public void testRecordStateMachineFinished() {
        DbAndReportTcStateLogStore dbAndReportTcStateLogStore = new DbAndReportTcStateLogStore();
        StateMachineInstanceImpl stateMachineInstance = new StateMachineInstanceImpl();
        ProcessContextImpl context = new ProcessContextImpl();
        context.setVariable(DomainConstants.VAR_NAME_STATEMACHINE_CONFIG,  new DbStateMachineConfig());
        Assertions.assertThrows(NullPointerException.class,
                () -> dbAndReportTcStateLogStore.recordStateMachineFinished(stateMachineInstance, context));
    }