Caching constraint check results per-constraint is probably too inefficient to be of any use, so we should probably cache the full results of checking constraints on one entity as one blob.
If there’s a cache hit, we can go over the cached results and, for each result, check if it’s potentially stale: “commons link”, “type”, “value type”, and “unique value” results are always potentially stale (and the response we send should indicate that, see T179844); results for all other constraint types will be known to be fresh if we set up correct purging. (This means that for most constraint types, we don’t need to show the user “this result may be stale”.)
If there’s a cache miss, we do the normal constraint check process, store the result in the cache, and also set it up so that it will be purged when the entity is edited, and (for “inverse”, “symmetric” and “target requires claim”) when certain other entities are edited. I’m not sure how best to do this – should we register some hook that explicitly purges the cache when those entities are edited, or should we record their revision IDs inside the cached blob and check if it’s still fresh when retrieving it?
(If the purging on edits of other entities turns out to be too difficult, we can instead add “inverse”, “symmetric” and “target requires claim” to the constraint types whose results may be stale.)