tim
06/06/2020, 3:29 PMtim
06/06/2020, 3:29 PMimport arrow.core.Either
import arrow.core.flatMap
import arrow.core.left
import arrow.core.right
import com.google.cloud.firestore.FirestoreOptions
import java.util.*
fun controller(name: String): String {
return Item
.from(name)
.flatMap { Repo.save(it) }
.fold(
{ "Something went wrong: $it" },
{ it.id }
)
}
object Item {
fun from(name: String): Either<Failure, State> {
return State(name = name).right()
}
}
object Repo {
private val repo = FirestoreOptions.newBuilder().build().service.collection("item")
fun save(state: State): Either<Failure, State> {
/**
* What's the right approach here? I believe my options are:
* 1 - Use Either with my Failure types below this is the limit of my knowledge currently :)
* 2 - Use Either.fx ... unsure how to use this
* 3 - Use IO ... unsure how to use this
*
*/
val result = repo
.document(state.id)
.create(state)
.get() // Google's NoSQL library uses Promises
return if (result == null) {
Failure.Infrastructure.left()
} else {
state.right()
}
}
}
data class State(
val id: String = UUID.randomUUID().toString(),
val name: String
)
sealed class Failure(val reason: String) {
object Domain : Failure("domain error")
object Service : Failure("service")
object Infrastructure : Failure("infrastructure error")
object Controller : Failure("controller error")
}
simon.vergauwen
06/06/2020, 3:52 PMIO
, then this might help. This was announced yesterday @ Kotliners, hopefully the video will be online soon.
https://github.com/arrow-kt/arrow-fx/pull/169simon.vergauwen
06/06/2020, 3:53 PMsimon.vergauwen
06/06/2020, 3:53 PMtim
06/06/2020, 3:57 PMsimon.vergauwen
06/06/2020, 3:57 PMtim
06/06/2020, 3:59 PMtim
06/06/2020, 4:00 PMsimon.vergauwen
06/06/2020, 4:01 PMsimon.vergauwen
06/06/2020, 4:02 PMtim
06/06/2020, 4:16 PMtim
06/06/2020, 5:07 PMfun save(state: State) = runBlocking<Either<Failure, State>> {
IO.fx {
val result = repo
.document(state.id)
.create(state)
.get() // Google's NoSQL library uses Promises
if (result == null) {
Failure.Infrastructure.left()
} else {
state.right()
}
}.suspended()
}
pakoito
06/06/2020, 6:42 PMpakoito
06/06/2020, 6:42 PMpakoito
06/06/2020, 6:42 PMpakoito
06/06/2020, 6:43 PMpakoito
06/06/2020, 6:43 PMpakoito
06/06/2020, 6:44 PMsuspend fun save(state: State): Either<Failure, State> {
val result = repo
.document(state.id)
.create(state)
.get() // Google's NoSQL library uses Promises
if (result == null) {
return Failure.Infrastructure.left()
} else {
return state.right()
}
}
pakoito
06/06/2020, 6:45 PMpakoito
06/06/2020, 6:45 PMpakoito
06/06/2020, 6:46 PMsuspend fun save(state: State): Either<Failure, State> = IO(IO.dispatchers().background()) { // start IO in another thread
val result = repo
.document(state.id)
.create(state)
.get() // Google's NoSQL library uses Promises
if (result == null) {
Failure.Infrastructure.left()
} else {
state.right()
}
}.suspended() // unwrap IO using suspension
pakoito
06/06/2020, 6:46 PMpakoito
06/06/2020, 6:46 PMsuspended
with unsafeRunSync
pakoito
06/06/2020, 6:48 PMfun save(state: State): Either<Failure, State> = IO(IO.dispatchers().background()) {
...
}.unsafeRunSync()
pakoito
06/06/2020, 6:49 PMrunBlocking
is the unsafeRunSync
of the kotlinx.coroutines library. It’ll work, it’s just mixing the libraries for the sake of it. kotlinx.coroutines isn’t necessary to use arrow.tim
06/06/2020, 6:50 PMtim
06/06/2020, 6:54 PMtim
06/06/2020, 7:21 PM