# Account Microservice: Worker The `account-worker` application is a event stream processing application that listens for `Account` domain events as AMQP messages. The domain events that are generated by the `account-web` application are processed in this module. The worker is responsible for durable transaction processing for work flows that are required to coordinate asynchronously with applications residing in other domain contexts. The worker is also responsible for automatically remediating state changes in a distributed transactions that encountered a partial failure. The most important goal of the worker module is to keep the state of the system consistent through automated means — to guarantee eventual consistency. # Usage The `account-worker` is a _Spring Cloud Stream_ application that drives the state of the `Account` domain resource. The application is completely stateless because it uses hypermedia to drive the state of the application. At the heart of the `account-worker` is a configurable state machine that describes how domain events trigger state transitions on an `Account` resource. The code snippet below describes a single state machine transition. ```java // Describe state machine transitions for accounts transitions.withExternal() .source(AccountStatus.ACCOUNT_CREATED) .target(AccountStatus.ACCOUNT_PENDING) .event(AccountEventType.ACCOUNT_CREATED) .action(createAccount()) ``` The `/src/main/java/demo/config/StateMachineConfig.java` class configures a state machine using the _Spring Statemachine_ project. The snippet above describes the first transition of a state machine for the `Account` resource. Here we see that the source state is `ACCOUNT_CREATED` and the target state is `ACCOUNT_PENDING`. We also see that the state transition is triggered by an `ACCOUNT_CREATED` event. Finally, we see that an action method named `createAccount` is mapped to this state transition. Each time an `AccountEvent` is received by the stream listener in the `AccountEventStream` class, a state machine is replicated by applying the ordered history of previous account events—we call this history the _Event Log_. Since each `AccountEvent` provides hypermedia links for retrieving the context of the attached `Account` resource, we can traverse to an account's event log and use a technique called _Event Sourcing_ to aggregate the current state of the `Account`. ### Functions As we saw earlier in the configuration of state machine transitions, an action can be mapped to a function. In the `StateMachineConfig` class we'll find multiple bean definitions that correspond to transition actions. For example, earlier we saw the method triggered for a transition triggered by an `ACCOUNT_CREATED` event that mapped to an action named `createAccount`. Let's see the definition of that method. ```java @Bean public Action createAccount() { return context -> applyEvent(context, new CreateAccountFunction(context)); } ``` The `createAccount` method returns an executable action that passes the state context to a method named `applyEvent`. The `applyEvent` method is a step function that replicates the current state of an `Account` resource. Since a state machine is replicated in-memory each time an `AccountEvent` is processed, we'll need to ensure that actions are not executed against the same resource multiple times during replication. The `applyEvent` method will only execute the supplied function—in this case `CreateAccountFunction`—if the state machine is finished replicating. When the state machine is finished replicating, it will attempt to apply the `AccountEvent` for this context to an action mapped function. We can find each of the function classes for state transitions inside the `/src/main/java/demo/function` package. ```bash . ├── /src/main/java/demo/function ├── AccountFunction.java ├── ActivateAccountFunction.java ├── ArchiveAccountFunction.java ├── ConfirmAccountFunction.java ├── CreateAccountFunction.java ├── SuspendAccountFunction.java ├── UnarchiveAccountFunction.java └── UnsuspendAccountFunction.java ``` The `AccountFunction` abstract class is extended by each of the other classes inside of the `function` package. Since we're using hypermedia to drive the state of the application, each function is immutable and stateless. In this reference application we can either define the task inside an `AccountFunction` class, or we can use a `Consumer`, which is a Java 8 lambda expression, to apply an `AccountEvent` to an `Account` resource. Let's go back to the `StateMachineConfig` class and look at an example of an action mapped function that uses a lambda expression. ```java @Bean public Action confirmAccount() { return context -> { // Map the account action to a Java 8 lambda function ConfirmAccountFunction accountFunction; accountFunction = new ConfirmAccountFunction(context, event -> { // Get the account resource for the event Traverson traverson = new Traverson( URI.create(event.getLink("account").getHref()), MediaTypes.HAL_JSON ); // Follow the command resource to activate the account Account account = traverson.follow("commands") .follow("activate") .toEntity(Account.class) .getBody(); }); applyEvent(context, accountFunction); }; } ``` The snippet above shows the definition of the `confirmAccount` action. Here we see a stateless function that uses a `Traverson` client to follow hypermedia links of the `AccountEvent` resource in a workflow that activates the `Account`. Since the embedded hypermedia links provide the full context of an `AccountEvent` resource, we can implement this function from anywhere—_even as a serverless function_! #### Serverless Functions A _serverless_ function is a unit of cloud deployment in a PaaS (Platform-as-a-Service) that is composed of a stateless function. Serverless was first popularized by _Amazon Web Services_ as a part of their _AWS Lambda_ compute platform. Serverless—which is also referred to as FaaS (Function-as-a-Service)—allows you to deploy code as functions without needing to setup or manage application servers or containers. With a serverless function, a cloud platform will take care of when and where a function is scheduled and executed. A cloud platform is also opinionated about the compute resources required to execute and/or scale a function. In this reference architecture we have two units of deployment per microservice, a web and worker application. Each of the workloads for the deployments are designed to operate in an immutable Linux container. Since the state machine actions that are mapped to the `AccountFunction` classes in the `account-worker` application are both immutable and stateless, we can choose to instead map each of these actions to a serverless function.