我正在try-catch
块中创建一个redis pubsub客户端。在try
块中,客户端初始化为回调以将消息转发到客户端。如果将消息发送到客户端时出现问题,则会抛出异常,在这种情况下,我需要停止redis客户端。这是代码:
try {
val redisClient = RedisPubSub(
channels = Seq(currentUserId.toString),
patterns = Seq(),
onMessage = (pubSubMessage: PubSubMessage) => {
responseObserver.onValue(pubSubMessage.data)
}
)
}
catch {
case e: RuntimeException =>
// redisClient isn't defined here...
redisClient.unsubscribe(currentUserId.toString)
redisClient.stop()
messageStreamResult.complete(Try(true))
responseObserver.onCompleted()
}
问题是redis客户端val没有在catch块中定义,因为可能存在创建它的异常。我也无法将try-catch
块移动到回调中,因为在回调中无法(我能找到)引用redisClient对象(this
无法解析)。
要解决此问题,我将redisClient
实例化为var
块之外的try-catch
。然后在try
块内部,我停止客户端,并为redisPubSub
var分配一个新的redisClient
(如上所述)。这是一个丑陋的黑客,也容易出错(例如,如果真的 创建第二个客户端的问题,catch块将尝试在错误的对象上调用方法)。
是否有更好的方法来编写此代码,以便在尝试将消息发送到responseObserver时引发异常时,可以在redisClient上正确调用stop()
?
更新
我刚用承诺解决了这个问题。有没有更简单的方法?
答案 0 :(得分:0)
如果在发送邮件时出现问题,则会调用该异常处理程序而不是。这是设置客户端的问题。这个SO answer讨论了在发送消息时处理错误。
至于引用客户端的回调,我认为您希望在创建客户端之后注册回调,而不是在创建时尝试传递回调。这是执行此操作的sample code from Debashish Ghosh。
据推测,回调将在另一个线程中运行,因此如果它使用redisClient
,则必须注意并发性。理想情况下,回调可以通过一些参数到达客户端对象。如果没有,那么使用volatile
可能是解决这个问题的最简单方法,尽管我怀疑如果多次回调一次失败,你最终会遇到麻烦。或许使用演员管理客户端连接,正如Debashish所做的那样?