Hello everyone!
I’m currently developing an HTTP server with Ktor backed by the BFT-SMaRt library.
The BFT-SMaRt library is a Byzantine Fault Tolerant State Machine Replication library, our usage is to replicate system operations across nodes.
This library has an async call invokeAsynchRequest, I need to call this method in a Ktor Route, however since it is asynchronous it gets called, goes on with it’s life and returns.
I want to somehow block the method.
The method receives a Listener that gets invoked whenever a reply to a request arrives, whenever we have enough we want the Ktor Route to return.
I have the following Listener:
class Listener(val proxy: AsynchServiceProxy, val handler: (List<TOMMessage>) -> Unit) : ReplyListener {
val quorumSize = 4
val replies = mutableListOf<TOMMessage>()
override fun replyReceived(ctx: RequestContext, message: TOMMessage) {
replies.add(message)
LOGGER.debug("${message}")
if (replies.size > quorumSize) {
LOGGER.debug("handler size > quorum ${replies}")
handler(replies)
proxy.cleanAsynchRequest(ctx.operationId)
}
}
override fun reset() {
LOGGER.debug("reset called")
replies.clear()
}
}
It receives an handler: (List<TOMMessage>) -> Unit
that gets called whenever I have sufficient messages, this handler should be the one signaling when the Route request is ready to return.
In the HTTP side I have this
invokeAsynchRequest(
msg,
Listener(asyncServiceProxy) {
call.respond(HttpStatusCode.OK)
},
TOMMessageType.ORDERED_REQUEST
)
This however doesn’t work because call.respond
needs to be called from a coroutine context.
I know the question might not be fully clear but any help would be appreciated and I’ll be glad to clarify any detail!
Thank you everyone in advance!