All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fmgp.did.framework.TransportWSImp.scala Maven / Gradle / Ivy

The newest version!
package fmgp.did.framework

import zio._
import zio.json._
import zio.stream._
import zio.http._
import fmgp.crypto.error._
import fmgp.did._
import fmgp.did.comm._

/** this API is still a WIP
  *
  * The Auto reconnect feature was remove.
  */
class TransportWSImp[MSG](
    outboundBuf: Queue[MSG],
    inboundBuf: Hub[MSG],
    val ws: Websocket[Throwable],
) extends TransportWS[Any, MSG] {

  def transmissionFlow = Transport.TransmissionFlow.BothWays
  def transmissionType = Transport.TransmissionType.MultiTransmissions

  override def outbound: ZSink[Any, Transport.OutErr, MSG, Nothing, Unit] = ZSink.fromQueue(outboundBuf)
  override def inbound: ZStream[Any, Transport.InErr, MSG] = ZStream.fromHub(inboundBuf)
}

object TransportWSImp {

  // def open(url: String): ZIO[Operator & Operations & Resolver & (Client & Scope), Throwable, String] = {
  //   def channel2Transport(
  //       channel: Channel[ChannelEvent[WebSocketFrame], ChannelEvent[WebSocketFrame]]
  //   ): ZIO[Operator & (Operations & Resolver), Throwable, TransportDIDCommWS[Any]] = {
  //     val socketID = Websocket.nextSocketName
  //     ZIO.logAnnotate(Websocket.logAnnotation(socketID)) {
  //       for {
  //         transport <- make(channel, identifier = socketID)
  //         ws <- WebsocketJVMImp
  //           .bindings(channel, transport.ws)
  //           .tapError(e => ZIO.logError(e.getMessage))
  //           .fork
  //         op <- ZIO.service[Operator]
  //         transportWarp = TransportDIDCommWS(transport)
  //         _ <- op
  //           .receiveTransport(transportWarp)
  //           .tapErrorCause(ZIO.logErrorCause(_))
  //           .mapError(DidException(_))
  //         _ <- ws.join *> ZIO.log("WebsocketJVM CLOSE")
  //       } yield transportWarp
  //     }
  //   }
  //   val url = URL.decode("url").getOrElse(???)

  //   for {
  //     client <- ZIO.service[Client]
  //     xxx = Handler.fromFunctionZIO(channel2Transport _)
  //     app = WebSocketApp(handler = xxx, customConfig = None)
  //     client2 = if (url.isAbsolute) client.url(url) else client.addUrl(url)
  //     aaa = client2.socket(app)
  //     response <- createWebSocketAppWithOperator(Seq.empty).connect("FIXME").debug
  //     data <- response.body.asString
  //       .tapError(ex => ZIO.logError(s"Fail parse http WS response body: ${ex.getMessage}"))
  //       .orDie
  //     _ <- response.status.isError match
  //       case true  => ZIO.logError(data)
  //       case false => ZIO.logInfo(data)
  //   } yield (data)
  // }

  def createWebSocketAppWithOperator(
      annotationMap: Seq[LogAnnotation]
  ): WebSocketApp[Operator & Operations & Resolver] =
    WebSocketApp(
      handler = Handler
        .fromFunctionZIO((channel: Channel[ChannelEvent[WebSocketFrame], ChannelEvent[WebSocketFrame]]) =>
          val socketID = Websocket.nextSocketName
          ZIO.logAnnotate(Websocket.logAnnotation(socketID), annotationMap*) {
            for {
              transport <- make(channel, identifier = socketID)
              ws <- fmgp.did.framework.WebsocketJVMImp
                .bindings(channel, transport.ws)
                .tapError(e => ZIO.logError(e.getMessage))
                .fork
              op <- ZIO.service[Operator]
              transportWarp = TransportDIDCommWS(transport)
              _ <- op
                .receiveTransport(transportWarp)
                .tapErrorCause(ZIO.logErrorCause(_))
                .mapError(DidException(_))
              _ <- ws.join *> ZIO.log("WebsocketJVM CLOSE")
            } yield ws
          }
        ),
      customConfig = None
    )

  def make(
      channel: Channel[ChannelEvent[WebSocketFrame], ChannelEvent[WebSocketFrame]],
      identifier: String,
      boundSize: Int = 10,
  ): ZIO[Any, Nothing, TransportWSImp[String]] = for {
    outbound <- Queue.bounded[String](boundSize)
    inbound <- Hub.bounded[String](boundSize)
    ws = new Websocket[Throwable] {
      override val socketID: String = identifier
      override def onMessage(message: String) =
        inbound.offer(message).flatMap {
          case true => ZIO.unit
          case false =>
            ZIO.logError(s"Message lost in inbound: '$message'") *>
              ZIO.fail(new RuntimeException(s"Message lost in inbound: '$message'"))
        }
      override def send(value: String) = channel.send(ChannelEvent.Read(WebSocketFrame.text(value)))
      override def close = channel.shutdown
    }
    _ <- ZStream
      .fromQueue(outbound)
      .runForeach(data => ws.send(data))
      .fork
  } yield TransportWSImp[String](outbound, inbound, ws)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy