Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache exchange not forwarding teardown correctly #215

Closed
federicobadini opened this issue Mar 28, 2019 · 3 comments
Closed

Cache exchange not forwarding teardown correctly #215

federicobadini opened this issue Mar 28, 2019 · 3 comments
Assignees
Labels
bug 🐛 Oh no! A bug or unintented behaviour.
Milestone

Comments

@federicobadini
Copy link
Contributor

Hi,

While I was working on a custom exchange I think I have found something wrong with how the default cache exchange forward requests down to the other exchanges downstream.
I have created a codesandbox to show you the problem.

Basically I have created an exchange that deduplicates queries by cancelling the old request and forwarding the new one (switchMapExchange).
In the example attached, I issue a couple of query at the same point in time.
You'll see that even though I forward teardown actions to cancel the first request of the two, no request is effectively cancelled and unexpectedly both are completed.

Trying to solve the problem, I'm quite convinced that it derives from how the default cacheExchange handle the forward action.
It basically creates different forwarding stream for new and skipped ops and merge those streams afterwards

const newOps$ = pipe(
  sharedOps$,
  filter(op => !shouldSkip(op) && !isOperationCached(op)),
  map(mapTypeNames),
  forward,
  tap(response => {
    if (response.operation.operationName === 'mutation') {
      handleAfterMutation(response);
    } else if (response.operation.operationName === 'query') {
      handleAfterQuery(response);
    }
  })
);

const skippedOps$ = pipe(
  sharedOps$,
  filter(op => shouldSkip(op)),
  forward
);

return merge([cachedOps$, newOps$, skippedOps$]);

In the codesandbox linked above I have included also a slightly modified cache exchange, in which forwarded operation streams are handled differently

const forwardedOps$ = pipe(
  merge([
    pipe(
      sharedOps$,
      filter(op => !shouldSkip(op) && !isOperationCached(op)),
      map(mapTypeNames)
    ),
    pipe(
      sharedOps$,
      filter(op => shouldSkip(op))
    )
  ]),
  forward,
  tap(response => {
    if (response.operation.operationName === "mutation") {
      handleAfterMutation(response);
    } else if (response.operation.operationName === "query") {
      handleAfterQuery(response);
    }
  })
);

return merge([cachedOps$, forwardedOps$]);

This approach solved my problem forwarding correctly teardown actions to default fetchExchange and cancelling request when needed.
Please let me know what you think

@kitten kitten added the bug 🐛 Oh no! A bug or unintented behaviour. label Mar 28, 2019
@kitten
Copy link
Member

kitten commented Mar 28, 2019

That seems absolutely right 👍 forward should also not be called twice. It's possible, but obviously leads to subtle bugs, since it spreads out some of the code.

I can put a fix in as soon as I find the time 🙌 Thank you so much for reporting this! I appreciate that this must have been hard to hunt down!

We should likely implement a test suite that can be run on all exchanges individually to test their compliance. Maybe even add a warning if forward is called multiple times as this will often not be intentional 🤔

For the record, I'm working on a normalised cache for urql that does have an exchange that's implemented correctly (to my knowledge 😆) It's not quite done yet, but probably a nice piece of code to compare the default cache exchange with. https://github.com/kitten/urql-exchange-graphcache/blob/master/src/exchange.ts

I'll post a comment here when I get to this bug, but please let me know if you're interested in opening a PR for a fix, which would be amazing 💯

@kitten kitten added this to the v1 Roadmap milestone Mar 28, 2019
@kitten kitten self-assigned this Apr 5, 2019
@federicobadini
Copy link
Contributor Author

Sorry for the delay. They were very busy days. 😆
I've opened a PR with a proposal to solve this bug. Let me know what you think

kitten added a commit that referenced this issue Apr 7, 2019
Cache exchange not forwarding teardown correctly #215
@kitten
Copy link
Member

kitten commented Apr 7, 2019

No worries! Super happy to have you have helped out here, since we're currently struggling to find enough time to solve the last remaining issues 💯

@kitten kitten closed this as completed Apr 7, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Oh no! A bug or unintented behaviour.
Projects
None yet
Development

No branches or pull requests

2 participants