Reputation: 806
I'm getting this compilation error which I do not understand:
[error] /Users/nicu/mooc-reactive/akkahttp-typed-actors-cluster-ORMap-followers/src/main/scala/followers/HttpServer.scala:43:76: type mismatch;
[error] found : akka.actor.typed.ActorRef[Res] => Req
[error] (which expands to) akka.actor.typed.ActorRef[scala.collection.immutable.Map[followers.UserId,followers.User]] => followers.FollowCommand
[error] required: akka.actor.typed.ActorRef[Res] => Map[followers.UserId,followers.User]
[error] (which expands to) akka.actor.typed.ActorRef[scala.collection.immutable.Map[followers.UserId,followers.User]] => Map[followers.UserId,followers.User]
[error] val usersStateFuture: Future[Res] = followersActorRef.ask[Res](func)
In my mind, this signature:
def ask[Res](replyTo: ActorRef[Res] => Req)(implicit timeout: Timeout, scheduler: Scheduler): Future[Res]
should simply mean that a temporary actor will be created, of type ActorRef[Res], and the replyTo function can be used to create the message to the destination actor in a way that includes the reply reference to the temporary actor, which will then upon receive complete a promise thus the returned future will be completed with Res. In my case the message (Req) is a Command, more precisely the FollowCommand, while the answer (Res) is a Map[UserId, User] with the current state that the destination actor manages.
I cannot simply understand why it is not compiling, Thanks.
package followers
import akka.Done
import akka.actor.typed.scaladsl.Behaviors
import akka.actor.typed.scaladsl.adapter._
import akka.actor.typed.{ActorRef, ActorSystem, Behavior, Scheduler}
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.server.directives.PathDirectives._
import akka.util.Timeout
import scala.concurrent.Future
object HttpServer {
val guardianBehavior: Behavior[Done] = Behaviors.setup[Done](context => {
val followersGraphActorRef = context.spawn(FollowersData.defaultBehavior(Map()), "followersGraph")
context.watch(followersGraphActorRef)
Http()(context.system.toClassic).bindAndHandle(route(followersGraphActorRef), "localhost", 8080)
Behaviors.receiveMessage {
case Done => Behaviors.stopped
}
})
val system: ActorSystem[Done] = ActorSystem[Done](guardianBehavior, "demo-system")
def route(followersActorRef: ActorRef[Map[UserId, User]]): Route =
pathPrefix("root") {
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.directives.MethodDirectives.get
import akka.http.scaladsl.server.directives.PathDirectives.path
import akka.http.scaladsl.server.directives.RouteDirectives.complete
concat(
pathEnd {
get {
import akka.actor.typed.scaladsl.AskPattern._
import scala.concurrent.duration._
implicit val timeout: Timeout = Timeout(5.seconds) // usually we'd obtain the timeout from the system's configuration
implicit val scheduler: Scheduler = system.scheduler
type Res = Map[UserId, User]
type Req = FollowCommand
val func: ActorRef[Res] => Req = (replyTo: ActorRef[Map[UserId, User]]) => FollowCommand(UserId(1), UserId(2), replyTo)
// def ask[Res](replyTo: ActorRef[Res] => Req)(implicit timeout: Timeout, scheduler: Scheduler): Future[Res] = {
val usersStateFuture: Future[Res] = followersActorRef.ask[Res](func)
onSuccess(usersStateFuture)(usersState =>
complete(usersState.toString)) //todo json
}
}
// path(Segment) {
// case "segment1" =>
// }
)
}
}
Upvotes: 0
Views: 358
Reputation: 806
The cause was the type of the actor onto which I was calling ask. That actor, after fixing, is of type ActorRef[Req] of course. The actors have the request in their type (what types of messages they can receive). Previously it was in the code above ActorRef[Response].
Upvotes: 1