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

fix(core): Allow retries for errored async reads #705

Merged
merged 3 commits into from
Sep 12, 2021

Conversation

Pinpickle
Copy link
Contributor

When changing a dependency for an atom in an error state, the derived atom's read function is re-run.

We'd expect that if that re-run is successful, useAtom will return the new value.

This is currently the case with sync atoms, but not async atoms. This PR fixes that, and adds tests (the async variant was failing, but the sync one wasn't).

Fixes #601

@vercel
Copy link

vercel bot commented Sep 12, 2021

This pull request is being automatically deployed with Vercel (learn more).
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: https://vercel.com/pmndrs/jotai/5YLw1D1DieaXtDJsxuzLoWQCfC59
✅ Preview: https://jotai-git-fork-pinpickle-fix-error-recovery-pmndrs.vercel.app

@codesandbox-ci
Copy link

codesandbox-ci bot commented Sep 12, 2021

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 3362181:

Sandbox Source
React Configuration
React Typescript Configuration
React Browserify Configuration
React Snowpack Configuration
Next.js Configuration

@@ -95,32 +70,3 @@ it('writable count state', async () => {
fireEvent.click(getByText('button'))
await findByText('count: 9')
})

// FIXME we would like to support retry
it.skip('count state with error', async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test wasn't valid - an observable can't recover from an error state. For the notion of "retrying" observables to work, the error would never reach atomWithObservable, so the retrying logic is out of scope for jotai.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I didn't know about the observable error behavior, and created this test. But, it's an expected behavior.
Now, you find the actual issue of error async reads, and fix it. Very very nice.

@@ -177,6 +177,7 @@ export const createStore = (
return
}
atomState.c?.() // cancel read promise
delete atomState.e // read error
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was being done when writing to a sync atom, but not an async atom.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow! Nice catch!
Feels like you have fairly deeper understanding of core.

Copy link
Member

@dai-shi dai-shi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing. You did great work here.

@@ -177,6 +177,7 @@ export const createStore = (
return
}
atomState.c?.() // cancel read promise
delete atomState.e // read error
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow! Nice catch!
Feels like you have fairly deeper understanding of core.

tests/error.test.tsx Outdated Show resolved Hide resolved
@@ -95,32 +70,3 @@ it('writable count state', async () => {
fireEvent.click(getByText('button'))
await findByText('count: 9')
})

// FIXME we would like to support retry
it.skip('count state with error', async () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I didn't know about the observable error behavior, and created this test. But, it's an expected behavior.
Now, you find the actual issue of error async reads, and fix it. Very very nice.

@dai-shi dai-shi changed the title fix: Allow retries for errored async reads fix(core): Allow retries for errored async reads Sep 12, 2021
@@ -492,7 +492,7 @@ describe('error recovery', () => {
await findByText('Value: 1')
})

it.only('recovers from async errors', async () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops - thank you!

@Pinpickle
Copy link
Contributor Author

Thanks @dai-shi 🎉

Hopefully we can get this merged before #698, which means I can bring back the failing test

@dai-shi
Copy link
Member

dai-shi commented Sep 12, 2021

Hopefully we can get this merged before #698, which means I can bring back the failing test

Yes, that's my plan too.

Seems like a test fails. Is this because our tests are not stable enough because we don't properly use fake timers?

@Pinpickle
Copy link
Contributor Author

Pinpickle commented Sep 12, 2021

Seems like a test fails. Is this because our tests are not stable enough because we don't properly use fake timers?

This was because of less mode and meant the atom state was shared between tests

I've fixed it now - could you run the workflow again?

@dai-shi
Copy link
Member

dai-shi commented Sep 12, 2021

This was because of less mode and meant the atom state was shared between tests

I see.

@dai-shi dai-shi merged commit 6d2ae55 into pmndrs:main Sep 12, 2021
@Pinpickle Pinpickle deleted the fix-error-recovery branch September 12, 2021 23:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

atomWithObservable can't recover from error (and also with any atoms?)
2 participants