Quick Caching Strategies


Quick is now sufficiently mature that it may be worthwhile to think about implementing a ready-made caching solution.

As a first stab at this, I propose keeping it simple and re-cycling what we've already got.

Since Quick depends on Coldbox already, we can assume that Cachebox is available. I haven't been able to think of any reason why the solution might not be as simple (from a user standpoint) as specifying a Cachebox cache, either in the component definition or else in a specific `.get()` call, similar to how the datasource can be specified globally or per-request.

When Quick first loads a cache-able entity, it fires off a (hopefully parallel) call to hydrate the cache with the properties it has just pulled from the database. Where this gets tricky is obviously the relationships: if I load `Author` do I also cache the `Books` relationship? No, but if I call `.getBooks()` then the related Book entities should also go in the cache. But caching these relationships and collections is perhaps not a first-pass concern.

If we limit the initial implementation to 'load x, cache x' and worry about relationships another time, we just store a memento in our cache and then hydrate from the cache on subsequent calls, with a cache miss falling back to the DB request. Easy enough to clear or update the cache whenever the entity is saved.

I can think of an argument against doing this, which is: given that most modern applications (and their caches) will be distributed, is it really worthwhile to go to all this trouble to save ourselves a trip to the database? Frankly, much of the time, no. Quick is great without any caching. But there are occasions where we have multi-stage interactions involving ten different entities, and only two of them are being updated; having to load all ten in each stage is manageable but there is room to be better!


Brad Wood
February 10, 2020, 6:21 PM

Hibernate has two levels of caching-- just the raw query object and then the CFC entities themselves. I’m curious which of the two you have in mind.

Samuel W. Knowlton
February 10, 2020, 6:27 PM

I think just the raw query object. Stuff we can easily serialize. So you’re still instantiating the entity, but the hydration is coming from the cache rather than queryExecute.

Luis Majano
February 10, 2020, 7:29 PM

Actually, Hibernate never caches the CFC entities. It always stores the raw query data in first level cache. The second level is to off load out of the heap the same raw query data.

Hydration always occurs.

Brad Wood
February 10, 2020, 9:29 PM

Thanks for clarifying. So basically, Quick users would control whether it was a “first level” or “second level” cache by their configuration of the CacheBox cache. I suppose Quick could use the “default” cache out of the box and then the user can change it if they want another?




Samuel W. Knowlton