从流进行异步 HTTP 调用

Making asynchronous HTTP calls from flows

在 Corda 中,如何从流中发出异步 HTTP 请求?是否有 API 在等待对 HTTP 调用的响应时暂停流程,或提供回调的方法?

Corda 当前不提供一种机制来发出异步 HTTP 请求,然后在等待响应时暂停流程,或者提供将在收到响应时调用的回调。

相反,建议您在启动流之前发出 HTTP 请求,然后在实例化流时将响应作为参数传递。

有时,这是不可能的。例如,HTTP 请求可能是自动启动的响应流所需要的,或者它可能取决于从交易对方收到的消息的内容。

在这种情况下,您仍然可以支持这种工作流程,如下所示。假设你正在为贷款申请编写一个 CorDapp,表示为 LoanApplicationStates。没有 HTTP 调用,响应者不知道是否接受贷款申请。

流程不会直接创建 LoanApplicationState,而是会创建一个 UnacceptedLoanApplicationState,响应者会将其存储在他们的分类帐中。流程结束后,响应者可以在流程框架之外进行 HTTP 调用。根据 HTTP 调用的结果,响应者将启动批准流程以创建交易以将 UnacceptedLoanApplicationState 转换为 LoanApplicationState,或者启动拒绝流程以使用 UnacceptedLoanApplicationState 状态没有发出接受 LoanApplicationState.

或者,您可以向 LoanApplicationState 添加状态字段,指定贷款是否已获批准。最初,贷款状态会将字段设置为未批准。然后,根据 HTTP 请求的结果,响应者将启动两个流程之一来更新 LoanApplicationState,将其更新为批准或拒绝状态。

Corda 使用 quasar fibers 进行类似同步(异步)的调用。幸好 quasar 支持 java's Futureguava's ListenableFuture.

在此基础上,您可以创建这样的流程

@InitiatingFlow
class ListenableFutureFlow<V>(val futureFn: () -> ListenableFuture<V>,
                              override val progressTracker: ProgressTracker) : FlowLogic<V>() {

    constructor(futureFn: () -> ListenableFuture<V>) : this(futureFn, tracker())

    companion object {
        object EXECUTING_FUTURE: ProgressTracker.Step("Executing future call inside fiber")
        fun tracker() = ProgressTracker(EXECUTING_FUTURE)
    }

    @Suspendable
    override fun call(): V {
        progressTracker.currentStep = EXECUTING_FUTURE
        return AsyncListenableFuture.get(futureFn())
    }
}

你可以这样使用它:

val asyncResponse = subFlow(ListenableFutureFlow { myAsyncCall(param1, param2) })

这不是最好的解决方案,但至少适用于 corda 的基础设施:)

让我知道它是否适合你!