avenger icon indicating copy to clipboard operation
avenger copied to clipboard

add "Alternative" operator into query DSL

Open mattiamanzati opened this issue 5 years ago • 4 comments

Imagine a scenario where you have 2 different queries, and those queryies take 2 different times to resolve. A real world scenario would be having the same query which one fetches from a local storage, and one fetches from a REST api.

Those 2 queries have the same signature (userId: string) => User, and I would love to compose them so that if the first one is pending or returned an error, the result of the second one is returned. Something along the lines of:

const userQuery = alternative(userFromRestQuery, userFromLocalStorageQuery)

and the behaviour of alternative would be the same as https://github.com/devex-web-frontend/remote-data-ts/blob/master/src/remote-data.ts#L408

Thanks again for the great library!

mattiamanzati avatar Aug 26 '19 07:08 mattiamanzati

The use case makes sense to me, and I think adding an alternative operator would be pretty straightforward 👍 (EDIT: pushed a quick POC here: https://github.com/buildo/avenger/commit/5e74a82cd920b21e65c6322ce07c176bcc562ad7)

As a side note, adding new operators would be an even simpler process if Query was encoded as an fp-ts data-type with all the implemented instances. As of now, we conceptually have Monad, but the encoding is custom since we want:

  1. to have query inputs aggregated as products, and errors as sums, while fp-ts has them both fixed (see e.g. the related discussion in https://github.com/gcanti/fp-ts/issues/904#issuecomment-510433571)
  2. on top of 1, there are a few additional overloads to make usage simpler when declaring product queries from the UI: https://github.com/buildo/avenger/blob/master/src/util.ts#L32

Query could otherwise just be a plain ReaderTaskEither, and compose would just be chain, product->sequenceS, and we could easily add an Alternative instance

giogonzo avatar Aug 26 '19 12:08 giogonzo

I would love to compose them so that if the first one is pending or returned an error, the result of the second one is returned

Actually re-reading this better, this is not what I'd expect by using alt/orElse from Alternative: it would fallback on the second only in case of failure, not also while "loading"

giogonzo avatar Aug 26 '19 12:08 giogonzo

Uhm, yeah that makes sense too! I'm my usecase example that means you'll need to put the localStorage as first, and rest as second, which makes sense

mattiamanzati avatar Aug 26 '19 16:08 mattiamanzati

instances for Alternatives could also be used to simulate a local state. If a locally updated value is present it is used, else the remotely fetched one is returned. This could be a very interesting feature :)

fes300 avatar Nov 06 '19 16:11 fes300