Skip to content

Instantly share code, notes, and snippets.

@Baccata
Last active April 14, 2023 06:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Baccata/5096e55e424951661973dd6145884bff to your computer and use it in GitHub Desktop.
Save Baccata/5096e55e424951661973dd6145884bff to your computer and use it in GitHub Desktop.
import org.http4s._
import org.http4s.syntax.all._
import smithy4s.kinds._
import smithy4s.Service
import smithy4s.http4s.SimpleRestJsonBuilder
import cats.data.OptionT
import cats.effect._
import cats.effect.syntax.all._
def precompileRoutes[Alg[_[_, _, _, _, _]]](service: Service[Alg])(
f: service.Impl[IO] => Resource[IO, HttpRoutes[IO]]
): Resource[IO, service.Impl[IO] => HttpRoutes[IO]] = {
IOLocal[Option[service.FunctorInterpreter[IO]]](None).toResource.flatMap {
local =>
val delegatingImpl =
service.fromPolyFunction(new service.FunctorInterpreter[IO] {
def apply[I, E, O, SI, SO](
operation: service.Operation[I, E, O, SI, SO]
): IO[O] = local.get.flatMap {
case None =>
IO.raiseError(
new IllegalAccessError(
s"Cannot call ${service.id.name} methods here"
)
)
case Some(interpret) => interpret(operation)
}
})
f(delegatingImpl).map { hotswappingRoutes => (impl: service.Impl[IO]) =>
HttpRoutes[IO] { request =>
OptionT.liftF {
local.set(Some(service.toPolyFunction(impl)))
} *> hotswappingRoutes(request)
}
}
}
}
// Here's the usage :
val deferredRouter: Resource[IO, HelloWorldService[IO] => HttpRoutes[IO]] =
precompileRoutes(HelloWorldService) { impl: HelloWorldService[IO] =>
// if you call a method of `HelloWorldService` in this lambda,
// you'll get the `IllegalAccessError`
SimpleRestJsonBuilder.routes(impl).resource
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment