我目前正在Scala中编写一个客户端应用程序,它向API发出HTTP请求。在这个客户端应用程序中,我实现了一个服务连接器,它封装了所有API相关逻辑。在进行API调用之前,我想验证用户身份,但我想抽象这个过程。这意味着我的actor只会调用服务连接器来启动API调用,如下所示:
class MessageProcessor(credentials: Credentials) extends Actor with ActorLogging {
implicit val ec = context.dispatcher
override def receive: Receive = {
case sendMsg: SendMessage =>
log.info(s"Sending message ${sendMsg.body}.")
sendMessage(sendMsg)
}
def sendMessage(msg: SendMessage) = {
ServiceConnector.sendMessage(credentials, msg).map { result =>
// My result
}
}
}
object MessageProcessor {
def props(credentials: Credentials) = Props(classOf[MessageProcessor], credentials)
}
在我的服务连接器中,我想以某种方式 保存 “Scala方式”JWT令牌,如果我尚未通过身份验证,请在创建之前发送身份验证请求实际的API调用。
如何在考虑到期货的情况下以不可变的方式编写此类服务?
我考虑过创建其他演员并只使用令牌发送消息,但这是否真的有必要?
答案 0 :(得分:2)
你需要多个Akka状态来做正确的" Scala方式"。我不完全确定您的API是如何工作的,但以下示例显示了一种基本方法。在其第一个状态中,它在发送消息之前进行身份验证。确认身份验证后,它会发送消息。以下所有消息都会立即发送。如果以某种方式丢失了身份验证,您还可以添加一个注销或超时情况,切换回第一个接收状态。
class MessageProcessor(credentials: Credentials) extends Actor with ActorLogging {
implicit val ec = context.dispatcher
override def receive: Receive = {
case sendMsg: SendMessage =>
log.info(s"Authenticating...")
sender ! NotAuthenticated(credentials) // or authenticate somehow
context become waitingAuthentication(sendMsg)
}
def waitingAuthentication(sendMsg: SendMessage): Receive = {
case _: AuthenticationConfirmation =>
log.info(s"Sending message ${sendMsg.body}.")
sendMessage(sendMsg)
context become authenticated
}
def authenticated: Receive = {
case sendMsg: SendMessage =>
log.info(s"Sending message ${sendMsg.body}.")
sendMessage(sendMsg)
}
}
它只是一个示例,并没有考虑所有情况(例如,在等待身份验证期间SendMessage
,因此您需要一个SendMessages
的队列。如果多个actor需要知道身份验证状态或凭据,那么如果您不想要一个处理和验证所有消息的瓶颈角色,则需要向他们广播。在这种情况下,所有这些都需要多个身份验证状态,如上所述。
答案 1 :(得分:0)
演员是为州设计的
这似乎是一种虚假的运动。 Actors的全部意义在于他们可以仓库状态。来自documentation specifically on state:
好消息是,Akka演员在概念上各有自己的 轻质螺纹,完全与其余部分隔离 系统。这意味着不必使用同步访问 锁定你可以编写你的演员代码而不用担心 并发性。
因此,“scala方式”只是将它保存在Actors中的变量中。
使用Actors而不是Futures的原因之一是你可以保持状态。为什么选择演员然后解雇他们的主要优势之一???
你的问题相当于“如何在不进行散列的情况下使用HashMap(以scala方式)?”