Skip to content

HasFullTableCache

Leonard Richardson edited this page Feb 5, 2021 · 3 revisions

HasFullTableCache is used for a few ORM classes where the best thing for performance is for each application server to keep an entire database table in memory. Individual item lookups are delegated to the in-memory cache rather than going to the database. Some of the ORM classes that implement HasFullTableCache are:

  • Admin
  • AdminRole
  • Collection
  • ConfigurationSetting
  • DataSource
  • DeliveryMechanism
  • ExternalIntegration
  • Genre
  • Library

These classes have two things in common: there's a relatively small number of items in the database table, and the database changes very rarely.

Of course, when the data does change, we run into the problem of cache invalidation, one of the classic "hard problems" of computer science. Multiple application servers may keep caches of the same data. When one of those servers changes the data, all of them must know to invalidate their caches.

That's why the circulation manager checks at the beginning of each request whether the cache needs to be invalidated. We track that information in a special row in the timestamps table (which does not implement HasFullTableCache) where the service field is set to the special value Site Configuration Changed.

Whenever a change is made to one of the tables that implements HasFullTableCache, a listener fires and calls the function site_configuration_has_changed. This function uses a raw SQL command to update the timestamps table with the current date. Any HasFullTableCaches populated before that date are now invalid. We don't try to be clever about it; it's not worth it. Any change to any of these tables invalidates every single HasFullTableCache.

But how does the circulation manager detect that this timestamp has changed? A method called Configuration.site_configuration_last_update retrieves this value from the database. The circulation manager's controller class defines a method called reload_settings_if_changed which checks that value and invalidates all of the HasFullTableCaches if necessary. This method is called by library_for_request and library_through_external_loan_identifier.

This means reload_settings_if_changed will be called very early on when processing basically any incoming request.

Updating the timestamp manually

If you run SQL directly against the database, as opposed to using the ORM, the SQLAlchemy listeners won't trigger and the timestamp won't be updated. This can cause problems if you do this while application servers are running.

Run this SQL to update the timestamp manually:

UPDATE timestamps SET finish=now() WHERE service='Site Configuration Changed' AND collection_id IS NULL;

This will cause all app servers to reload their full-table caches on the next request.

Clone this wiki locally