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: User profile not found on account creation #56

Merged
merged 1 commit into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ Change Log
Unreleased
**********

0.9.5 - 2024-05-24
******************

Fixes
=====

* UserProfile sink now runs after the transaction is committed, preventing UserProfileNotFound errors and creation of rows in ClickHouse that don't exist in MySQL in the case of a rollback.


0.9.4 - 2024-05-16
******************

Expand Down
2 changes: 1 addition & 1 deletion platform_plugin_aspects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
import os
from pathlib import Path

__version__ = "0.9.4"
__version__ = "0.9.5"

ROOT_DIRECTORY = Path(os.path.dirname(os.path.abspath(__file__)))
24 changes: 19 additions & 5 deletions platform_plugin_aspects/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Signal handler functions, mapped to specific signals in apps.py.
"""

from django.db import transaction
from django.db.models.signals import post_save
from django.dispatch import Signal, receiver

Expand Down Expand Up @@ -33,11 +34,9 @@ def receive_course_publish( # pylint: disable=unused-argument # pragma: no cov
dump_course_to_clickhouse.delay(str(course_key))


def on_user_profile_updated( # pylint: disable=unused-argument # pragma: no cover
sender, instance, **kwargs
):
def on_user_profile_updated(instance):
"""
Receives post save signal and queues the dump job.
Queues the UserProfile dump job when the parent transaction is committed.
"""
# import here, because signal is registered at startup, but items in tasks are not yet able to be loaded
from platform_plugin_aspects.tasks import ( # pylint: disable=import-outside-toplevel
Expand All @@ -52,11 +51,26 @@ def on_user_profile_updated( # pylint: disable=unused-argument # pragma: no co
)


def on_user_profile_updated_txn(**kwargs):
"""
Handle user_profile saves in the middle of a transaction.

If this gets fired before the transaction commits, the task may try to
query an id that doesn't exist yet and throw an error. This should postpone
queuing the Celery task until after the transaction is committed.
"""
transaction.on_commit(
lambda: on_user_profile_updated(kwargs["instance"])
) # pragma: no cover


# Connect the UserProfile.post_save signal handler only if we have a model to attach to.
# (prevents celery errors during tests)
_user_profile = get_model("user_profile")
if _user_profile:
post_save.connect(on_user_profile_updated, sender=_user_profile) # pragma: no cover
post_save.connect(
on_user_profile_updated_txn, sender=_user_profile
) # pragma: no cover


def on_externalid_saved( # pylint: disable=unused-argument # pragma: no cover
Expand Down
4 changes: 2 additions & 2 deletions platform_plugin_aspects/xblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@

# These moved from xblockutils to xblock in Quince, these can be removed
# when we stop supporting earlier versions.
try: # pragma: no-cover
try: # pragma: no cover
from xblock.utils.resources import ResourceLoader
from xblock.utils.studio_editable import StudioEditableXBlockMixin
except ImportError:
except ImportError: # pragma: no cover
from xblockutils.resources import ResourceLoader
from xblockutils.studio_editable import StudioEditableXBlockMixin

Expand Down
Loading