My code is:
@ttl_cache(maxsize=50, ttl=60 * 60)
def get_query_set():
return Model.objects.all().order_by('year')
def get_latest():
cached_qs = get_query_set()
try:
return cached_qs.last().year if len(cached_qs) > 0 else None
except AttributeError:
print('~~~~~~~~~~~~~~~~~')
print('CHECK CIRCLECI PROBLEM')
print(cached_qs)
print(cached_qs.last())
print(len(cached_qs))
for aa in cached_qs:
print(aa)
print(type(aa))
print(dir(aa))
print(hasattr(aa, 'year'))
try:
print(aa.year)
except Exception:
print('no attr for aa')
print(Model.objects.all().order_by('year'))
for aaa in Model.objects.all().order_by('year'):
print(aaa)
print(aaa.year)
print('~~~~~~~~~~~~~~~~~')
raise
Without try-except
I getting (on get_latest()
)
AttributeError: 'NoneType' object has no attribute 'year'
When I catch exception it print:
~~~~~~~~~~~~~~~~~
CHECK CIRCLECI PROBLEM
<QuerySet [<Model: Model object (2)>]>
None
1
Model object (2)
<class 'path.models.model.Model'>
['DoesNotExist', 'Meta', 'MultipleObjectsReturned', '__class__', '__delattr__', ..., 'year']
True
2019
<QuerySet []>
~~~~~~~~~~~~~~~~~
So we can see that
- this problem is reproducible only at CircleCI build sometimes (I don’t know how to reproduce it at local machine)
- cached queryset is not empty
- length of cached queryset is 1
- queryset object is not
None
and has attributeyear
- value of
year
is 2019 - real object is already deleted at DB and does not exist (physically DB table is empty)
- non cached queryset is empty (because of ⑥)
I guess that last()
trying to re-get object from DB even if queryset is cached (because of queryset lazy behaviour?). But I don’t understand why it exactly happens? And what I should expect from last()
output?
I tried to delete Model object from DB manually after cache python queryset, but last()
method working as expected and return value properly.
Any ideas?