Page MenuHomePhabricator

[EXP] Evaluate removing WANObjectCache 'minAsOf' option, in favor of 'touchedCallback'
Open, In Progress, MediumPublic

Description

@Krinkle and I have been discussing reducing WANObjectCache callback options. To begin with, we're surveying consumers of minAsOf and we want to attempt to replace them with the touchedCallback.

A Codesearch survey: https://codesearch.wmcloud.org/deployed/?q=%27minAsOf%27+%3D%3E shows the usage pattern such as:

$value = $this->wanCache->getWithSetCallback(
	$key,
	TTL,
	function () { // callback definition },
	[ 'minAsOf' => INF ]
)

... with a few other unique cases that are fundamentally variants of the above snippet. This pattern forces the getWithSet callback to run every time, bypassing the TTL, since we want to double-check that the cache value is "fresh" and can be reused. If otherwise, the cache should be re-computed synchronously in the current function call with the new value returned to the caller.

We think that it is possible to replace the usage of minAsOf with touchedCallback in these cases, and want to try it out there by potentially (if possible) removing the option if having both is redundant (based on usage needs). This could turn out to be *not true*, and the experiment could be closed, with lessons captured and documented for a future audience.

The replacement for the majority of the cases, per the survey, would be something like:

$value = $this->wanCache->getWithSetCallback(
	$key,
	TTL,
	function () { // callback definition },
	[ 'touchedCallback' => fn () => time() ]
)

or

$value = $this->wanCache->getWithSetCallback(
	$key,
	TTL,
	function () { // callback definition },
	[ 'touchedCallback' => fn () => INF ]
)

The key result we want to achieve (with the bigger picture in mind) is to reduce the number of callback options provided by WANCache, thereby reducing what developers need to understand and making it more likely they'll use the platform and use it correctly, instead of avoiding it or using the wrong option due to there being too many similar capabilities provided.

Related Objects

Event Timeline

Krinkle renamed this task from [EXP] Review & replace usage of 'minAsOf' option with 'touchedCallback' for WANObjectCache consumers to [EXP] Evaluate removing WANObjectCache 'minAsOf' option, in favor of 'touchedCallback'.Jan 9 2026, 8:49 AM
Krinkle updated the task description. (Show Details)

Change #1226217 had a related patch set uploaded (by D3r1ck01; author: Derick Alangi):

[mediawiki/extensions/CentralAuth@master] User: Replace WANCache::getWithSet 'minAsOf' callback options

https://gerrit.wikimedia.org/r/1226217

Change #1227856 had a related patch set uploaded (by D3r1ck01; author: Derick Alangi):

[mediawiki/core@master] Storage: Use 'touchedCallback' in NameTableStore::getName()

https://gerrit.wikimedia.org/r/1227856

Change #1227860 had a related patch set uploaded (by D3r1ck01; author: Derick Alangi):

[mediawiki/extensions/GrowthExperiments@master] NewcomerTasks: Use 'touchedCallback' for cache value regeneration

https://gerrit.wikimedia.org/r/1227860

Change #1227865 had a related patch set uploaded (by D3r1ck01; author: Derick Alangi):

[mediawiki/extensions/StopForumSpam@master] DenyListManager: Use 'touchedCallback' for cache regeneration

https://gerrit.wikimedia.org/r/1227865

Notes and findings

Using [ 'touchedCallback' => static fn () => time() ] to always force a touched callback method run poses a problem. In PHPUnit tests, if tests are written so that running the callback is too fast (back-to-back), e.g., CentralAuthUserUsingDatabaseTest::testGetBlocksExecute() (ref), then the tests break because, from the perspective of the running tests, the question "when did the getWithSet callback last run?" will respond with "now" since the callback can be called several times within the same second. We have 3 ways of resolving, but they're not great:

  • [worse idea] Using sleep( 1 ) in tests is not recommended, I think, but I tried this out locally to verify if we need at least a second passing to make time() work correctly in tests with this option (touchedCallback). That worked, proving that if the callback was last run less than a second ago, calling it again won't re-run/force-run the getWithSet callback. Also, we can't intentionally introduce a delay (even 1 second) in our test pipeline just to make a test pass, as that might add up in CI and cause unnecessary delay in our CI pipeline? I've seen some PHPUnit usage patterns in our codebase, so maybe it's not very terrible?
  • [slightly better] Since we're already using time() to force run the callback with the touched callback, I thought of something that measures time at a smaller/microscopic scale. PHP has options like microtime(), hrtime(), etc. microtime( true ) could work, since it returns a timestamp with floating-point precision. But hrtime() time has been ruled out.
  • [slightly better than both above] Using INF as the value of the touched callback. We're already using minAsOf with INF to force-run the callback, so we could replicate the behavior by using the touched callback's value (for simple cases). This works in tests (even for those that run the callback multiple times per second), so we could just reuse the concept here too.
Krinkle triaged this task as Medium priority.

Change #1242488 had a related patch set uploaded (by D3r1ck01; author: Derick Alangi):

[mediawiki/extensions/CentralAuth@master] CentralAuthUser: Refactor `::getBlocks()` to use 'touchedCallback'

https://gerrit.wikimedia.org/r/1242488

DAlangi_WMF changed the task status from Open to In Progress.Mar 3 2026, 9:48 AM

Change #1226217 abandoned by D3r1ck01:

[mediawiki/extensions/CentralAuth@master] User: Replace WANCache::getWithSet 'minAsOf' callback options

Reason:

Moving forward with https://gerrit.wikimedia.org/r/c/mediawiki/extensions/CentralAuth/+/1242488

https://gerrit.wikimedia.org/r/1226217

Change #1242488 merged by jenkins-bot:

[mediawiki/extensions/CentralAuth@master] User: Refactor `::getBlocks()` to use 'touchedCallback'

https://gerrit.wikimedia.org/r/1242488

Change #1269584 had a related patch set uploaded (by Ladsgroup; author: Ladsgroup):

[mediawiki/extensions/FileAnnotations@master] Remove unneeded complexity regarding caching

https://gerrit.wikimedia.org/r/1269584

Change #1269584 abandoned by Ladsgroup:

[mediawiki/extensions/FileAnnotations@master] Remove unneeded complexity regarding caching

Reason:

Project is archived

https://gerrit.wikimedia.org/r/1269584

haha, the repo is archived.

Yes, @Ladsgroup, plus we realized this is not a deployed extension, too, you see. So I think you can just continue with your work without worrying about breaking anything. ;)

If you find a place you're interested in around removing this option, you can just flag it here, and we can try to assist you.

Change #1227865 merged by jenkins-bot:

[mediawiki/extensions/StopForumSpam@master] DenyListManager: Use 'touchedCallback' for cache regeneration

https://gerrit.wikimedia.org/r/1227865

Change #1300297 had a related patch set uploaded (by Krinkle; author: Krinkle):

[mediawiki/core@master] ObjectCache: Improve test coverage of touchedCallback option

https://gerrit.wikimedia.org/r/1300297