Closed CodeLionX closed 6 years ago
Customer
domain actor example:
object Customer {
object CustomerInfo extends RelationDef {
val custName: ColumnDef[String] = ColumnDef("cust_name")
val custGroupId: ColumnDef[Int] = ColumnDef("c_g_id")
override val columns: Set[UntypedColumnDef] =
Set(custName, custGroupId)
override val name: String = "customer_info"
}
object StoreVisits extends RelationDef {
val storeId: ColumnDef[Int] = ColumnDef("store_id")
val timestamp: ColumnDef[ZonedDateTime] =
ColumnDef("time", ZonedDateTime.EPOCH)
val amount: ColumnDef[Double] = ColumnDef("amount")
val fixedDiscount: ColumnDef[Double] = ColumnDef("fixed_disc")
val varDiscount: ColumnDef[Double] = ColumnDef("var_disc")
override val columns: Set[UntypedColumnDef] =
Set(storeId, timestamp, amount, fixedDiscount, varDiscount)
override val name: String = "store_visits"
}
}
class Customer(id: Int) extends Dactor(id) {
override protected val relations: Map[RelationDef, MutableRelation] =
Dactor.createAsRowRelations(Seq(CustomerInfo, StoreVisits, Password))
override def receive: Receive = {
case GetCustomerInfo.Request() => getCustomerInfo()
case AddStoreVisit.Request([params]) => addStoreVisit([params])
}
}
Example for relation usage:
override def receive: Receive = {
case AddStoreVisit.Request(params: AsvParams) =>
addStoreVisit(params) match {
case Success(_) => sender() ! AddStoreVisit.Success(Relation.empty)
case Failure(e) => sender() ! AddStoreVisit.Failure(e)
}
[...]
}
def addStoreVisit(p: AsvParams): Try[Relation] =
if(!isValid(p))
throw NotValidStoreVisitException(p)
val svRecord = StoreVisits.newRecord(
StoreVisits.storeId ~> p.storeId
& StoreVisits.timestamp ~> p.time
& StoreVisits.amount ~> p.amount
& StoreVisits.fixedDiscount ~> p.fixedDiscount
& StoreVisits.varDiscount ~> p.varDiscount
).build()
relations(StoreVisits).insert(svRecord)
}
how to access a relation:
relation(StoreVisits)
.project(Set(StoreVisits.storeId))
.where([...])
.insert([...])
.delete([...])
.update([...])
definition of message protocol of customer:
object GetCustomerInfo {
case class Request() extends RequestResponseProtocol.Request
case class Success(result: Relation) extends RequestResponseProtocol.Success
case class Failure(e: Throwable) extends RequestResponseProtocol.Failure
}
object AddStoreVisit {
case class Request(params: AsvParams) extends RequestResponseProtocol.Request
case class Success(result: Relation) extends RequestResponseProtocol.Success
case class Failure(e: Throwable) extends RequestResponseProtocol.Failure
}
// not in architecture:
object GetCustomerGroupId {
case class Request() extends RequestResponseProtocol.Request
case class Success(result: Relation) extends RequestResponseProtocol.Success
case class Failure(e: Throwable) extends RequestResponseProtocol.Failure
}
send messages to store sections
val purchaseRequests = sectionIds.map( sectionId => {
val cartItems: Relation = allCartItems
.where(CartPurchases.sectionId -> { _ == sectionId })
sectionId -> StoreSection.GetVariableDiscountUpdateInventory.Request(
customerId, time, cartItems
)
})
val variableDiscounts: FutureRelation =
Dactor.askDactor(system, classOf[StoreSection], purchaseRequests)
// process discounts: calculate sum
notify customer
val variableDiscountSumResult: Relation = Await.result(variableDiscountSum)
val sumRecord = variableDiscountSumResult.head
val msg = Customer.AddStoreVisit.Request(
storeId,
time,
sumRecord.get(amountCol),
sumRecord.get(fixedDiscCol),
sumRecord.get(varDiscCol)
)
Dactor.dactorSelection(system, classOf[Customer], customerId) ! msg
Film
domain actor example:
object FilmInfo extends RelationDef("film_info") {
val title: ColumnDef[String] = ColumnDef("title")
val description: ColumnDef[String] = ColumnDef("description")
val release: ColumnDef[ZonedDateTime] =
ColumnDef("release", ZonedDateTime.EPOCH)
}
object Cast extends RelationDef("cast") {
val actorId: ColumnDef[Int] = ColumnDef("actor_id")
val name: ColumnDef[String] = ColumnDef("name")
val role: ColumnDef[String] = ColumnDef("role")
}
class Film(id: Int) extends Dactor(id) {
override protected val relations: Map[RelationDef, MutableRelation] =
Dactor.createAsRowRelations(Seq(FilmInfo, Cast))
override def receive: Receive = {
case PrepareDisplayInfo.Request() => prepareDisplayInfo()
}
}
how to access a relation:
relation(FilmInfo)
.project(Set(FilmInfo.title, FilmInfo.description))
.where([...])
.insert([...])
.delete([...])
.update([...])
more functionality:
val results: Seq[Record] =
relation(Cast)
.where(Cast.role ~> {
_ equals "Casey Bracket"
})
.project(Set(Cast.name))
.records
results.foreach(println)
// ["Olivia Munn"]
Functor usage:
val filmId = 1
val actorId= 13
val role = "Quinn McKenna"
val addCastToFilm = SequentialFunction()
.start( (_: AddCastToFilm.Start) =>
GetActorInfo.Request()
}, Dactor.dactorSelection(classOf[Actor], actorId)
.next(response => {
response.records.headOption match {
case Some(actorInfo: Record) =>
val name= actorInfo(ActorInfo.name)
AddCast.Request(actorId, name, role)
case None =>
fail(ActorInfoNotFoundException())
}
}, Dactor.dactorSelection(classOf[Film], filmId)
//.next(response => new request, receiver)
.end(identity) // sends last response or failure message to caller
val functorRef = Dactor.startFunctor(
// functor, akka-context, reference to Actor receiving response
addCastToFilm, context, self
)(
// start-message
AddCastToFilm.Start
)
Collection of code snippets highlighted with github-scala, so everybody can relate to.