Scheduler and Vault Failed to record transaction

Viewed 15

I'm quite new with Corda.

I want to do a Scheduler, is like a Todo List that check if the Task is assigned every 30 seconds. I use the Java Template without any specific configuration, the database is H2 and the Corda version is 4.9

The State class extend ContractState, LinearState and SchedulableState

ToDoState

@BelongsToContract(ToDoContract.class)
public class TodoState  implements ContractState, LinearState, SchedulableState {


    private final Instant deadlineReminder;

    public Party getAssignedBy() {
        return assignedBy;
    }

    private final Party assignedBy;

    public Party getAssignedTo() {
        return assignedTo;
    }

    private final Party assignedTo;

    public String getTaskDescription() {
        return taskDescription;
    }

    private final String taskDescription;
    private UniqueIdentifier linearId;

    public TodoState(Party assignedBy, Party assignedTo, String taskDescription) {
        this.assignedBy = assignedBy;
        this.assignedTo = assignedTo;
        this.taskDescription = taskDescription;
        this.linearId = new UniqueIdentifier();
        this.deadlineReminder = Instant.now().plusSeconds(30);
    }
    @ConstructorForDeserialization
    public TodoState(Party assignedBy, Party assignedTo, String taskDescription, UniqueIdentifier linearId, Instant deadlineReminder) {
        this.assignedBy = assignedBy;
        this.assignedTo = assignedTo;
        this.taskDescription = taskDescription;
        this.linearId = linearId;
        this.deadlineReminder = deadlineReminder;
    }

    public TodoState assign(Party assignedTo) {
        return new TodoState(assignedBy, assignedTo, taskDescription, linearId, deadlineReminder);
    }
    @NotNull
    @Override
    public List<AbstractParty> getParticipants() {
        return Arrays.asList(assignedBy, assignedTo);
    }

    @NotNull
    @Override
    public UniqueIdentifier getLinearId() {
        return linearId;
    }


    @Nullable
    @Override
    public ScheduledActivity nextScheduledActivity(@NotNull StateRef thisStateRef, @NotNull FlowLogicRefFactory flowLogicRefFactory) {
        System.out.println("nextScheduledActivity invoked");
        System.out.println("StateRef TX is " + thisStateRef.getTxhash());
        final ScheduledActivity scheduledActivity = new ScheduledActivity(flowLogicRefFactory.create(
                "com.template.flows.AlarmFlow", thisStateRef
        ), deadlineReminder);
        System.out.println("Passed");
        return scheduledActivity;
    }
}

The Flow

public class CreateToDoFlow {

    @InitiatingFlow
    @StartableByRPC
    public static class CreateTodoFlowInitiator extends FlowLogic<Void> {
        private final String taskDescription;
        private Party me;

        public CreateTodoFlowInitiator(String task) {
            this.taskDescription = task;
        }


        @Override
        @Suspendable
        public Void call() throws FlowException {
            this.me = getOurIdentity();
            final Party notary = getServiceHub().getNetworkMapCache().getNotary(CordaX500Name.parse("O=Notary,L=London,C=GB"));
            final TodoState output = new TodoState(this.me, this.me, this.taskDescription);
            final TransactionBuilder builder = new TransactionBuilder(notary);
            builder.addOutputState(output);
            builder.addCommand(new Command.CreateToDoCommand(), me.getOwningKey());
            builder.verify(getServiceHub());
            final SignedTransaction ptx = getServiceHub().signInitialTransaction(builder);

            subFlow(new FinalityFlow(ptx, Collections.<FlowSession>emptySet()));
            System.out.println("1");
            return null;
        }
    }
}

And the AlarmFlow called from the Scheduler, where, i guess the error come.

AlarmFlow

public class AlarmFlow {

    @InitiatingFlow
    @SchedulableFlow
    public static class AlarmFlowInitiator extends FlowLogic<Void> {


        private StateRef stateRef;

        //public constructor
        public AlarmFlowInitiator(StateRef stateRef) {
            this.stateRef = stateRef;
        }

        @Override
        @Suspendable
        public Void call() throws FlowException {
            ServiceHub sb = getServiceHub();
            StateAndRef<TodoState> todoStateAndRef = sb.toStateAndRef(stateRef);
            TodoState todo = todoStateAndRef.getState().getData();
            sb.getVaultService().addNoteToTransaction(
                    stateRef.getTxhash(), "Reminder made: " + Instant.now()
            );
            System.out.println("DeadLine is coming up for task: " + todo.getTaskDescription());
            return null;
        }
    }
}

when i execute the flow

flow start CreateTodoFlow task: "Pay bill"

i get the following error

[ERROR] 23:48:19+0200 [Node thread-1] vault.NodeVaultService. - Failed to record transaction states locally - the node could be now in an inconsistent state with other peers and/or the notary - hospitalising the flow  {actor_id=internalShell, actor_owning_identity=O=PartyA, L=London, C=GB, actor_store_id=NODE_CONFIG, fiber-id=10000001, flow-id=5eb282b3-4b47-459d-917d-06ea0de16e6f, invocation_id=aadb5b6a-4716-4875-a18e-78a351592365, invocation_timestamp=2022-09-19T21:48:19.052Z, origin=internalShell, session_id=b78e7e1d-b91f-4c40-b42e-468e7b5f4fb0, session_timestamp=2022-09-19T21:48:18.782Z, thread-id=139, tx_id=1BBDFF4EC549457D1C8D60E30041AE97436D44778675BEB2C78E737DBFFFE124}

seems that the vault fail when is called in the Scheduled Activity method

Thanks in advance for your help

1 Answers

I have found the solution: The scheduler call the AlarmFlow Class and the class is embebbed on the AlarmFlow class like that:


public class AlarmFlow {

    @InitiatingFlow
    @SchedulableFlow
    public static class AlarmFlowInitiator extends FlowLogic<Void> {


        private StateRef stateRef;

        //public constructor
        public AlarmFlowInitiator(StateRef stateRef) {
            this.stateRef = stateRef;
        }

        @Override
        @Suspendable
        public Void call() throws FlowException {
            ServiceHub sb = getServiceHub();
            StateAndRef<TodoState> todoStateAndRef = sb.toStateAndRef(stateRef);
            TodoState todo = todoStateAndRef.getState().getData();
            sb.getVaultService().addNoteToTransaction(
                    stateRef.getTxhash(), "Reminder made: " + Instant.now()
            );
            System.out.println("DeadLine is coming up for task: " + todo.getTaskDescription());
            return null;
        }
    }
}

If i extract the AlarmFlowInitiator class out side like that


@InitiatingFlow
@SchedulableFlow
public class AlarmFlow extends FlowLogic<Void>{

        private StateRef stateRef;

        //public constructor
        public AlarmFlow(StateRef stateRef) {
            this.stateRef = stateRef;
        }

        @Override
        @Suspendable
        public Void call() throws FlowException {
            ServiceHub sb = getServiceHub();
            StateAndRef<TodoState> todoStateAndRef = sb.toStateAndRef(stateRef);
            TodoState todo = todoStateAndRef.getState().getData();
            sb.getVaultService().addNoteToTransaction(
                    stateRef.getTxhash(), "Reminder made: " + Instant.now()
            );
            System.out.println("DeadLine is coming up for task: " + todo.getTaskDescription());
            return null;
        }
}

the Scheduler work properly

Related