20. 実装(2)
object Commands {
sealed trait OrderProcessCommand extends Command[OrderProcessId]
case class PlaceOrder(id: OrderProcessId) extends OrderProcessCommand
case class CancelOrderProcess(id: OrderProcessId) extends OrderProcessCommand
}
object Events {
sealed trait OrderProcessEvent extends DomainEvent
case class OrderStarted(orderId: OrderId) extends OrderProcessEvent
case class OrderAdded(orderId: OrderId) extends OrderProcessEvent
case class ReservationAdded(reservationId: ReservationId, seatId: SeatId) extends OrderProcessEvent
case class WaitListAdded(waitListId: WaitListId) extends OrderProcessEvent
case class PaymentAdded(paymentId: PaymentId) extends OrderProcessEvent
case class OrderConfirmed(orderId: OrderId) extends OrderProcessEvent
case class PaymentRemoved(paymentId: PaymentId) extends OrderProcessEvent
case class ReservationRemoved(reservationId: ReservationId) extends OrderProcessEvent
case class WaitListRemoved(waitListId: WaitListId) extends OrderProcessEvent
case class OrderRemoved(orderId: OrderId) extends OrderProcessEvent
}
object Data {
case class OrderProcessData(orderId: Option[OrderId],
reservationId: Option[ReservationId],
waitListId: Option[WaitListId],
paymentId: Option[PaymentId]) {
def isAllCanceled = orderId.isEmpty && reservationId.isEmpty && waitListId.isEmpty &&
paymentId.isEmpty
}
}
21. 実装(3)
class OrderProcessManager(receiver: ActorRef, order: ActorRef, reservation: ActorRef, payment: ActorRef, waitList: ActorRef)
extends PersistentFSM[OrderProcessState, OrderProcessData, OrderProcessEvent] {
override def domainEventClassTag: ClassTag[OrderProcessEvent] = scala.reflect.classTag[OrderProcessEvent]
override def persistenceId: String = self.path.parent.name + "-" + self.path.name
override def applyEvent(domainEvent: OrderProcessEvent, currentData: OrderProcessData): OrderProcessData = {
domainEvent match {
case OrderStarted(orderId) => currentData.copy(orderId = Some(orderId))
case OrderAdded(orderId) => currentData.copy(orderId = Some(orderId))
case ReservationAdded(reservationId, seatId) => currentData.copy(reservationId = Some(reservationId))
case WaitListAdded(waitListId) => currentData.copy(waitListId = Some(waitListId))
case PaymentAdded(paymentId) => currentData.copy(paymentId = Some(paymentId))
case PaymentRemoved(_) => currentData.copy(paymentId = None)
case ReservationRemoved(_) => currentData.copy(reservationId = None)
case WaitListRemoved(_) => currentData.copy(waitListId = None)
case OrderRemoved(_) => currentData.copy(orderId = None)
case OrderConfirmed(_) => currentData
}
}
22. 実装(4)
startWith(Untouched, OrderProcessData(None, None, None, None))
when(Untouched, 10 seconds) {
case Event(PlaceOrder(id), _) =>
val orderId = OrderId(UUID.randomUUID().toString)
goto(OrderProcessing) applying OrderStarted(orderId) forMax (5 seconds) andThen {
case OrderProcessData(Some(oid), _, _, _) =>
order ! CreateOrder(orderId)
}
}
when(OrderProcessing, 10 seconds) {
case Event(OrderCreated(orderId), _) =>
val reservationId = ReservationId(UUID.randomUUID().toString)
goto(ReservationProcessing) applying OrderAdded(orderId) forMax (5 seconds) andThen {
case OrderProcessData(Some(oid), _, _, _) =>
reservation ! MakeReservation(reservationId)
}
case Event(StateTimeout, _) =>
goto(CancellationProcessing) andThen {
case d: OrderProcessData =>
cancelAll(d)
}
}