izumi.idealingua.runtime.rpc.http4s.clients.WsRpcDispatcher.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of idealingua-v1-runtime-rpc-http4s_2.13 Show documentation
Show all versions of idealingua-v1-runtime-rpc-http4s_2.13 Show documentation
idealingua-v1-runtime-rpc-http4s
The newest version!
package izumi.idealingua.runtime.rpc.http4s.clients
import io.circe.Json
import izumi.functional.bio.{Async2, Entropy2, F, Temporal2}
import izumi.idealingua.runtime.rpc.*
import izumi.idealingua.runtime.rpc.http4s.clients.WsRpcDispatcher.IRTDispatcherWs
import izumi.idealingua.runtime.rpc.http4s.clients.WsRpcDispatcherFactory.WsRpcClientConnection
import izumi.idealingua.runtime.rpc.http4s.ws.{RawResponse, WsSessionId}
import logstage.LogIO2
import java.util.concurrent.TimeoutException
import scala.concurrent.duration.FiniteDuration
class WsRpcDispatcher[F[+_, +_]: Async2](
connection: WsRpcClientConnection[F],
timeout: FiniteDuration,
codec: IRTClientMultiplexor[F],
logger: LogIO2[F],
entropy2: Entropy2[F],
) extends IRTDispatcherWs[F] {
override def sessionId: Option[WsSessionId] = {
connection.sessionId
}
override def authorize(headers: Map[String, String]): F[Throwable, Unit] = {
connection.authorize(headers, timeout)
}
override def dispatch(input: IRTMuxRequest): F[Throwable, IRTMuxResponse] = {
dispatchFor(connection, codec)(timeout)(input)
}
protected def dispatchFor(
connection: WsRpcClientConnection[F],
codec: IRTClientMultiplexor[F],
)(timeout: FiniteDuration
)(request: IRTMuxRequest
): F[Throwable, IRTMuxResponse] = {
for {
_ <- logger.trace(s"${request.method -> "method"}: Going to perform $request")
encoded <- codec.encode(request)
rpcPacketId <- RpcPacketId.random(entropy2)
rpcPacket = buildRequest(rpcPacketId, request.method, encoded)
res <- connection.requestAndAwait(rpcPacketId, rpcPacket, Some(request.method), timeout).flatMap {
case Some(value: RawResponse.EmptyRawResponse) =>
F.fail(new IRTGenericFailure(s"${request.method -> "method"}, $rpcPacketId: empty response: $value"))
case Some(value: RawResponse.GoodRawResponse) =>
logger.debug(s"${request.method -> "method"}, $rpcPacketId: Have response: $value") *>
codec.decode(value.data, value.method)
case Some(value: RawResponse.BadRawResponse) =>
logger.debug(s"${request.method -> "method"}, $rpcPacketId: Have response: $value") *>
F.fail(new IRTGenericFailure(s"${request.method -> "method"}, $rpcPacketId: generic failure: ${value.error}"))
case None =>
F.fail(new TimeoutException(s"${request.method -> "method"}, $rpcPacketId: No response in $timeout"))
}
} yield res
}
protected def buildRequest(rpcPacketId: RpcPacketId, method: IRTMethodId, body: Json): RpcPacket = {
RpcPacket.rpcRequest(rpcPacketId, method, body)
}
}
object WsRpcDispatcher {
trait IRTDispatcherWs[F[_, _]] extends IRTDispatcher[F] {
def sessionId: Option[WsSessionId]
def authorize(headers: Map[String, String]): F[Throwable, Unit]
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy