Fixed XF web upgrade exposes half-upgraded state to caching layer

Xon

Well-known member
Affected version
XF 2.3.0 Beta 3
Related to;

Updating XF2.2 => XF2.3 fails when my Redis Cache add-on is installed in some cases.

XF2.3 Beta 3 now fails with a different error which is the result of the XF2.2 code being loaded while the XF2.3 code is being deployed.

SV\RedisCache\Redis checks \XF::$versionId to determine if it should load the version of the cache provider which extends Doctrine Cache or Symfony's Cache.

Even if the RedisCache add-on didn't check \XF::$versionId, it would still error as XF2.3 deploys an incompatible version of Doctrine Cache's Doctrine\Common\Cache\CacheProvider class.

It looks like src/XF.php is copied fairly late (rather than just after the composer dependencies), so code which depends on checking \XF::$versionId doesn't work as expected.

web upgrade XenForo 2.2.15 -> XenForo 2.3 beta 3 w/ redis addon installed.
Previous error got fixed according to devs
but now the upgrade stops with different error at the same step as before (verifying and copying files stage):
Code:
PHP Fatal error:  Declaration of SV\RedisCache\DoctrineCache\CacheProvider::delete($id) must be compatible with Doctrine\Common\Cache\CacheProvider::delete(string $id): bool in /var/www/[redacted]/public/src/addons/SV/RedisCache/DoctrineCache/CacheProvider.php on line 105
PHP Fatal error:  Uncaught Error: Class "SV\RedisCache\Redis" not found in /var/www/[redacted]/public/src/XF/CacheFactory.php:68
Stack trace:
#0 /var/www/[redacted]/public/src/XF/CacheFactory.php(36): XF\CacheFactory->instantiate('...', Array)
#1 /var/www/[redacted]/public/src/XF/App.php(709): XF\CacheFactory->create('...', Array)
#2 /var/www/[redacted]/public/src/XF/Container.php(234): XF\App->XF\{closure}('', Array, Object(XF\Container))
#3 /var/www/[redacted]/public/src/XF/App.php(2661): XF\Container->create('...', '')
#4 /var/www/[redacted]/public/src/XF/App.php(736): XF\App->cache('...')
#5 /var/www/[redacted]/public/src/XF/Container.php(31): XF\App->XF\{closure}(Object(XF\Container))
#6 /var/www/[redacted]/public/src/XF/Install/App.php(73): XF\Container->offsetGet('...')
#7 /var/www/[redacted]/public/src/XF/Container.php(31): XF\Install\App->XF\Install\{closure}(Object(XF\Container))
#8 /var/www/[redacted]/public/src/XF/App.php(2704): XF\Container->offsetGet('...')
#9 /var/www/[redacted]/public/src/XF.php(838): XF\App->options()
#10 /var/www/[redacted]/public/src/XF/Entity/User.php(2431): XF::options()
#11 /var/www/[redacted]/public/src/XF/Mvc/Entity/Manager.php(72): XF\Entity\User::getStructure(Object(XF\Mvc\Entity\Structure))
#12 /var/www/[redacted]/public/src/XF/Repository/User.php(86): XF\Mvc\Entity\Manager->getEntityStructure('...')
#13 /var/www/[redacted]/public/src/XF/Repository/User.php(32): XF\Repository\User->getGuestUser()
#14 /var/www/[redacted]/public/src/XF.php(586): XF\Repository\User->getVisitor(0)
#15 /var/www/[redacted]/public/src/XF/Error.php(137): XF::visitor()
#16 /var/www/[redacted]/public/src/XF/App.php(2498): XF\Error->logException(Object(Error), true, '')
#17 /var/www/[redacted]/public/src/XF.php(202): XF\App->logException(Object(Error), true)
#18 [internal function]: XF::handleException(Object(Error))
#19 {main}
  thrown in /var/www/[redacted]/public/src/XF/CacheFactory.php on line 68

I'm guessing this is still an XenForo issue even tho it also mentions Redis Cache?
The actual error which triggered this is being hidden, as the error is caused when \XF::handleException blows up. But given XF\Entity\User has a dependency on \XF::app()->options() which then touches the \XF::app()->cache() which resolves to potentially 3rd party or complex code which changes between XF versions, it is likely something touching that code-path.
 
Last edited:
Thank you for reporting this issue, it has now been resolved. We are aiming to include any changes that have been made in a future XF release (2.3.0 Beta 6).

Change log:
Disable cache in the install app and ensure Doctrine shim is type-compatible
There may be a delay before changes are rolled out to the XenForo Community.
 
I've removed some scalar type hints and return types from the Doctrine shim to help avoid type compatibility issues, and disabled the caching layer in the install app entirely. I didn't make any changes to copy src/XF.php sooner, as I think there's some risk of exceptions from the public app in the middle of an upgrade either way since the updater isn't transactional.
 
@Xon It looks like this causes stale data to linger in the cache after upgrading (most notably data registry items, including the currentVersionId option). Clearing the cache post-upgrade doesn't seem ideal as the registry may share a global cache with things like sessions. I think we're going to have to re-enable the cache in the install app and look at copying src/XF.php earlier instead.

In the future it might be nice if we used tag-aware adapters to allow clearing items more granularly.
 
@Xon I've re-enabled the cache in the install app, but I'm going to hold off on copying src/XF.php earlier for now. Mostly out of an abundance of caution as the paginated create/copy actions in the one-click upgrade can be brittle (the install app is rebooted in between pages when the code may not be entirely consistent, though some care is taken to minimize dependencies and initialize them manually). Since the shim is now type-compatible, I think other errors should no longer be obscured and we can go from there.
 
Top Bottom