Comments (12)
I have the same bug. Django-rest-framework 2.2.7 set force_update to True when models update (https://github.com/tomchristie/django-rest-framework/blob/2.2.7/rest_framework/mixins.py#L124).
Do you have any ideas about this?
from django-cacheops.
The simplest alternative is to fetch old object on pre_save
signal. That will add one more db call for any .save()
. Other variant is to catch object attribute writes, preserve old state somehow and then use it in invalidation. This one adds overhead on all attribute writes on instances of cached models.
I'll prefer second one, but it's harder to implement.
from django-cacheops.
Thanks!
I solved this problem in my concrete case by adding .exists() before save (only in force_update case). It's not universal, but enough for now.
I'm interested do you plan to fix this bug?
from django-cacheops.
Some day
from django-cacheops.
You can move "hack" from QuerySetMixin.exists() method to _update(values) method which is called just after (force_update or <check exists()>) condition:
https://github.com/django/django/blob/stable/1.4.x/django/db/models/base.py line 626
It will work in 1.3, 1.4 and 1.5 versions, but in master branch code is different :(
from django-cacheops.
In django master there is a method _do_update, which also calls _update, so fix may work with future versions also.
from django-cacheops.
I'm working on better solution, which will use
http://github.com/Suor/django-dirty
from django-cacheops.
After some research, looks like there is no easy and cheap way to track changes in model instance. Still overriding _update
doesn't make sense, it will lead to extra request to db instead of just using the one done anyway in exists call. And if you are ok making extra request, you should just do it on pre_save
.
from django-cacheops.
Кажется возможно решить проблему хотя бы статистически. По степени критичности проявления ошибки можно выделить:
- Однопоточное исполнение, выбираем объект модели по pk, меняем свойства с force_update и оп! бага с инвалидацией старых значений. При этом объект модели уже находится в кэше на момент выполнения _update. Стандартная ситуация при PUT в djangorestframework 2-че-то-там.
- Однопоточное исполнение, выбираем objects.filter(field_name=field_value)[0], объект есть в кэше, но закеширован не по первичному ключу. При сохранении с force_update вызов _update плодит запрос к БД, но сама ситуация это изменение списка объектов в цикле с использованием force_update. Может и существует в природе, но имхо не часто встречается.
- Многопоточное исполнение, выбираем объект модели по pk, ждем 5 минут, сохраняем с force_update и вот она бага, да еще и с гонками. Статистически редка, и тоже фиксится модификацией _update.
- Многопоточное исполнение, queryset[0], ситуация гонки с модификацией через другой queryset. Мозг вытек обдумывать способы решения данной проблемы, но кажется тут только запрос к БД решит.
Убедил?
It seems that it's possible to fix this bug at least statistically. There are several ways to reproduce this bug with different level of importance.
- Single-threaded: getting object with PK, saving with force_update and here is the bug. At the time of _update call object is already in cache. This usecase is typical for PUT in djangorestframework 2.x
- Single-threaded when changine objects.filter(field_name=field_value)[0]. Object is in cache but not cached with PK value. With _update fix it will query database, but IMHO the usecase is very rare.
- Multi-threaded execution, getting object with PK, waiting for 5 min, saving with force_update and here is the bug with race-conditions. Very rare usecase and could be fixed with _update modification.
- Multi-threaded excution, selecting queryset[0], changing anotherset[3]. It blowed my mind, and I think only DB query could solve it.
Am I right?
from django-cacheops.
I don't understand what point are you trying to make here?
If you are saying that extra request isn't that bad since it will be usually cached anyway then I agree.
If you are trying to convince me to override _update()
then it still doesn't make any sense since attaching handler to pre_save event would be cleaner while being same in efficiency.
from django-cacheops.
I'm saying that fixing pre_save in next release is better than do nothing while trying to propose better decision and it will not harm performance seriously.
from django-cacheops.
Django 1.6+ default behavior is to use pre_save
signal now. Which will bypass this problem. cacheops will still use old algorithm in case select_on_save = True
is set on models Meta
.
It's possible I'll get rid of old faster, but buggy method in future cacheops.
from django-cacheops.
Related Issues (20)
- features to prevent cache stampede HOT 3
- django-cacheops not working with Django version 4 HOT 3
- Unable to disable cacheops primitives HOT 1
- Memory problem on django test init HOT 7
- DB migrations are being cached even after using setting migrations timeout to zero HOT 6
- Issue with signals (ManagerMixin._post_save() missing 1 required positional argument: 'using') HOT 3
- Question on @cached_as HOT 1
- Redis getting called too many times in a single API call. HOT 3
- Django Admin not invalidating cache on save HOT 4
- Nik
- Support for cache invalidation on `bulk_update()` method HOT 3
- AWS Elasticache Redis Serverless Implementation is raising AttributeError HOT 6
- cache wrongly set to empty list for get query (when accessing a foreignkey field) HOT 15
- conj keys always have -1 as expiration in redis 7 HOT 3
- Are we supporting model translation with django cacheops ? HOT 5
- Potential Concurrency Issue Leading to Cache Inconsistency in Multithreaded Environment HOT 6
- Delete operation fails with -OOM command not allowed when used memory > 'maxmemory'. HOT 2
- How to enable caching for 'views' only HOT 3
- @user_script: 36: Unknown Redis command called from Lua script HOT 8
- `conj` key doesnt have expiry when using 7.0.2 HOT 4
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from django-cacheops.