All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.statusmachina.core.api.Transition Maven / Gradle / Ivy

Go to download

Core functionality for Status Machina, a small, simple and pragmatic state machine for resilient microservices orchestration.

The newest version!
/*
 *  Copyright 2019 <---> Present Status Machina Contributors (https://github.com/entzik/status-machina/graphs/contributors)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  This software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
 *  CONDITIONS OF ANY KIND, either express or implied. See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 */

package io.statusmachina.core.api;

import java.util.Optional;
import java.util.function.Supplier;

/**
 * Specifies if and how a state machine can transition from one state to another. It matches an edge in the
 * state machine diagram graph.
 * 

* An action can be specified to be executed as part of the transition. If the action throws an exception, the transition * will not be cancelled and the machine will be put in an error state. *

* The transition action can interact with external systems and can mutate the machine's context. *

* transitions can be automatic ( STP: Straight Through Processing ) or event triggered * * @param the state type * @param the event type */ public class Transition { public static final Supplier EVENT_CARDINALITY_OF_ONE_SUPPLIER = () -> 1L; public static final Optional> NO_POST_ACTION = Optional.empty(); public static final Optional> NO_ACTION = Optional.empty(); public static final Optional NO_GUARD = Optional.empty(); private final S from; private final S to; private final Optional event; private final Optional guard; private final Optional> action; private final Optional> postAction; private final Supplier eventCardinalitySupplier; /** * Configure a transition so that if the machine is in a specified current state ("from") and receives the specified * event ("event"), it will move to the specified target state ("to") and execute the specified action in the process. *

* The post action is executed after the transition has completed. if a specific service provider executes the * transition in a transaction, then the post action must be executed after the the transaction has completed and * only if it has completed successfully. *

* Unlike the a transition action, the post transition action is not allowed to mutate the state machine's context. * * @param from the current state * @param to the target state * @param event the event that triggers the transition * @param action the action to be executed during the transition * @param postAction the action to be executed after the transition has completed * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition event(S from, S to, E event, TransitionAction action, TransitionPostAction postAction) { return new Transition<>(from, to, event, action, postAction); } /** * Configure a transition so that if the machine is in a specified current state ("from") and receives the specified * event ("event"), it will move to the specified target state ("to") and execute the specified action in the process. * * @param from the current state * @param to the target state * @param event the event that triggers the transition * @param action the action to be executed * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition event(S from, S to, E event, TransitionAction action) { return new Transition<>(from, to, event, action); } /** * Configure a transition so that if the machine is in a specified current state ("from") and receives the specified * event ("event"), it will move to the specified target state ("to"). * * @param from the current state * @param to the target state * @param event the event that triggers the transition * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition event(S from, S to, E event) { return new Transition<>(from, to, event); } /** * Configure a transition so that if the machine is in a specified current state ("from"), it will move to the * specified target state ("to") after receiving the number of events ("event") as returned by the "eventCardinalitySupplier". * The specified post action will be executed after the transition has completed. * * @param from the current state * @param to the target state * @param event the event that triggers the transition * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition event(S from, S to, E event, TransitionAction action, Supplier eventCardinalitySupplier) { return new Transition<>(from, to, event, action, eventCardinalitySupplier); } /** * Configure a transition so that if the machine is in a specified current state ("from"), it will move to the * specified target state ("to") after receiving the number of events ("event") as returned by the "eventCardinalitySupplier". * The specified post action will be executed after the transition has completed. * * @param from the current state * @param to the target state * @param event the event that triggers the transition * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition event(S from, S to, E event, TransitionAction action, TransitionPostAction postAction, Supplier eventCardinalitySupplier) { return new Transition<>(from, to, event, action, postAction, eventCardinalitySupplier); } /** * Configure a transition so that if the machine is in a specified current state ("from") it will automatically * move to the specified target state ("to") and execute the specified action in the process. *

* The post action is executed after the transition has completed. If a specific service provider executes the * transition in a transaction, then the post action must be executed after the the transaction has completed and * only if it has completed successfully. *

* Unlike the a transition action, the post transition action is not allowed to mutate the state machine's context * * @param from the current state * @param to the target state * @param action the action to be executed * @param transitionGuard the guard that will decide if the transition can be executed or not * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition stp(S from, S to, TransitionAction action, TransitionPostAction postAction, TransitionGuard transitionGuard) { return new Transition<>(from, to, action, postAction, transitionGuard); } /** * Configure a transition so that if the machine is in a specified current state ("from") it will automatically * move to the specified target state ("to") and execute the specified action in the process. *

* The post action is executed after the transition has completed. If a specific service provider executes the * transition in a transaction, then the post action must be executed after the the transaction has completed and * only if it has completed successfully. *

* Unlike the a transition action, the post transition action is not allowed to mutate the state machine's context * * @param from the current state * @param to the target state * @param action the action to be executed * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition stp(S from, S to, TransitionAction action, TransitionPostAction postAction) { return new Transition<>(from, to, action, postAction); } /** * Configure a transition so that if the machine is in a specified current state ("from") it will automatically * move to the specified target state ("to") and execute the specified action in the process. * * @param from the current state * @param to the target state * @param action the action to be executed * @param transitionGuard the guard that will decide if the transition can be executed or not * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition stp(S from, S to, TransitionAction action, TransitionGuard transitionGuard) { return new Transition<>(from, to, action, transitionGuard); } /** * Configure a transition so that if the machine is in a specified current state ("from") it will automatically * move to the specified target state ("to") and execute the specified action in the process. * * @param from the current state * @param to the target state * @param action the action to be executed * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition stp(S from, S to, TransitionAction action) { return new Transition<>(from, to, action); } /** * Configure a transition so that if the machine is in a specified current state ("from") it will automatically * move to the specified target state ("to"). * * @param from the current state * @param to the target state * @param transitionGuard the guard that will decide if the transition can be executed or not * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition stp(S from, S to, TransitionGuard transitionGuard) { return new Transition<>(from, to, transitionGuard); } /** * Configure a transition so that if the machine is in a specified current state ("from") it will automatically * move to the specified target state ("to"). * * @param from the current state * @param to the target state * @param the state type * @param the event type * @return a {@link Transition} instance */ public static Transition stp(S from, S to) { return new Transition<>(from, to); } private Transition(S from, S to, E event, TransitionAction action, TransitionPostAction postAction) { this(from, to, event, action, postAction, () -> 1L); } private Transition(S from, S to, E event, TransitionAction action, TransitionPostAction postAction, Supplier eventCardinalitySupplier) { this(from, to, Optional.of(event), NO_GUARD, Optional.of(action), Optional.of(postAction), eventCardinalitySupplier); } private Transition(S from, S to, E event, TransitionAction action, Supplier eventCardinalitySupplier) { this(from, to, Optional.of(event), NO_GUARD, Optional.of(action), NO_POST_ACTION, eventCardinalitySupplier); } private Transition(S from, S to, E event, TransitionAction action) { this(from, to, Optional.of(event), NO_GUARD, Optional.of(action), NO_POST_ACTION, EVENT_CARDINALITY_OF_ONE_SUPPLIER); } private Transition(S from, S to, E event) { this(from, to, Optional.of(event), NO_GUARD, NO_ACTION, NO_POST_ACTION, EVENT_CARDINALITY_OF_ONE_SUPPLIER); } private Transition(S from, S to, TransitionAction action, TransitionPostAction postAction) { this(from, to, Optional.empty(), NO_GUARD, Optional.of(action), Optional.of(postAction), EVENT_CARDINALITY_OF_ONE_SUPPLIER); } private Transition(S from, S to, TransitionAction action, TransitionPostAction postAction, TransitionGuard transitionGuard) { this(from, to, Optional.empty(), Optional.of(transitionGuard), Optional.of(action), Optional.of(postAction), EVENT_CARDINALITY_OF_ONE_SUPPLIER); } private Transition(S from, S to, TransitionAction action) { this(from, to, Optional.empty(), NO_GUARD, Optional.of(action), NO_POST_ACTION, EVENT_CARDINALITY_OF_ONE_SUPPLIER); } private Transition(S from, S to, TransitionAction action, TransitionGuard transitionGuard) { this(from, to, Optional.empty(), Optional.of(transitionGuard), Optional.of(action), NO_POST_ACTION, EVENT_CARDINALITY_OF_ONE_SUPPLIER); } private Transition(S from, S to) { this(from, to, Optional.empty(), NO_GUARD, NO_ACTION, NO_POST_ACTION, EVENT_CARDINALITY_OF_ONE_SUPPLIER); } private Transition(S from, S to, TransitionGuard transitionGuard) { this(from, to, Optional.empty(), Optional.of(transitionGuard), NO_ACTION, NO_POST_ACTION, EVENT_CARDINALITY_OF_ONE_SUPPLIER); } public Transition(S from, S to, Optional event, Optional guard, Optional> action, Optional> postAction, Supplier eventCardinalitySupplier) { this.from = from; this.to = to; this.event = event; this.guard = guard; this.action = action; this.postAction = postAction; this.eventCardinalitySupplier = eventCardinalitySupplier; } /** * return the state in which the state machine needs to be in order for this transition to activate (if all other * conditions are fulfilled) * * @return the state */ public S getFrom() { return from; } /** * return the state in which this transition will end up should this transition activate and cbe carried over successfully * * @return the target state */ public S getTo() { return to; } /** * returns the event that needs to be sent to the state machine in order to trigger this transition (should all other * conditions be fulfilled) * * @return the event */ public Optional getEvent() { return event; } /** * @return true if this is an STP action, false otherwise */ public boolean isSTP() { return !event.isPresent(); } /** * @return the action to be executed as part of the transition, should one be configured */ public Optional> getAction() { return action; } /** * @return an action to be executed after a the transition has completed and all state and context changes have been * commited to underlying storage, along with change of any transactional service the action may have invoked. */ public Optional> getPostAction() { return postAction; } public Optional getGuard() { return guard; } public long getEventCardinality() { return eventCardinalitySupplier.get(); } }