Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cached assets become stale after engine version changes #325

Closed
wjordan opened this issue Jun 23, 2016 · 1 comment
Closed

Cached assets become stale after engine version changes #325

wjordan opened this issue Jun 23, 2016 · 1 comment

Comments

@wjordan
Copy link
Contributor

wjordan commented Jun 23, 2016

When a new version of an "engine" registered with Sprockets generates different content from the same source file compared to a previous version, the cached asset remains stale and is not regenerated correctly by Sprockets.

I came across this issue when updating an existing Rails project containing sass-rails, and updating sass from 3.2.19 to 3.4.22, which generated slightly different CSS output from the same source file. On the next run of rake assets:precompile, a new asset was not generated and the existing (stale) cached asset continued to be used.

This caused issues in a load-balanced multi-server environment containing a mix of old and new servers, since the old servers continued to reference asset-[old-hash].ext in their manifest while the new ones contained asset-[new-hash].ext. When a page was requested from a new server and the referenced asset-[new-hash].ext asset was requested from an old server which not containing the new asset, a 404 error was returned.

Here is a minimal Bash script demonstrating the issue (or you can manually step through the commands listed):

#!/bin/bash

# Run in a temp dir and clean up after
TEST_DIR=$(mktemp -d)
pushd ${TEST_DIR} > /dev/null
trap "rm -rf ${TEST_DIR}; popd > /dev/null" EXIT

# Generate new Rails project
rails new ${TEST_DIR} -q

# Use old version of Sass
OLD_SASS=3.2.19
cat <<GEMFILE >> Gemfile
gem 'sass', '${OLD_SASS}'
GEMFILE
bundle update --quiet sass

# Write a .scss file
rm app/assets/stylesheets/application.css
cat <<'SCSS' > app/assets/stylesheets/application.scss
/*= require_self */
$red: #c00;
.selector {
  color: $red;
}
SCSS

# Compile asset
bundle exec rake assets:precompile >/dev/null 2>&1

# Update sass version
NEW_SASS=3.4.22
sed -i -e "s/${OLD_SASS}/${NEW_SASS}/g" Gemfile
bundle update --quiet sass

# WORKAROUND: Clear Sprockets cache
# bundle exec rake tmp:cache:clear >/dev/null 2>&1

# Remove old asset
bundle exec rake assets:clobber >/dev/null 2>&1
# Compile asset again
bundle exec rake assets:precompile >/dev/null 2>&1
# Test output of compiled asset
cat public/assets/application*.css | grep color

Expected output (compiled with the new version of sass):

  color: #c00;

Actual output (cached output of the old version of sass):

  color: #cc0000;

A workaround (see commented line in the test script above) is to manually clear out the Sprockets cache by running rake tmp:cache:clear whenever Sprockets-engine dependencies are updated in a way that potentially changes the compiled asset output for given input contents. (Changing config.assets.version did not have any effect.) However, this workaround is extremely prone to human error and would require extremely clear documentation to rely upon.

I think it would more robust if an engine version was included in the code Sprockets uses to generate its cache key, so that cached assets would automatically expire whenever a dependent engine version is updated.

@rafaelfranca
Copy link
Member

rafaelfranca commented Jun 23, 2016

that is exactly how it works. Then engine should bump the cache key based in they version. If an engine is not doing this it is an engine bug. Could you report this issue to the engine?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants