Last active
April 10, 2020 15:28
-
-
Save samuelorji/56aa034ed9d3ed6677514492410fee1a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
trait MarshallingSupport | |
extends SprayJsonSupport | |
with DefaultJsonProtocol with Runtime[Unit] { self => | |
//implicit marshallers for my return Type A | |
implicit val todoItemFormatter = jsonFormat2(TodoItem) | |
implicit val todoNameFormatter = jsonFormat1(TodoName) | |
sealed trait ErrorToHttpResponse[E] { | |
def toHttpResponse(value: E): HttpResponse | |
} | |
private def generateHttpResponseFromError(error : TodoError) : HttpResponse = { | |
error match { | |
case ToDoItemError(errorMsg) => | |
HttpResponse(StatusCodes.NotFound, entity = HttpEntity(errorMsg)) | |
case QueryError(errorMsg) => | |
HttpResponse(StatusCodes.BadRequest, entity = HttpEntity(errorMsg)) | |
case DbError(errorMsg) => | |
HttpResponse(StatusCodes.InternalServerError, entity = HttpEntity(errorMsg)) | |
} | |
} | |
implicit def errorHttp = new ErrorToHttpResponse[TodoError] { | |
override def toHttpResponse(value: TodoError): HttpResponse = { | |
generateHttpResponseFromError(value) | |
} | |
} | |
implicit val errorMarshaller: Marshaller[TodoError, HttpResponse] = { | |
Marshaller { implicit ec => error => | |
val response = generateHttpResponseFromError(error) | |
PredefinedToResponseMarshallers.fromResponse(response) | |
} | |
} | |
implicit def ioEffectToMarshallable[E, A] | |
(implicit m1: Marshaller[A, HttpResponse], m2: Marshaller[E, HttpResponse]) | |
: Marshaller[IO[E, A], HttpResponse] = { | |
//Factory method for creating marshallers | |
Marshaller { implicit ec => | |
effect => | |
val promise = Promise[List[Marshalling[HttpResponse]]]() | |
val marshalledEffect: IO[Throwable, List[Marshalling[HttpResponse]]] = | |
//foldM creates a new effect | |
//similar to flatMap | |
effect.foldM( | |
err => IO.fromFuture(_ => m2(err)), | |
suc => IO.fromFuture(_ => m1(suc)) | |
) | |
self.unsafeRunAsync(marshalledEffect) { done => | |
done.fold(failed => promise.failure(failed.squash), | |
success => promise.success(success)) | |
} | |
promise.future | |
} | |
} | |
implicit def standardRouteToRoute[E](effect: IO[E, StandardRoute]) | |
(implicit errToHttp: ErrorToHttpResponse[E]): Route = { | |
//type Route = RequestContext ⇒ Future[RouteResult] | |
ctx => | |
val promise = Promise[RouteResult]() | |
//fold doesn't return a new effect. | |
// similar to map | |
val foldedEffect = effect.fold( | |
err => { Future.successful(Complete(errToHttp.toHttpResponse(err))) }, | |
suc => suc.apply(ctx) | |
) | |
self.unsafeRunAsync(foldedEffect) { done => | |
done.fold( | |
err => promise.failure(err.squash), | |
suc => promise.completeWith(suc) | |
) | |
} | |
promise.future | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment