Alejandro Ramos
04/24/2024, 2:01 AM// say I have something like this in my ktor endpoint
post<Resource>{
applicationService.doSomething.fold(
ifLeft= {call.respond(HttpStatusCode.BadRequest, it)},
ifRight = {call.respond(HttpStatusCode.OK, // it)}
)
}
I was wondering if this is the correct usage because fold is used to transform either into a value of C.
Would it be better to change the order to call.respond(result.fold( ifLeft, ifRight))
?
What about when we deal with side effects? (say we want to log and then respond when its a left)
I suppose we use onLeft
in those cases? (since it takes an action that is (left: A) -> Unit))
result.onLeft {
logger.log
call.respond(400)
}
call.respond(200)
I’ve also seen some people do result.mapLeft{call.respond(400,it)}
and then respond 200 after but I feel like that’s not meant to be used that way..
So, is there a “best practice” in these cases? Any of them work but I want to use them how they’re meant to be used.
Sorry for my lack of knowledge in FP, have a nice day!simon.vergauwen
04/24/2024, 5:05 AMfold
underneath. You can also just use when
instead of fold
.
when(val result = applicationService.doSomething) {
is Right -> call.respond(OK, result.value)
is Left -> call.respond(BadRequest, result.value)
}
simon.vergauwen
04/24/2024, 5:11 AMfold(ifLeft, ifRight)
map(ifRight).getOrElse(ifLeft)
either { ifRight(bind()) }.getOrElse(ifLeft)
What I think is nice, and I've used this in a few place but it depends a bit on how your errors are modelled.
inline suspend fun <refied A : Any> Either<MyError, A>.respond(
call: ApplicationCall,
statusCode: HttpStatusCode
): Unit =
when(val result = applicationService.doSomething) {
is Right -> call.respond(OK, result.value)
is Left -> when(value) {
is UserNotFound -> call.respond(BadRequest, result.value)
is Unauthorized -> call.respond(Unauthorized, result.value)
// and so on
}
}
Then in my application code I do:
applicationService.doSomething.respond(call, OK)
simon.vergauwen
04/24/2024, 5:11 AMcontext receivers
you can remove the call
parameters.
context(PipelineContext<ApplicationCall, Unit>)
Alejandro Ramos
04/24/2024, 5:47 AMWhat I think is nice, and I’ve used this in a few placeWow! This is a pretty way of abstracting this, I like it. I think I’ll try implementing it that way to further simplify our controller layerarrow intensifies