You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When using DJANGO_FSM_LOG_STORAGE_METHOD = 'django_fsm_log.backends.CachedBackend', a cache is used to stash unsaved log instances created during the pre transition callback. These unsaved StateLog instances are then retrieved and saved as part of the post transition callback.
Problems arise when DJANGO_FSM_LOG_CACHE_BACKEND points to a shared cache, since the PendingStateLogManager._get_cache_key_for_object method doesn't differentiate cache keys between between different requests. This results in StateLog instances being lost if multiple concurrent requests change the state of a single object. This could be solved by either including request identifying details in the cache key, or by using a specialised cache backend (such as django-request-cache). Better yet, the StateLog instance should be stashed on the related object itself.
Easy enough to fix, however...
I've seen code that relies on current cache semantics. More specifically, I have code that approximates the behaviour of queryset.select_for_update() to ensure pending StateLog instances are written to the DB before proceeding:
# wait for pending StateLog instances to be written to the DB before querying# to find the most recent instanceswhile(StateLog.pending_objects.get_for_object(instance) isnotNone):
sleep(0.05)
This results in StateLog instances being lost if multiple concurrent requests change the state of a single object.
This part of the problem is actually quite common and can occur simply as a result of double-clicking a form submit button, which can occur for lots of different reasons. Of course solutions for preventing double submission exist, but there are other causes such as multiple users working on a single object simultaneously that should be handled as well.
When using
DJANGO_FSM_LOG_STORAGE_METHOD = 'django_fsm_log.backends.CachedBackend'
, a cache is used to stash unsaved log instances created during the pre transition callback. These unsaved StateLog instances are then retrieved and saved as part of the post transition callback.Problems arise when
DJANGO_FSM_LOG_CACHE_BACKEND
points to a shared cache, since thePendingStateLogManager._get_cache_key_for_object
method doesn't differentiate cache keys between between different requests. This results in StateLog instances being lost if multiple concurrent requests change the state of a single object. This could be solved by either including request identifying details in the cache key, or by using a specialised cache backend (such as django-request-cache). Better yet, the StateLog instance should be stashed on the related object itself.Easy enough to fix, however...
I've seen code that relies on current cache semantics. More specifically, I have code that approximates the behaviour of
queryset.select_for_update()
to ensure pending StateLog instances are written to the DB before proceeding:Changing current cache semantics would break code like this. This wouldn't be so bad except that it seems to be supported behaviour.
I'm not sure how to proceed, any help would be appreciated.
The text was updated successfully, but these errors were encountered: