Making asynchronous HTTP calls from flows

强颜欢笑 提交于 2019-11-28 02:18:23

问题


In Corda, how can I make an asynchronous HTTP request from within a flow? Is there an API to suspend a flow while awaiting the response to the HTTP call, or a way to provide a callback?


回答1:


Corda doesn't currently provide a mechanism for making an asynchronous HTTP request and then either suspending the flow while awaiting a response, or providing a callback that will be called when the response is received.

Instead, it is recommended that you make the HTTP request before initiating the flow, then pass in the response as an argument when instantiating the flow.

Sometimes, this isn't possible. For example, the HTTP request may be required by a response flow that is initiated automatically, or it may depend on the contents of a message received from a counterparty.

In this case, you can still support this kind of workflow as follows. Suppose you are writing a CorDapp for loan applications, which are represented as LoanApplicationStates. Without an HTTP call, the responder doesn't know whether to accept the loan application or not.

Instead of creating a LoanApplicationState directly, the flow would create an UnacceptedLoanApplicationState, which the responder would store on their ledger. Once the flow ends, the responder can make an HTTP call outside of the flow framework. Based on the result of the HTTP call, the responder will either kick off an approve flow that creates a transaction to transform the UnacceptedLoanApplicationState into an LoanApplicationState, or kick off a reject flow to consume the UnacceptedLoanApplicationState state without issuing an accepted LoanApplicationState.

Alternatively, you could add a status field to the LoanApplicationState, specifying whether the loan is approved or not. Initially, the loan state would have the field set to unapproved. Then, based on the result of the HTTP request, the responder would initiate one of two flows to update the LoanApplicationState, updating it with either an approved or a rejected status.




回答2:


Corda uses quasar fibers to make sync-like (async) calls. Fortunately quasar has support for java's Future and guava's ListenableFuture.

Based on that, you could create a Flow like this

@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())
    }
}

And you can use it like this:

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

It is not the best solution but at least works with corda's infrastructure :)

Let me know if it works for you!



来源:https://stackoverflow.com/questions/47700190/making-asynchronous-http-calls-from-flows

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!