Open kegsay opened 2 months ago
It could probably use a sentinel instead of None to know if it uncached?
Maybe the mypy plugin is missing this coercion?
That should probably handle cachedList
too?
It could probably use a sentinel instead of None to know if it uncached?
That's what I had to do for bulk_get_room_type
and bulk_get_room_encryption
in https://github.com/element-hq/synapse/pull/17450
Related discussion: https://github.com/element-hq/synapse/pull/17450#discussion_r1678786409
I think the historical context for this is that it was very much expected that a value was returned for every key, i.e. the bulk fetch function should return the exact same thing as just calling the non-bulk function in a loop. The common case for store functions that couldn't find a row is to return None, and so that is likely why we treated missing values as None.
However, there are now quite a few functions that don't actually have a non-bulk equivalent, and so it could make sense for those functions not to return everything.
Agreed this is a footgun, and we probably should make @cachedList
error if the function doesn't return an entry for each item. I'm not super keen on adding sentinel values in there by default, as it breaks the idea that @cachedList
should behave like calling @cached
function in a loop
The docs for this state:
This is not semantically the same as absence of a key, and creates very subtle failure modes. I just spent an hour or two trying to figure out how a function could possibly set None and well, it can't. It turns out the cache is doing it because some rooms don't have entries in the DB. The function in question is https://github.com/element-hq/synapse/blob/51dd4df0a317330d0679e48d7a6dcd5abb054ec7/synapse/storage/databases/main/stream.py#L1495
Unfortunately, the caller of this function never did a None check causing runtime failures: see https://github.com/element-hq/element-x-ios/issues/3300#issuecomment-2358222041
It is absolutely not clear that adding a cache decorator would change the semantics like this. I suggest we double check every caller of these functions to make sure they
None
check before usage.