-
-
Notifications
You must be signed in to change notification settings - Fork 87
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
Refactor ModelObserver
and Fix Test Warnings for Consistency and Safety
#208
base: master
Are you sure you want to change the base?
Conversation
What about making some larger changes to the class: Do all the message building (for all actions) before the commit. And then on commit send them all. This way the messages for delete will not be sent if the transaction is rolled back, but they will still have access to the pk. You could have Then have |
Thank you for your suggestion! I really like the idea of handling all message building before the commit and then sending them on commit. It makes a lot of sense to ensure consistency and proper rollback handling. I'll work on implementing this approach tomorrow. |
ModelObserver
and Fix Test Warnings for Consistency and Safety
hishnash, I'm done! Pytest results: |
Looks like the tests are all timing out, you might need to bump some package versions to match your local setup. https://github.com/NilCoalescing/djangochannelsrestframework/blob/master/setup.py. and in requirements.txt maybe would be good to pin these to a new version. |
…ges in some tests.
I’ve fixed everything and tested it again. I updated the list of dependencies and ran the tests once more. There were two errors in the tests: in two cases, after subscribing to database changes, instances of the model we are observing were immediately created, and the communicator was requested for a message. As a result, a TimeoutError occurred because the subscription process was not completed before the model creation. Could you please let me know if the solution with a timeout works for you? Alternatively, in my code, I handle this differently: in every "subscribe" action, I always send a response to the client confirming that the subscription is established. This way, even in the tests, we can wait for a response before inserting data into the database to ensure that the observer works as expected. I believe this approach would be more deterministic. Also, I want to note that during the first test run, before starting development, I encountered an error stating that the |
…d readability and flexibility
In this latest commit, I refactored two test cases where multiple websocket connections are established, and one of them is terminated during execution. Previously, the code used nested async with connected_communicator(TestOtherConsumer()) as communicator1:
async with connected_communicator(TestUserConsumer()) as communicator2: This was replaced with a more concise and flexible approach using async with AsyncExitStack() as stack:
communicator1 = await stack.enter_async_context(connected_communicator(TestOtherConsumer()))
communicator2 = await stack.enter_async_context(connected_communicator(TestUserConsumer())) This change improves readability and offers greater flexibility for managing multiple connections, making it easier to modify or extend in future test scenarios. @hishnash I think I’m done with all the updates and fixes. Tests are now passing in both the Pytest results: |
@hishnash hi! I discovered a critical bug in the With the fix implemented in this PR, the unsubscribe logic now works as expected, ensuring proper cleanup of observer groups even when specific Please don’t be alarmed by the size of this PR (+1,366 −1,318), as the majority of the changes are due to indentation updates from refactoring tests to use asynchronous context managers consistently. The actual logic changes are around 100 lines, with a couple of hundred lines added for new test cases. |
I see that some tests have failed, and this surprises me. To be honest, I only tested the code with Python 3.12 and Django 5. I’ll try to check it on other dependency versions in the coming days and make adjustments to the code or tests. |
I identified the issue causing some tests to fail. The consumer was not unsubscribing from username: thenewname in time, likely due to slower machine performance during test execution. This resulted in the communicator receiving a message unexpectedly. To fix this, I increased the asyncio.sleep timeout to 2 seconds, ensuring sufficient time for the consumer to complete the unsubscribe action. This change should improve test reliability across different environments. |
Ensure test consumers send JSON responses confirming subscription and unsubscription actions. Update tests to validate the new response payloads for improved accuracy and clarity. Fix timeout error on slow machines by explicitly waiting for subscription and unsubscription confirmation before proceeding with further test execution.
I fixed the tests to eliminate timeout errors. Now, whenever subscribing or unsubscribing to changes, we explicitly wait for the consumer's response before proceeding further in the test. Please, run the test workflow in GitHub to verify the fixes. |
To ensure test isolation and prevent signals from being received across tests, I added unique suffixes to group names in each test. This resolves the issue of overlapping group names causing unexpected behavior in asynchronous tests. |
This PR includes three key updates to improve the functionality and reliability of the ModelObserver, the Observer unsubscribe logic, and the test suite:
Refactor ModelObserver for transaction safety:
prepare_messages
,generate_messages
,send_prepared_messages
) to enhance code clarity and consistency.Fix unsubscribe logic in Observer:
unsubscribe
method of theBaseObserver
class that caused theremove_group
method to not be called under certain conditions due to incorrect logic.request_id
is provided or groups become empty.unsubscribe
logic now works as expected in all scenarios.Fix warnings and improve test suite:
Task was destroyed but it is pending!
caused by improper cleanup in tests.__test__ = False
to test models to prevent pytest from misinterpreting them as test cases.Benefits:
ModelObserver
for DELETE actions.unsubscribe
logic, ensuring proper resource cleanup and reliability.This PR significantly improves the reliability and maintainability of the ModelObserver implementation, Observer unsubscribe logic, and the associated test suite.