您可以使用 Arrow FX 将此代码转换为 monad 理解吗?

Can you convert this code to monad comprehensions using Arrow FX?

你能把这个反应式方法转换成 Arrow Fx Project Reactor monad comprehension 吗?

class ApplicationServiceImpl(private val applicationRepository: ApplicationRepository,
                             private val clientRepository: ClientRepository) : ApplicationService {

    override fun findByProjectId(clientId: String, projectId: String): Flux<ApplicationOut> {
        return clientRepository.findById(clientId)
                .switchIfEmpty(ClientDoesntExistException(clientId).toMono())
                .flatMapMany { client ->
                    applicationRepository.findByProjectIdOrderByNameAsc(projectId).map {
                        it.convertToApplicationOut(client.timeZone)
                    }
                }
    }

}

我试过类似的方法,但它无效。

我发现的第一个问题是,最初我使用 flatMapMany 将 Mono 转换为 Flux。如果我使用 FluxK.monad().fx.monad clientRepository.findById(clientId).k().bind() 没有可用的 .bind() 函数。

如果我改用 MonoK.monad().fx.monad,我不知道如何将输出转换为 Flux:

    override fun findByProjectId(clientId: String, projectId: String): Flux<out ApplicationOut> {

        return FluxK.monad().fx.monad {
            val client = clientRepository.findById(clientId).k().bind()
            if (client != null) {
                !applicationRepository.findByProjectIdOrderByNameAsc(projectId)
                        .map { it.convertToApplicationOut(client.timeZone) }.k()
            } else {
                throw !ClientDoesntExistException(clientId).toMono<ApplicationOut>().k()
            }
        }.fix().flux

更新

根据 El Paco 的回答,我将代码修改为:

        return FluxK.monad().fx.monad {
            val client = !clientRepository.findById(clientId).toFlux().k()
            if (client != null) {
                !applicationRepository.findByProjectIdOrderByNameAsc(projectId)
                        .map { it.convertToApplicationOut(client.timeZone) }.k()
            } else {
                !ClientDoesntExistException(clientId).toFlux<ApplicationOut>().k()
            }
        }.fix().flux

clientRepository.findById(clientId) 存在时它工作正常。如果没有,它不会将 null 分配给 val 客户端,而是退出理解(else 不执行)所以我无法从理解内部启动我的异常,我想这是正常的。

考虑以下方法,其中我需要控制客户或项目不存在的两种情况:

    return clientRepository.findById(clientId)
            .switchIfEmpty(ClientDoesntExistException(clientId).toMono())
            .flatMapMany { client ->
                applicationRepository.findByProjectIdOrderByNameAsc(projectId)
                        .switchIfEmpty(ClientDoesntExistException(projectId).toMono())
                        .map { it.convertToApplicationOut(client.timeZone) }
            }

考虑到 if/else 方法不起作用,我如何在使用理解时处理那些不存在的情况?

我可以在理解之外使用 switchIfEmpty 运算符,但我不知道原因(客户端不存在与项目不存在)

    return FluxK.monad().fx.monad {
        val client = !clientRepository.findById(clientId).toFlux().k()
        !applicationRepository.findByProjectIdOrderByNameAsc(projectId)
              .map { it.convertToApplicationOut(client.timeZone) }.k()        
    }.fix().flux
            .switchIfEmpty(XXX)

然后,您应该将所有操作转换为 Flux,在您的情况下 clientRepository.findById(clientId).toFlux().k()

此外,您不需要抛出该异常来打破链条。

!ClientDoesntExistException(clientId).toMono<ApplicationOut>().k()