【问题标题】:Swift NIO EventLoopFuture chain not completingSwift NIO EventLoopF​​uture 链未完成
【发布时间】:2021-04-23 01:30:29
【问题描述】:

我有一个基于 Vapor 应用的非常简单的服务。该服务使用来自另一个服务系列的数据。显然,这只是 map 方法所针对的应用程序。

链中的所有回调都执行,但链中的最后一个EventLoopFuture 从未完成,导致我的服务无限期挂起。

此代码进行一次异步调用以获取会话 ID,然后使用该数据检查某人是否是特定组的成员。对其他服务的调用返回合理的值 - 目前第二次调用总是返回错误。

当我调用此方法时,所有回调都会按预期执行和运行。

请注意,在这段代码 sn-p 中,我已经“解开”了序列的各个阶段,以试图找出问题所在,但整体行为不受影响。

我尝试了许多不同的链排列,在适当的情况下使用flatMapmapflatMapError,而没有改变最终结果。

let authService = remoteApi.authServices();

// EventLoopFuture<String> with sessionId
let sessionIdFuture = authService.getSessionId(username: userName, password: password)

// EventLoopFuture<Bool> with whether the user is in a particular group
let gsFuture = sessionIdFuture.flatMap { sessionId -> EventLoopFuture<Bool> in
    let groupMemberService = remoteApi.groupMemberServices()
    return groupMemberService.personIsInGroup(sessionId: sessionId, groupId: groupId, userId: userId)
}

// EventLoopFuture<Bool> if the above has an error, just return false
let errorFuture = gsFuture.flatMapErrorThrowing { error in
    // This executes successfully!
    return false
}

// EventLoopFuture<String> with the return data 
let returnFuture = errorFuture.flatMapThrowing { isMember -> String in
    // This executes successfully!
    let response = PersonIsMemberResponse(isMember: isMember)
    if let json = self.encodeResponse(response) {
        print(json) // {"isMember": false}
        return json
    } else {
        throw Abort(.internalServerError, reason: "could not encode our own dang data type");
    }
}.always { result in
    // This executes!
    do {
        try remoteApi.shutdown()
    } catch {
        print(error)
    }
}

gsFuture.whenComplete { result in
    // This executes!
    print("gsFuture complete!")
}
errorFuture.whenComplete { result in
     // This executes!
   print("errorFuture complete!")
}
returnFuture.whenComplete { result in
    // This DOES NOT execute!
    print("returnFuture complete!")
}

我看不到最后一个flatMapThrowing 是如何执行并返回一个值的,那么future 不完整。我错过了什么?

【问题讨论】:

  • 我刚刚尝试了这段代码(所有服务调用都被删除了),它对我来说很好用。但让我们深入了解一下:你确定try remoteApi.shutdown() 没有阻塞吗?例如,您可以在该行之后添加 print("still here")。如果它仍在运行,您介意描述remoteApi.shutdown() 正在做什么。是否可能关闭 EventLoopGroup 或 Vapor 应用程序?
  • 哦,这是 Linux 还是 macOS?如果是 macOS,sample YourBinaryName 在卡住状态下的输出也会有所帮助。
  • 我在这里发表评论是因为 SO 告诉我,如果你用问题“回答”这不是一个好的答案:)。
  • 确实是阻塞的。看起来它在AsyncHTTPClient 上调用了syncShutdown()。我知道如果客户端在没有关闭被调用的情况下进行 deinit 会非常生气。我想我需要为该服务制定正确的生命周期。 (它是单独库的一部分。)无论如何,谢谢!如果你复制你的问题作为答案,我可以给你梦寐以求的复选标记。
  • 酷!这个想法是你从 一个 EventLoopGroup 开始,然后将它重用于一切:Vapor、AsyncHTTPClient、你的 NIO 代码等......

标签: swift swift-nio


【解决方案1】:

正如我们在 cmets 中一起发现的那样,try remoteApi.shutdown() 似乎处于阻塞状态,从而阻止了进一步的事情发生。

【讨论】:

    猜你喜欢
    • 2020-03-25
    • 2021-10-30
    • 2021-11-23
    • 2021-03-24
    • 2020-09-24
    • 2013-10-26
    • 2020-11-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多