Skip to content

Instantly share code, notes, and snippets.

@alterationx10
Created June 27, 2023 20:03
Show Gist options
  • Save alterationx10/745433b4abe812604451dba25005143d to your computer and use it in GitHub Desktop.
Save alterationx10/745433b4abe812604451dba25005143d to your computer and use it in GitHub Desktop.
ZIO HTTP app using Scope to open/close a resource per websocket connection
import zio.Console.printLine
import zio._
import zio.http.ChannelEvent.UserEvent._
import zio.http.ChannelEvent._
import zio.http._
import java.io.IOException
object Main extends ZIOAppDefault {
// Pretend this is something we might stream from, and need to call back to.
// We would want to make one-per-ws-connection
case class FakeResource()
// While we're playing make-believe, pretend it's "closable" too.
// It would be swell if we could use Scope to manage closing the resource
val fakeResourceAR: ZIO[Scope, IOException, FakeResource] =
ZIO.acquireRelease(printLine("Scope opened!").as(FakeResource()))(_ =>
printLine("Scope closed!").orDie
)
val wsLogic = Handler.webSocket { ws =>
ZIO.scoped {
for {
createdResource <- fakeResourceAR // Create the thing when connected
_ <- ws.receiveAll {
case UserEventTriggered(HandshakeComplete) =>
ZIO.never.fork.unit // Do something forever using createdResource
case Read(WebSocketFrame.Text(msg)) =>
ZIO.unit // Do some call/response with createdResource
case Unregistered =>
ZIO.interrupt // This will bail, and our scope will close 🎉
case other => ZIO.unit
}
} yield ()
}
}
val app: Http[Any, Nothing, Request, Response] =
Http.collectZIO[Request] { case Method.GET -> Root / "ws" =>
wsLogic.toResponse
}
override def run: ZIO[Environment with ZIOAppArgs with Scope, Any, Any] =
Server.serve(app).provide(Server.default)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment