Fire events and inquiry
This section describes how to fire sensory events into a Baker process, and how to query information from a running Baker process.
Note
For the Java API most methods return a CompletableFuture<A>, in the Scala API they return Future<A>. The Kotlin
API makes use of suspending functions, and thus does not wrap the return type. To keep things readable,
the descriptions in this section reason from Java's perspective.
Fire sensory events
To trigger a Baker process you'll need to fire a sensory event. After firing an event, you may want to continue your asynchronous computation at one of the following moments:
- Right after the event was received, but before any interactions are executed.
- After all interactions have completed. At this point the process is either finished, or requires other sensory events to continue.
- As soon one of the interactions fires a specific event.
To this end, the Baker interface exposes one method to fire an event and 2 methods to wait. We'll discuss each of those in more detail.
Fire sensory event and wait for acknowledgement of it's reception.
This method completes right after the event was received, but before any interactions are executed.
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
import com.ing.baker.runtime.javadsl.EventInstance;
import examples.java.events.OrderPlaced;
public class FireSensoryEventAndAwaitReceived {
private final Baker baker;
public FireSensoryEventAndAwaitReceived(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId, OrderPlaced orderPlaced) {
var eventInstance = EventInstance.from(orderPlaced);
var sensoryEventStatus = baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, eventInstance).join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.javadsl.EventInstance
import com.ing.baker.runtime.kotlindsl.Baker
import examples.kotlin.events.OrderPlaced
class FireSensoryEventAndAwaitReceived(private val baker: Baker) {
suspend fun example(recipeInstanceId: String, orderPlaced: OrderPlaced) {
val orderPlacedEvent = EventInstance.from(orderPlaced)
val sensoryEventStatus = baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, orderPlacedEvent)
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.{Baker, EventInstance}
import examples.scala.events.OrderPlaced
class FireSensoryEventAndAwaitReceived(val baker: Baker) {
def example(recipeInstanceId: String, orderPlaced: OrderPlaced): Unit = {
val eventInstance = EventInstance.unsafeFrom(orderPlaced)
val sensoryEventStatus = baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, eventInstance)
}
}
Wait for completion
awaitCompleted completes when additional sensory events are required to continue
the process, or when the process has finished.
Note
Make sure to set a timeout smaller than the requestTimeout of your httpClient. Otherwise, you will see awaitCompleted() timeout prematurely.
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
import com.ing.baker.runtime.javadsl.EventInstance;
import examples.java.events.OrderPlaced;
import java.time.Duration;
public class AwaitCompleted {
private final Baker baker;
public AwaitCompleted(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId, OrderPlaced orderPlaced) {
var eventInstance = EventInstance.from(orderPlaced);
baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, eventInstance).join();
baker.awaitCompleted(recipeInstanceId, Duration.ofSeconds(5)).join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.javadsl.EventInstance
import com.ing.baker.runtime.kotlindsl.Baker
import examples.kotlin.events.OrderPlaced
import kotlin.time.Duration.Companion.seconds
class AwaitCompleted(private val baker: Baker) {
suspend fun example(recipeInstanceId: String, orderPlaced: OrderPlaced) {
val orderPlacedEvent = EventInstance.from(orderPlaced)
baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, orderPlacedEvent)
baker.awaitCompleted(recipeInstanceId, timeout = 5.seconds)
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.{Baker, EventInstance}
import examples.scala.events.OrderPlaced
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.DurationInt
class AwaitCompleted(val baker: Baker) {
def example(recipeInstanceId: String, orderPlaced: OrderPlaced): Unit = {
val eventInstance = EventInstance.unsafeFrom(orderPlaced)
for {
_ <- baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, eventInstance)
_ <- baker.awaitCompleted(recipeInstanceId, timeout = 5.seconds)
} yield ()
}
}
Wait for an event
awaitEvent completes when an event with the specified name appears in the list of fired events.
Note
Make sure to set a timeout smaller than the requestTimeout of your httpClient. Otherwise, you will see awaitEvent() timeout prematurely.
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
import com.ing.baker.runtime.javadsl.EventInstance;
import examples.java.events.OrderPlaced;
import java.time.Duration;
public class AwaitEvent {
private final Baker baker;
public AwaitEvent(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId, OrderPlaced orderPlaced) {
var eventInstance = EventInstance.from(orderPlaced);
baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, eventInstance).join();
baker.awaitEvent(recipeInstanceId, "ExpectedEvent", Duration.ofSeconds(5)).join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.javadsl.EventInstance
import com.ing.baker.runtime.kotlindsl.Baker
import examples.kotlin.events.OrderPlaced
import kotlin.time.Duration.Companion.seconds
class AwaitEvent(private val baker: Baker) {
suspend fun example(recipeInstanceId: String, orderPlaced: OrderPlaced) {
val orderPlacedEvent = EventInstance.from(orderPlaced)
baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, orderPlacedEvent)
baker.awaitEvent(recipeInstanceId, "ExpectedEvent", timeout = 5.seconds)
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.{Baker, EventInstance}
import examples.scala.events.OrderPlaced
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.DurationInt
class AwaitEvent(val baker: Baker) {
def example(recipeInstanceId: String, orderPlaced: OrderPlaced): Unit = {
val eventInstance = EventInstance.unsafeFrom(orderPlaced)
for {
_ <- baker.fireSensoryEventAndAwaitReceived(recipeInstanceId, eventInstance)
_ <- baker.awaitEvent(recipeInstanceId, "ExpectedEvent", timeout = 5.seconds)
} yield ()
}
}
Inquiry
Baker allows you to query the state of a recipe instance at any given moment. To this end, Baker exposes a couple of different methods that allow you to fetch information about events, ingredients, and interactions from a running process.
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
public class InquiryExample {
private final Baker baker;
public InquiryExample(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId) {
var ingredient = baker.getIngredient(recipeInstanceId, "orderId").join();
var ingredients = baker.getIngredients(recipeInstanceId).join();
var events = baker.getEvents(recipeInstanceId).join();
var eventNames = baker.getEventNames(recipeInstanceId).join();
var recipeInstanceState = baker.getRecipeInstanceState(recipeInstanceId).join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.kotlindsl.Baker
class InquiryExample(private val baker: Baker) {
suspend fun example(recipeInstanceId: String) {
val ingredient = baker.getIngredient(recipeInstanceId, "orderId")
val ingredients = baker.getIngredients(recipeInstanceId)
val events = baker.getEvents(recipeInstanceId)
val eventNames = baker.getEventNames(recipeInstanceId)
val recipeInstanceState = baker.getRecipeInstanceState(recipeInstanceId)
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.Baker
class InquiryExample(val baker: Baker) {
def example(recipeInstanceId: String): Unit = {
val ingredient = baker.getIngredient(recipeInstanceId, "orderId")
val ingredients = baker.getIngredients(recipeInstanceId)
val events = baker.getEvents(recipeInstanceId)
val eventNames = baker.getEventNames(recipeInstanceId)
val recipeInstanceState = baker.getRecipeInstanceState(recipeInstanceId)
}
}
Deprecated API
Deprecated
The methods described below are deprecated and will be removed in a future version. Please use the new API described above.
To trigger a Baker process you'll need to fire a sensory event. After firing an event, you may want to continue your asynchronous computation at one of four different moments:
- Right after the event was received, but before any interactions are executed.
- After all interactions have completed. At this point the process is either finished, or requires other sensory events to continue.
- You want to do something on both the previously mentioned moments.
- As soon one of the interactions fires a specific event.
To this end, the Baker interface exposes four different methods to fire events. We'll discuss each of those in more detail.
Fire event and resolve when received
This method returns a CompletableFuture<SensoryEventStatus>. It completes right after the event was received, but
before any interactions are executed. The SensoryEventStatus is an enum containing information about the outcome
of the event (Received, Completed, FiringLimitMet, etc).
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
import com.ing.baker.runtime.javadsl.EventInstance;
import examples.java.events.OrderPlaced;
public class FireEventAndResolveWhenReceived {
private final Baker baker;
public FireEventAndResolveWhenReceived(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId, OrderPlaced orderPlaced) {
var eventInstance = EventInstance.from(orderPlaced);
var sensoryEventStatus = baker.fireEventAndResolveWhenReceived(recipeInstanceId, eventInstance).join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.javadsl.EventInstance
import com.ing.baker.runtime.kotlindsl.Baker
import examples.kotlin.events.OrderPlaced
class FireEventAndResolveWhenReceived(private val baker: Baker) {
suspend fun example(recipeInstanceId: String, orderPlaced: OrderPlaced) {
val orderPlacedEvent = EventInstance.from(orderPlaced)
val sensoryEventStatus = baker.fireEventAndResolveWhenReceived(recipeInstanceId, orderPlacedEvent)
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.{Baker, EventInstance}
import examples.scala.events.OrderPlaced
class FireEventAndResolveWhenReceived(val baker: Baker) {
def example(recipeInstanceId: String, orderPlaced: OrderPlaced): Unit = {
val eventInstance = EventInstance.unsafeFrom(orderPlaced)
val sensoryEventStatus = baker.fireEventAndResolveWhenReceived(recipeInstanceId, eventInstance)
}
}
Fire event and resolve when completed
Returns a CompletableFuture<SensoryEventResult>. It completes when additional sensory events are required to continue
the process, or when the process has finished. The SensoryEventResult contains the SensoryEventStatus and a list
of all events names triggered as a result of this sensory event.
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
import com.ing.baker.runtime.javadsl.EventInstance;
import examples.java.events.OrderPlaced;
public class FireEventAndResolveWhenCompleted {
private final Baker baker;
public FireEventAndResolveWhenCompleted(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId, OrderPlaced orderPlaced) {
var eventInstance = EventInstance.from(orderPlaced);
var sensoryEventResult = baker.fireEventAndResolveWhenCompleted(recipeInstanceId, eventInstance).join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.javadsl.EventInstance
import com.ing.baker.runtime.kotlindsl.Baker
import examples.kotlin.events.OrderPlaced
class FireEventAndResolveWhenCompleted(private val baker: Baker) {
suspend fun example(recipeInstanceId: String, orderPlaced: OrderPlaced) {
val orderPlacedEvent = EventInstance.from(orderPlaced)
val sensoryEventResult = baker.fireEventAndResolveWhenCompleted(recipeInstanceId, orderPlacedEvent)
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.{Baker, EventInstance}
import examples.scala.events.OrderPlaced
class FireEventAndResolveWhenCompleted(val baker: Baker) {
def example(recipeInstanceId: String, orderPlaced: OrderPlaced): Unit = {
val eventInstance = EventInstance.unsafeFrom(orderPlaced)
val sensoryEventResult = baker.fireEventAndResolveWhenCompleted(recipeInstanceId, eventInstance)
}
}
Fire event
This method is useful if you want to do something after the event was received and after all interactions have completed.
The method returns an EventResolutions object consisting of a CompletableFuture<SensoryEventStatus> and
CompletableFuture<SensoryEventResult>. The former completes on receiving the event, the latter on completion of the
interactions.
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
import com.ing.baker.runtime.javadsl.EventInstance;
import examples.java.events.OrderPlaced;
public class FireEvent {
private final Baker baker;
public FireEvent(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId, OrderPlaced orderPlaced) {
var eventInstance = EventInstance.from(orderPlaced);
var eventResolutions = baker.fireEvent(recipeInstanceId, eventInstance);
var sensoryEventStatus = eventResolutions.getResolveWhenReceived().join();
var sensoryEventResult = eventResolutions.getResolveWhenCompleted().join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.javadsl.EventInstance
import com.ing.baker.runtime.kotlindsl.Baker
import examples.kotlin.events.OrderPlaced
class FireEvent(private val baker: Baker) {
suspend fun example(recipeInstanceId: String, orderPlaced: OrderPlaced) {
val orderPlacedEvent = EventInstance.from(orderPlaced)
val eventResolutions = baker.fireEvent(recipeInstanceId, orderPlacedEvent)
val sensoryEventStatus = eventResolutions.resolveWhenReceived.await()
val sensoryEventResult = eventResolutions.resolveWhenCompleted.await()
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.{Baker, EventInstance}
import examples.scala.events.OrderPlaced
class FireEvent(val baker: Baker) {
def example(recipeInstanceId: String, orderPlaced: OrderPlaced): Unit = {
val eventInstance = EventInstance.unsafeFrom(orderPlaced)
val eventResolutions = baker.fireEvent(recipeInstanceId, eventInstance)
val sensoryEventStatus = eventResolutions.resolveWhenReceived
val sensoryEventResult = eventResolutions.resolveWhenCompleted
}
}
Fire event and resolve on event
This method returns a CompletableFuture<SensoryEventResult>. It completes when one of the interactions fires an event
with a specified name.
package examples.java.application;
import com.ing.baker.runtime.javadsl.Baker;
import com.ing.baker.runtime.javadsl.EventInstance;
import examples.java.events.OrderPlaced;
public class FireEventAndResolveOnEvent {
private final Baker baker;
public FireEventAndResolveOnEvent(Baker baker) {
this.baker = baker;
}
public void example(String recipeInstanceId, OrderPlaced orderPlaced) {
var eventInstance = EventInstance.from(orderPlaced);
var sensoryEventResult = baker.fireEventAndResolveOnEvent(recipeInstanceId, eventInstance, "ExpectedEvent").join();
}
}
package examples.kotlin.application
import com.ing.baker.runtime.javadsl.EventInstance
import com.ing.baker.runtime.kotlindsl.Baker
import examples.kotlin.events.OrderPlaced
class FireEventAndResolveOnEvent(private val baker: Baker) {
suspend fun example(recipeInstanceId: String, orderPlaced: OrderPlaced) {
val orderPlacedEvent = EventInstance.from(orderPlaced)
val sensoryEventResult = baker.fireEventAndResolveOnEvent(recipeInstanceId, orderPlacedEvent, "ExpectedEvent")
}
}
package examples.scala.application
import com.ing.baker.runtime.scaladsl.{Baker, EventInstance}
import examples.scala.events.OrderPlaced
class FireEventAndResolveOnEvent(val baker: Baker) {
def example(recipeInstanceId: String, orderPlaced: OrderPlaced): Unit = {
val eventInstance = EventInstance.unsafeFrom(orderPlaced)
val sensoryEventResult = baker.fireEventAndResolveWhenCompleted(recipeInstanceId, eventInstance)
}
}