Last active
April 26, 2017 15:49
-
-
Save abdheshkumar/ea550ac6f1aa1eeee32f2bf8997db1c4 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
import freestyle._ | |
import freestyle.implicits._ | |
import freestyle.implicits.interpretAp | |
import cats.implicits._ | |
case class ValidationResult(isValid:Boolean, events:List[Event]) | |
trait Command | |
case class UnknownCommand(cmd:Any) extends Command | |
sealed trait Event {val name:String} | |
@free trait LoggerOp[A[_]] { | |
def debug(msg: String, o: List[Event]): FreeS[A, Unit] | |
def info(msg: String, o: List[Event]): FreeS[A, Unit] | |
def warn(msg: String, o: List[Event]): FreeS[A, Unit] | |
def error(msg: String, o: List[Event]): FreeS[A, Unit] | |
} | |
@free trait ActorOp[A[_]] { | |
def send(a: Any, to: ActorRef): FreeS[A, Unit] | |
def sendToActorSelection(a: Any, context: ActorContext, path: String): FreeS[A, Unit] | |
def tellFrom(a: Any, to: ActorRef, from: ActorRef): FreeS[A, Unit] | |
def timeOut(context: ActorContext, time: Int): FreeS[A, Unit] | |
def transitionState(context: ActorContext, state: () => Receive): FreeS[A, Unit] | |
def stopActor(context: ActorContext, victim: ActorRef): FreeS[A, Unit] | |
def createActor(props: Props, name: String, context: ActorContext): FreeS[A, ActorRef] | |
} | |
@module trait FinalApp[F[_]] { | |
val loggerOp: LoggerOp[F] | |
val actorOp: ActorOp[F] | |
} | |
type OutputState[T] = State[T, ?] | |
implicit val StatelessLoggerInterpreter = new LoggerOp.Handler[Id] { | |
def debug(msg: String, o: List[Event]): Id[Unit] = println(s"[Debug] : ${msg}") | |
def info(msg: String, o: List[Event]): Id[Unit] = println(s"[Info] : ${msg}") | |
def warn(msg: String, o: List[Event]): Id[Unit] = println(s"[Warn] : ${msg}") | |
def error(msg: String, o: List[Event]): Id[Unit] = println(s"[Error] : ${msg}") | |
} | |
implicit val StatelessActorOpsInterpreter = new ActorOp.Handler[Id] { | |
def send(a: Any, to: ActorRef): Id[Unit] = to ! a | |
def sendToActorSelection(a: Any, context: ActorContext, path: String): Id[Unit] = context.actorSelection(path) ! a | |
def tellFrom(a: Any, to: ActorRef, from: ActorRef): Id[Unit] = to tell(a, from) | |
def timeOut(context: ActorContext, time: Int): Id[Unit] = { | |
if (time == 0) { | |
context.setReceiveTimeout(Duration.Undefined) | |
} | |
else { | |
context.setReceiveTimeout(time seconds) | |
} | |
} | |
def transitionState(context: ActorContext, state: () => Receive): Id[Unit] = context.become(state()) | |
def stopActor(context: ActorContext, victim: ActorRef): Id[Unit] = context.stop(victim) | |
def createActor(props: Props, name: String, context: ActorContext): Id[Unit] = context.actorOf(props, name) | |
} | |
final def handleCommand[T[?], A <: ActorMessage](message: A, | |
validate: (Command) => ValidationResult, | |
success: (A, ActorContext) => FreeS[T, List[Event]], | |
failure: (A, ActorContext) => FreeS[T, List[Event]], | |
logger: (String, List[Event]) => FreeS[T, List[Event]], | |
timeOut: => FreeS[T, List[Event]] | |
)(implicit context: ActorContext, interpreter: FunctionK[T, cats.Id]): List[Event] = { | |
(message.command match { | |
case x: UnknownCommand => logger(s"Stateless -- Unknown Message ${x}", Nil).exec[Id](interpreter) | |
case x: ReceiveTimeout => timeOut.exec[Id](interpreter) //timeOut.foldMap[Id](interpreter) | |
case x: Command => | |
val validationResult = validate(x) | |
validationResult.events ++ | |
(if (validationResult.isValid) { | |
success(message, context).exec[Id](interpreter) | |
} else { | |
failure(message, context).exec[Id](interpreter) | |
} | |
) | |
case x => logger(s"Stateless -- Unknown Message ${x}", Nil).exec[Id](interpreter) | |
}).filter(event => persistenceFilter(event, persistenceLevel)) | |
} | |
object Implicits { | |
//I want to combine interpreters | |
implicit val loggerAndActorInterpreter: FinalApp.Op ~> Id = StatelessLoggerInterpreter or StatelessActorOpsInterpreter | |
} | |
I want to call handleCommand function: | |
handleCommand[FinalApp.Op,ActionMessage](message, | |
validate, | |
successWhenSleeping, | |
failure, | |
logger, | |
setTimeOutAndMoveOn(TimedOut,node,action,context))(Implicits.loggerAndActorInterpreter) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment