Alexander Schell
07/29/2020, 5:22 AMPatrick Louis
07/29/2020, 6:07 AM.sequence(Either.applicative)
should be able to convert your Either<Throwable<Iterable<T>>
into Iterable<Either<Throwable,T>>
. I'm not sure if you can flatten over nested Sequences directly but I guess you'd be able to figure something out from there.Alexander Schell
07/29/2020, 6:08 AMpakoito
07/29/2020, 10:17 AMsequence
first, then flatten
should do the trick!Alexander Schell
07/29/2020, 11:07 AMfun fetchEventsByStatusSafe(eventStatus: EventStatus,
fetchBatchSize: Int): SequenceK<Either<Throwable, Event>> {
LOGGER.debug("Fetching Events (eventStatus = $eventStatus)")
return generateSequence(fetchPageSafe(eventStatus, PageRequest.of(0, fetchBatchSize))) {
either -> when (either) {
is Either.Right -> {
when (either.b.hasNext()) {
true -> fetchPageSafe(eventStatus, either.b.nextPageable())
else -> null
}
}
else -> either
}
}.flatten().k()
}
private fun fetchPageSafe(eventStatus: EventStatus,
pageable: Pageable): Either<Throwable, Page<Event>> {
LOGGER.debug("Fetching Page<Event> (eventStatus = $eventStatus, pageNumber = ${pageable.pageNumber}, pageSize = ${pageable.pageSize})")
return Either.fx {
eventRepository.findAllByStatus(eventStatus.eventStatusId, pageable, EVENT_WITH_PARAMETERS_GRAPH)
}
}
private fun Sequence<Either<Throwable, Page<Event>>>.flatten(): Sequence<Either<Throwable, Event>>
= this.map { either -> either.flatten() }.flatten()
private fun Either<Throwable, Page<Event>>.flatten(): Sequence<Either<Throwable, Event>>
= when (this) {
is Either.Right -> {
this.b.asSequence().map { event -> Either.right(event) }
}
is Either.Left -> sequenceOf(this)
}
Alexander Schell
07/29/2020, 11:09 AMpakoito
07/29/2020, 11:56 AMreturn Either.fx {
eventRepository.findAllByStatus(eventStatus.eventStatusId, pageable, EVENT_WITH_PARAMETERS_GRAPH)
}
pakoito
07/29/2020, 11:56 AMpakoito
07/29/2020, 11:56 AMAlexander Schell
07/29/2020, 12:12 PMPatrick Louis
07/29/2020, 12:35 PMfun fetchEventsByStatusSafe(eventStatus: EventStatus,
fetchBatchSize: Int): SequenceK<Either<Throwable, Event>> {
LOGGER.debug("Fetching Events (eventStatus = $eventStatus)")
return generateSequence(fetchPageSafe(eventStatus, PageRequest.of(0, fetchBatchSize))) {
either -> either.map { if (it.hasNext()) fetchPageSafe(eventStatus, either.b.nextPageable()) else null }
}.flatMap { it.sequence(Either.applicative())<<<possibly '.toSequence()'>>> }.fix()
}
private fun fetchPageSafe(eventStatus: EventStatus,
pageable: Pageable): Either<Throwable, Page<Event>> {
LOGGER.debug("Fetching Page<Event> (eventStatus = $eventStatus, pageNumber = ${pageable.pageNumber}, pageSize = ${pageable.pageSize})")
return eventRepository.findAllByStatus(eventStatus.eventStatusId, pageable, EVENT_WITH_PARAMETERS_GRAPH).right()
// if you want exceptions to be caught here you should probably do something like
// return IO { eventRepository.findAllByStatus(eventStatus.eventStatusId, pageable, EVENT_WITH_PARAMETERS_GRAPH) }.attempt().unsafeRunSync()
}
Alexander Schell
07/29/2020, 12:59 PMAlexander Schell
07/30/2020, 2:49 PMPatrick Louis
07/31/2020, 6:48 AMval thing: Sequence<Either<Throwable,Iterable<XXX>>>
thing.map { it.sequence(Either.applicative()) } // Sequence<Iterable<Either<Throwable,XXX>>>
in order to flatten this to a Sequence<Either<Throwable,XXX>>
you'd need to turn the Iterable
into a Sequence
.
That's where the toSequence()
extension function would come into play, given that it's provider by the Iterable.
Also in order for this to work, the Iterable
- you're using Page
iirc - must implement the Traverse
TypeClass: https://arrow-kt.io/docs/next/apidocs/arrow-core-data/arrow.typeclasses/-traverse/Alexander Schell
08/07/2020, 8:38 AMAlexander Schell
08/07/2020, 8:38 AMAlexander Schell
08/07/2020, 8:41 AMPatrick Louis
08/07/2020, 10:37 AM@higherkind
annotation. if you need any help with that let me know πAlexander Schell
08/08/2020, 2:00 PMAlexander Schell
08/08/2020, 2:10 PMAlexander Schell
08/08/2020, 2:10 PMPatrick Louis
08/10/2020, 6:01 AMPage<D>
objects to its content D
? If so that can be achieved with
val items: SequenceK<Either<Throwable,Page<D>>>
items.map{ either -> either.map { page -> page.whateverExtractsTheContent() } } // SequenceK<Either<Throwable,D>>
This would not evaluate the pages in parallel however.Patrick Louis
08/10/2020, 6:48 AMfun fetchEventsByStatusSafe(
eventStatus: EventStatus,
fetchBatchSize: Int
): SequenceK<Either<Throwable, Event?>> {
return generateSequence(fetchPageSafe(eventStatus, PageRequest.of(0, fetchBatchSize))) {
IO.fx {
val current = !it
if (current?.hasNext() == true) !fetchPageSafe(eventStatus, current.nextPageable()) else null // Page<Event>?
}
}.k().parTraverse(SequenceK.traverse()) {
it.map { current ->
current?.whateverGetsTheContent()
}.attempt()
}.unsafeRunSync().fix()
}
private fun fetchPageSafe(
eventStatus: EventStatus,
pageable: Pageable
): IO<Page<Event>?> {
return IO {
eventRepository.findAllByStatus(eventStatus.eventStatusId, pageable, EVENT_WITH_PARAMETERS_GRAPH).right()
}
}
This will also run the current?.whateverGetsTheContent()
in parallel.Alexander Schell
08/10/2020, 3:37 PMPatrick Louis
08/11/2020, 7:35 AMList<Option<A>>
to Option<List<A>>
you can search for it like this:
https://hoogle.haskell.org/?hoogle=f%20t%20a%20-%3E%20t%20f%20a
the results will most likely also be found in arrow under a similar name.
Cheers,
PatrickAlexander Schell
08/11/2020, 8:26 AM