Skip to content

Add a test case for an extreme scenario #7070

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

Closed
wants to merge 4 commits into from

Conversation

kryon-7
Copy link
Contributor

@kryon-7 kryon-7 commented Apr 9, 2025

Describe the problem you have without this PR

Because there is a test case that may fail intermittently (uncertain) #7069 , I am now adding more extreme test cases.

@kryon-7 kryon-7 changed the title Add a use case for an extreme scenario Add a test case for an extreme scenario Apr 9, 2025
@pubkey
Copy link
Owner

pubkey commented Apr 14, 2025

Hi @kryon-7
So this only fails on the memory-random-delay storage which. This storage is only made to fetch additional stuff, it does not behave like a "real" storage. Do you think you could change the test to fail in one of the real storages?

@kryon-7
Copy link
Contributor Author

kryon-7 commented Apr 14, 2025

@kryon-7 hello!I have identified the cause. It's because the handling of external modifications and internal modifications are not in the same queue. When creating an rx-state, an Observer is created to monitor external modifications to the collection, while internal modifications are processed using the _writeQueue. The execution order between these two is uncontrollable, which leads to concurrency issues. Theoretically, this problem should occur in all cases, but perhaps the inconsistent speed of processing internal and external modifications in other real storage systems makes the error harder to reproduce.
Below is our expected flow.
image
But Scenario:
Assume StateA first calls insert() to set num=1 and succeeds.

However, we know the insert method's workflow:

First, it actually stores the data in the storage.

Then, it broadcasts a notification.

Finally, it returns.

Race Condition:
Once the data is stored in the storage, other states (e.g., StateB) can modify it.

At this point, StateA’s insert() request might not have returned yet, but StateB has already started modifying the data (e.g., setting num = 1 + 1 = 2).

The storage applies StateB’s change (num=2) and broadcasts the update.

StateA receives the notification and updates its num to 2.

The Problem:
But await insert() in StateA still hasn’t resolved! (This is possible!)

Meanwhile, StateA has already accepted num=2 from StateB’s update.

When StateA’s await insert() finally returns successfully, it reverts num from 2 back to 1, causing inconsistency!

image I already know how to fix this issue to prevent it from occurring, but accurately reproducing the error will require more time to study the source code and write non-intrusive tests. Sorry I haven't had time recently, but I'll write a proper test case for this bug in the next few days.

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.

None yet

2 participants