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