capistrano-magento2
capistrano-magento2 copied to clipboard
Cached data from current release causes new release to fail with redis caching
Similar issue to: https://github.com/davidalger/capistrano-magento2/issues/138
When running magento:maintenance:enable the redis cache is not correct. You fixed it by flushing before app:config:import, but it should have done a cache flush after the magento:maintenance:enable in the release_path
issue with cache:
16:47:12
16:47:12 Maintenance mode usage will be enforced per :magento_deploy_maintenance (setting is true)
16:47:12 07:05 magento:maintenance:enable
16:47:12 01 /usr/bin/php72 -f bin/magento -- maintenance:enable
16:47:13 01 Enabled maintenance mode
16:47:13 ✔ 01 xxx@xxx 0.865s
16:47:13 01
16:47:13 01 In ClassReader.php line 19:
16:47:13 01
16:47:13 01 Class Vertex\Tax\Model\Cache\Type does not exist
16:47:13 01
16:47:13 01
16:47:13 01 maintenance:enable [--ip IP] [--magento-init-params MAGENTO-INIT-PARAMS]
To fix it I added the following to override it:
Rake::Task["magento:maintenance:enable"].clear
namespace :magento do
namespace :maintenance do
task :enable do
on release_roles :all do
within release_path do
execute :magento, 'cache:flush'
execute :magento, 'maintenance:enable'
execute :magento, 'cache:flush'
end
end
end
end
end
The issue is that a cache:flush needs to be done after the maintenance:enable, because then it does a maintenance:enable in the current_path (https://github.com/davidalger/capistrano-magento2/blob/3d32c7d654bd9221f67e20c27fc4e62503bdd73d/lib/capistrano/tasks/deploy.rake#L74)
We have also experienced this. But we have seen that capistrano-magento2 in the end just invokes magento:setup:di:compile, so it didn't look like the element to blame:
https://github.com/davidalger/capistrano-magento2/blob/3d32c7d654bd9221f67e20c27fc4e62503bdd73d/lib/capistrano/tasks/deploy.rake#L57
We still have some issues in our production environment during production releases - where classes are not generated.
But seeing your issue @PascalBrouwers made us thought of it to tackle it better than manually copying the generated files from the staging server to production 😅
Maybe capistrano-magento2 could force Magento to ignore the Redis cache while preparing the 2nd release?
That's not possible, but I should make sure that running commands between release_path and current_path the cache should be flushed.
Small update: you also need to fix the autoloader because that is cached too. So run this too:
invoke!('magento:composer:install') if fetch(:magento_deploy_composer)
Trying to get a fail-safe method for this but it feels like there isn't one.
As soon as you flush the redis cache there is the possibility that a visitor is on the site and trigger the redis cache for the current release, while you were trying to fill it with the release_path. There is the option to set the maintenance flag, but that would mean a long downtime.
Also an issue when running php 7.2 / 7.3 in your current release and the latest release need php 7.4 Running composer install in both directories isn't going to work with the same php version.
Decided to go with using a different cache prefix for each deployment. This way generated files and other caches don't interfere with each other during a deploy for a site that has allot of visitors. Because this runs before composer, if also fixes the issue with the classmap cache.
after "deploy:symlink:linked_files", "set_cache_prefix"
task :set_cache_prefix do
on release_roles :all do
within release_path do
unless test %Q[#{SSHKit.config.command_map[:php]} -r '
$cfg = include "#{shared_path}/app/etc/env.php";
exit((int)!isset($cfg["cache"]["frontend"]["default"]["id_prefix"]));
']
# generate a new prefix
version = '100_'
else
# get the current prefix
version = capture %Q[#{SSHKit.config.command_map[:php]} -r '
$cfg = include "#{shared_path}/app/etc/env.php";
echo(($cfg["cache"]["frontend"]["default"]["id_prefix"]));
']
end
# convert prefix to a number and increment it
version = version.gsub("_", "")
versionNumber = version.to_i
newVersionNumber = versionNumber + 1
set :newVersionNumber, newVersionNumber
# copy the file as a normal file in the next release
execute :rm, "-rf #{release_path}/app/etc/env.php"
execute :cp, "-rf #{shared_path}/app/etc/env.php #{release_path}/app/etc/env.php"
execute %Q[#{SSHKit.config.command_map[:php]} -r '
$cfg = include "#{release_path}/app/etc/env.php";
$cfg["cache"]["frontend"]["default"]["id_prefix"] = "#{fetch(:newVersionNumber)}_";
$out = "<?php return " . var_export($cfg, true) . ";"
file_put_contents("#{release_path}/app/etc/env.php", $out);
']
# save new env file to shared dir
execute :rm, "-rf #{shared_path}/app/etc/env.php"
execute :cp, "-rf #{release_path}/app/etc/env.php #{shared_path}/app/etc/env.php"
end
end
end
Works when env.php does not have a cache prefix yet. Also Magento fixes the array( syntax with a short syntax [ during deployment by itself.
@davidalger is this an idea to include it?