Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add fouleggs sample application #105

Merged
merged 16 commits into from
Aug 2, 2018
Merged

Add fouleggs sample application #105

merged 16 commits into from
Aug 2, 2018

Conversation

srfc
Copy link
Collaborator

@srfc srfc commented Jul 20, 2018

Proposed Changes

  • Add fouleggs (think rottentomatoes.com) sample application
  • The example will likely be used to replace the already existing sampleapp application which is modeled after the case study presented in Shah et al.; ADS: A Manifesto for examples in term paper
  • fouleggs also serves as an example to explore approaches to generalize MultiDactorFunctions

@srfc srfc added the WIP Work In Progress label Jul 20, 2018
@@ -43,7 +43,8 @@ class AdminSession extends Actor {
}

def addCastToFilm(personId: Int, filmId: Int, roleName: String): Unit = {
context.system.actorOf(Props(new CastAndFilmographyFunctor(personId, filmId, roleName, self)))
val functor: ActorRef = context.system.actorOf(Props(new CastAndFilmographyFunctor(personId, filmId, roleName, self)))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Props(new SomeActor(params*))

This is really not recommended to use in another actor. Please see Akka Documentation - Props for the recommended way to create Props instances, which I really would argue for: Define them in the companion object:

object CastAndFilmographyFunctor {
  def props(pId, fId, role, caller) = Props(new CastAndFilmographyFunctor(...))
}

Copy link
Owner

@SebastianSchmidl SebastianSchmidl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See inline comments. Nice example 👍, but I don't like that the DefaultMessageProtocol is used. It's ok for this PR, testing and so on, but should really be changed later on as our example applications should show best practices.


object AdminSession {

final case class Up()
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a case object, then you wouldn't need the ().

object AddCastToFilm {
final case class Request(personId: Int, filmId: Int, roleName: String)
final case class Success(personId: Int, filmId: Int, roleName: String)
final case class Failure(e: Throwable)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those messages do not extend our RequestResponseProtocol. This is nothing bad in general, but they look like they should be subtypes of it (AddCastToFilm defines our Message-Trinity: Request, Success, Failure)!

override def receive: Receive = commonBehaviour

def commonBehaviour: Receive = {
case AdminSession.Up => sender() ! akka.actor.Status.Success
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get the point of this one. If it's for a health-check, then you could use Identify and ActorIdentity or just rely on the parent-child-relationship and listen in the SystemInitializer for a Terminated message.

Nothing, you have to change now.


def addCastToFilm(personId: Int, filmId: Int, roleName: String): Unit = {
log.info(s"Adding person $personId as $roleName to film $filmId")
val functor: ActorRef = context.system.actorOf(CastAndFilmographyFunctor.props(personId, filmId, roleName, self))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

def waitingForFilmInfo: Receive = {
case DefaultMessagingProtocol.SelectAllFromRelation.Failure(e) => fail(e)
case DefaultMessagingProtocol.SelectAllFromRelation.Success(relation: Relation) => {
context.become(waitingForInsertAck orElse commonBehaviour)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you write that at the end of the code block? That's easier to read

case DefaultMessagingProtocol.SelectAllFromRelation.Success(relation: Relation) => {
context.become(waitingForInsertAck orElse commonBehaviour)

val filmInfo: Record = relation.records.get.head
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pls use exception-free code (as suggested by Codacy), example:

val filmInfoOption: Option[Record] = relation.records match {
  case Some(records) => records.headOption
  case None => None
}
filmInfoOption match {
  case None => // failure-case use `fail()` or just silently skip next step
  case Some(filmInfo) => {
    // rest of the code
  }
}

val newFilmRecord: Record = Person.Filmography.newRecord(
Person.Filmography.filmId ~> filmId &
Person.Filmography.roleName ~> roleName &
Person.Filmography.filmName ~> filmInfo.get(Film.Info.title).get &
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid record.get(col).get by using the apply-method: record(col): same effect, but nicer

def waitingForPersonInfo: Receive = {
case DefaultMessagingProtocol.SelectAllFromRelation.Failure(e) => fail(e)
case DefaultMessagingProtocol.SelectAllFromRelation.Success(relation: Relation) => {
val personInfo: Record = relation.records.get.head
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above


val newCastRecord: Record = Film.Cast.newRecord(
Film.Cast.firstName ~> personInfo.get(Person.Info.firstName).get &
Film.Cast.lastName ~> personInfo.get(Person.Info.lastName).get &
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same as above: avoid record.get(col).get

@SebastianSchmidl
Copy link
Owner

I created an issue for replacing the DefaultMessagingProtocol: Issue #109

@srfc
Copy link
Collaborator Author

srfc commented Aug 2, 2018

@CodeLionX thanks for the review! Can you have a look at the changes now?

case Some(records: Seq[Record]) => records.headOption
case _ => None
}
filmInfoOption match {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alignment ...

@SebastianSchmidl SebastianSchmidl added Merge This PR can be merged and removed Needs Review labels Aug 2, 2018
@SebastianSchmidl SebastianSchmidl merged commit 74b5763 into master Aug 2, 2018
@SebastianSchmidl SebastianSchmidl deleted the feature/fouleggs branch August 2, 2018 12:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Merge This PR can be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants