Skip to content

Instantly share code, notes, and snippets.

@PedroAlvarado
Last active December 3, 2022 07:35
Show Gist options
  • Save PedroAlvarado/62c5cd7546b3926fdd2a0f4ef09e36e2 to your computer and use it in GitHub Desktop.
Save PedroAlvarado/62c5cd7546b3926fdd2a0f4ef09e36e2 to your computer and use it in GitHub Desktop.
Error Handling - More errors than necessary.
package com.example.x
import arrow.core.Either
import arrow.core.continuations.Effect
import arrow.core.continuations.EffectScope
import arrow.core.continuations.effect
import io.kotest.core.spec.style.StringSpec
typealias Raise<E> = EffectScope<E>
class ArrowErrorHandling : StringSpec({
val serviceA = ServiceA()
val serviceB = ServiceB()
val serviceC = ServiceC()
"Consume multiple Domain Services with Context Receiver" {
val resultValue = effect {
val a = serviceA.deleteA("someId")
val b = serviceB.deleteB("someId")
val c = serviceC.deleteC("someId")
val result = a.id + b.id + c.id
result
}.fold(
{
when (it) {
is AServiceError -> {
when (it) {
is AServiceReadOperationError -> TODO()
is AServiceDeleteOperationError -> when (it) {
is AIsProtected -> TODO()//Only care about this ones
is AIsFrozen -> TODO()//Only care about this ones
}
is AServiceUpdateOperationError -> TODO()
}
}
is BServiceError -> when (it) {
is BServiceReadOperationError -> TODO()
is BServiceDeleteOperationError -> when (it) {
is BIsProtected -> TODO()//Only care about this ones
is BIsFrozen -> TODO()//Only care about this ones
}
is BServiceUpdateOperationError -> TODO()
}
is CServiceError -> when (it) {
is CServiceReadOperationError -> TODO()
is CServiceDeleteOperationError -> when (it) {
is CIsProtected -> TODO()//Only care about this ones
is CIsFrozen -> TODO()//Only care about this ones
}
is CServiceUpdateOperationError -> TODO()
}
}
},
{ it }
)
println(resultValue)
}
})
sealed interface BaseError
/**
* Service A Errors
*/
sealed interface AServiceError : BaseError
sealed interface AServiceReadOperationError : AServiceError
sealed interface AServiceDeleteOperationError : AServiceError
sealed interface AServiceUpdateOperationError : AServiceError
sealed interface AServiceCreateOperationError : AServiceError
data class ANotFound(val property: String) : AServiceReadOperationError
data class TooManyA(val property: String) : AServiceCreateOperationError, AServiceUpdateOperationError
data class TooManySomethingElse(val property: String) : AServiceCreateOperationError, AServiceUpdateOperationError
data class AAlreadyExistsService(val property: String) : AServiceCreateOperationError, AServiceUpdateOperationError
data class AIsBannedService(val property: String) : AServiceUpdateOperationError
data class AIsProtected(val property: String) : AServiceDeleteOperationError
data class AIsFrozen(val property: String) : AServiceDeleteOperationError
data class A(val id: String)
class ServiceA {
fun createA(): Either<AServiceCreateOperationError, A> = Either.Right(A("A"))
fun updateA(id: String): Either<AServiceUpdateOperationError, A> = Either.Right(A("A"))
fun readA(id: String): Either<AServiceReadOperationError, A> = Either.Right(A("A"))
context(Raise<AServiceDeleteOperationError>)
fun deleteA(id: String): A = A("A")
}
/**
* Service B Errors
*/
sealed interface BServiceError : BaseError
sealed interface BServiceReadOperationError : BServiceError
sealed interface BServiceDeleteOperationError : BServiceError
sealed interface BServiceUpdateOperationError : BServiceError
sealed interface BServiceCreateOperationError : BServiceError
data class BNotFound(val property: String) : BServiceReadOperationError, BServiceCreateOperationError
data class BUnavailable(val property: String) : BServiceReadOperationError, BServiceUpdateOperationError
data class BAlreadyExists(val property: String) : BServiceUpdateOperationError, BServiceCreateOperationError
data class TooManyB(val property: String) : BServiceUpdateOperationError, BServiceCreateOperationError
data class BIsProtected(val property: String) : BServiceDeleteOperationError
data class BIsFrozen(val property: String) : BServiceDeleteOperationError
data class B(val id: String)
class ServiceB {
fun createB(): Either<BServiceCreateOperationError, B> = Either.Right(B("B"))
fun updateB(id: String): Either<BServiceUpdateOperationError, B> = Either.Right(B("B"))
fun readB(id: String): Either<BServiceReadOperationError, B> = Either.Right(B("B"))
context(Raise<BServiceDeleteOperationError>)
fun deleteB(id: String) = B("B")
}
/**
* Service C Errors
*/
sealed interface CServiceError : BaseError
sealed interface CServiceReadOperationError : CServiceError
sealed interface CServiceDeleteOperationError : CServiceError
sealed interface CServiceUpdateOperationError : CServiceError
sealed interface CServiceCreateOperationError : CServiceError
data class CNotFound(val property: String) : CServiceReadOperationError, CServiceCreateOperationError
data class CUnavailable(val property: String) : CServiceReadOperationError, CServiceUpdateOperationError
data class CAlreadyExists(val property: String) : CServiceUpdateOperationError, CServiceCreateOperationError
data class TooManyC(val property: String) : CServiceUpdateOperationError, CServiceCreateOperationError
data class CIsProtected(val property: String) : CServiceDeleteOperationError
data class CIsFrozen(val property: String) : CServiceDeleteOperationError
data class C(val id: String)
class ServiceC {
fun createC(): Either<CServiceCreateOperationError, C> = Either.Right(C("C"))
fun updateC(id: String): Either<CServiceUpdateOperationError, C> = Either.Right(C("C"))
fun readC(id: String): Either<CServiceReadOperationError, C> = Either.Right(C("C"))
context(Raise<CServiceDeleteOperationError>)
fun deleteC(id: String) = C("C")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment