Hi Alex,
I would agree, `Connection.connectionFromSeq` can help here. Generally, Relay uses cursor-based pagination, but it's possible to translate it to offset+limit based pagination. I will use `offset` instead of `page` since it's a bit more general concept, but "page" generally represents the same thing (if I understand correctly, in your case page represents a specific number of elements, so `offset = page * limit`).
`connectionFromSeq` is a very simple implementation of connection that uses an element index as a cursor. `index == offset`, so here is how you can use it.
First of all, you need to be able to convert connection arguments (`after`, `before`, `first`, `last`) to a `limit` and `offset`. Here is one example of how you can do it:
case class OffsetLimit(offset: Int, limit: Int)
def getOffset(cursor: Option[String], defaultOffset: Int): Int =
cursor flatMap Connection.cursorToOffset getOrElse defaultOffset
def calculateOffsetLimit(args: ConnectionArgs, total: Int): OffsetLimit = {
val fromOffset = getOffset(args.after, 0)
val toOffset = getOffset(args.before, total - 1)
val startOffset = args.last.fold(fromOffset)(last ⇒ toOffset - last)
val endOffset = args.first.fold(toOffset)(first ⇒ math.min(toOffset, startOffset + first))
OffsetLimit(offset = startOffset, limit = endOffset - startOffset)
}
As you probably noticed, you will also need `total` number of entities in the DB/external service. Without it, you would not be able to cover all possible pagination scenarios allowed by relay (it's pretty flexible in this respect).
Now that you have `calculateOffsetLimit` you can use it to calculate offset and limit and load data from external service:
val offsetAndLimit = calculateOffsetLimit(args, total)
val data: Seq[Fruit] = fruitService.loadTastyFruits(offsetAndLimit)
Now `connectionFromSeq` comes into play. `data` contains only a slice of the actual dataset, so you will need to use `SliceInfo` to tell `connectionFromSeq` which part of the data this is:
Connection.connectionFromSeq(data, args, SliceInfo(offsetAndLimit.offset, offsetAndLimit.limit))
This will give you a `Connection[Fruit]` which contains the right page of the data.
I probably made some minor mistakes in the code (just quickly prototyped it), but hope this demonstrated the concept. Let me know if you have further questions.
Cheers,
Oleg