Caching
All models handled via the connector are, by default, cached in memory by:
- Primary key
- Unique fields
Refreshing Models
While in most scenario caching is good and you'll benefit from it, it does slightly
change the semantics of refresh_from_db
: this will effectively refresh from cache,
not from the database.
If you're using refresh_from_db
simply to discard the unsaved changes you've made to
a model and "reset" to the original state, that's ok.
If instead, you need to absolutely make sure to get the latest value from the database
then you can temporarily disable the cache with the gcloudc.context_decorators.disable_cache
context manager:
from gcloudc.context_decorators import disable_cache
with disable_cache():
instance.refresh_from_db()
You can also disable the cache globally by setting GCLOUDC_CACHE_ENABLED
to False
.
Warning: if you disable the cache, you may have weird behaviour inside transactions. Read on!
Inside transactions
The connectors cache is particularly useful inside transactions. In datastore transactions, any write done inside of it will note be "seen" until the transaction is committed, which would lead to scenario like this
with transaction.atomic():
obj = Model.object.create(...)
...
Model.object.get(pk=obj.pk) # <-- raises Model.DoesNotExists
This is generally not what you want, but you'll only have to worry about it if you disable the cache.
Non-unique queries
Only "unique[^*]" queries are performed on the cache. Non-unique queries will still be performed on the underlying datastore instance.
If, inside a transaction, you're performing a query on a kind that has been modified in that same transaction, the query won't see those changes.
For example
number = IntegerModel(value=1)
number.save()
with transaction.atomic():
number.value = 100
bigger_than_10 = IntegerModel.objects.filter(value__gt=10).count()
# bigger_than_10 == 0 here, the query didn't pick up the change outside the transaction
[^*]: By unique here we mean a query that will return either 1 or no result as a consequence
of a unique constraint: this includes queries by primary key, query with an equality filter
or a unique=True
field or queries with equality filters on all fields for a unique_together
constraint