Splitting this off from #111127: Cache node_load.
The main objection to that patch is that we need special logic in hook_$object_load() modules to clear the cache for $object when they update their data independently of $object_save or $object_load (i.e. taxonomy, book, nodereference and lots of other modules).
What we could consider doing do is abstract some of the cache clearing logic to a few central hooks and implementations. It's possible we could centralise the bulk of the work for field providing modules (find the ids of all objects which have a nodereference field pointing to $nid, then clear the object cache for those objects), hook_$object_$op() modules would still need special casing, but it'd be special casing inside a hook implementation - and they're already special casing by using hook_$object_$op() in the first place.
Very rough sketch of how this might look:
function node_cacheable_objects() {
return array('node');
}
function taxonomy_term_delete($tid) {
// Or this could be a hook_taxonomy_term_delete implementation.
cache_clear_object_cache($tid, 'taxonomy_term');
}
function taxonomy_term_update($term) {
cache_clear_object_cache($term->tid, 'taxonomy_term');
}
function cache_clear_object_cache($id, $referenced_thingy_type) {
$cacheable_objects = array();
foreach (module_implements('cacheable_objects') as $module) {
$cacheable_objects += $module . '_cacheable_objects';
}
foreach ($cacheable_objects as $object_type) {
$function = $referenced_thingy_type . '_clear_object_cache';
$function($id, $object_type);
}
}
function taxonomy_term_clear_object_cache($tid, $object_type) {
if ($object_type = 'node') {
// same as current patch because we only implement hook_node_load() currently.
}
// or use field API scalar searching to get ids for any object which references the tid, then do:
cache_clear_all($ids, 'cache_' . $object);
}
The field API stuff would depend on #392494: Fields API needs to allow searching of scalars - but even with that it's only going to work if caching is done at the object level, with easily accessible cids - doing it with cache_field cids would be a complete pain - see arguments in the cache node_load() issue.
With something like that it'd mean making other first class core objects cacheable would be a matter of copy/paste from node_load_multiple for the actual cache saving and loading, then implementing one hook - and only modules using hook_$object_load() instead of field API would need to do major special casing. However, we'd still get the extra performance benefit and simplicity of being able to cache the full objects, and only clear caches for specific objects as well.
Comments
Comment #1
yched commentedI'm not sure I see how field cache ids are so terrible. They are composed of obj_type : id : vid (= id if no revisions).
field_attach_query would get you all these informations.
At worst, I'm not even sure it's worth bothering with caching field values for non-current object revisions - in which case it would be obj_type : id.
I guess we can, however, separate field caching into as many tables as fieldable entities. In this case, it would probably be the job of the module defining the fieldable entity to define the [entity]_field_cache table.
Comment #2
catchHmm, maybe it's not quite so bad.
Would boil down to:
vs.
However to do this abstractly you'd have to use field_attach_extract_ids() wouldn't you? Still seems like extra work for no obvious benefit as far as I can see.
Comment #3
joshk commentedThis makes sense. >90% of the use-case out there is for people wanting to stick fields on nodes. If I'm creative and want to develop my own object, or I do something off-the-wall around nodes, then I take responsibility for caching/clearing as dictated by my use-case.
Giving developers this power is good. It should be transparent to most administrators and end-users, except that with a modern caching infrastructure their site will be crazily faster.
Comment #4
catchMarking as duplicate of #460320: Standarized, pluggable entity loading (nodes, users, taxonomy, files, comments) which would allow any first class entity in Drupal to be cached from contrib (and by maintaining their own caches, we wouldn't need to worry so much about clearing them from reference fields).