Created
July 6, 2016 10:34
-
-
Save NikitaMelnikov/d4e20f274175ca479e0577ecf6798674 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
case class Persist(data: Any) | |
case class PaymentError(data: Any) | |
object Database { | |
def props() = Props(classOf[Database]) | |
} | |
class Database extends Actor with ActorLogging { | |
def receive = { | |
case Persist(what) => | |
log.info(s"[Persist] $what") | |
case PaymentError(why) => | |
log.error(s"[Persist] $why") | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object PaymentProtocol { | |
type Timestamp = Long | |
sealed trait Command | |
object Command { | |
case class Create(user: String, provider: String, amount: Long) extends Command | |
case object Pay extends Command | |
case class Finish(status: Boolean, message: Option[String] = None) | |
} | |
sealed trait State | |
object State { | |
case object New extends State | |
case object Created extends State | |
case object InProgress extends State | |
trait Ready extends State | |
case object Successful extends Ready | |
case object Failed extends Ready | |
} | |
sealed trait Data | |
object Data { | |
case object Empty extends Data | |
case class Initialized(user: String, provider: String, amount: Long, createdAt: Timestamp) extends Data | |
case class PayedPayment(user: String, provider: String, amount: Long, createdAt: Timestamp, updatedAt: Timestamp, result: Boolean) extends Data | |
} | |
} | |
object Payment { | |
def props(database: ActorRef) = Props(classOf[Payment], database) | |
} | |
class Payment(database: ActorRef) extends LoggingFSM[PaymentProtocol.State, PaymentProtocol.Data] { | |
import PaymentProtocol._ | |
startWith(State.New, Data.Empty) | |
when(State.New) { | |
case Event(command: Command.Create, Data.Empty) => stay using Data.Initialized(command.user, command.provider, command.amount, System.currentTimeMillis()) | |
case Event(Command.Pay, data: Data.Initialized) => goto(State.InProgress) using data | |
} | |
when(State.InProgress, stateTimeout = 2 seconds) { | |
case Event(Command.Finish(status, message), data: Data.Initialized) => | |
goto(if(status) State.Successful else State.Failed) using Data.PayedPayment(data.user, data.provider, data.amount, data.createdAt, System.currentTimeMillis(), status) | |
} | |
// TODO: | |
when(State.Successful)(FSM.NullFunction) | |
when(State.Failed)(FSM.NullFunction) | |
onTransition { | |
case State.InProgress -> State.Successful => nextStateData match { | |
case payment: Data.PayedPayment => database ! Persist(payment) | |
case _ => | |
} | |
case _ -> State.Failed => | |
database ! PaymentError((stateData, nextStateData)) | |
} | |
whenUnhandled { | |
case e => | |
log.error(e.toString) | |
goto(Failed) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
object Processing extends App { | |
import PaymentProtocol._ | |
implicit val system = ActorSystem("Processing") | |
val db = system.actorOf(Database.props(), "Database") | |
runSuccessfulPayment() | |
runPaymentWithTimeout() | |
def runSuccessfulPayment(): Unit = { | |
val payment = system.actorOf(Payment.props(db), "Payment-1") | |
// Init payment | |
payment ! Command.Create("Some user", "WebMoney", 1000) | |
// User payment command | |
payment ! Command.Pay | |
// Provider response | |
payment ! Command.Finish(status = true) | |
} | |
def runPaymentWithTimeout(): Unit = { | |
val payment = system.actorOf(Payment.props(db), "Payment-2") | |
// Init payment | |
payment ! Command.Create("Another user", "Yandex", 1000) | |
// User payment command | |
payment ! Command.Pay | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment