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

Remove delete() call from CompressorFileStorage.get_available_name #1107

Merged
merged 2 commits into from
Apr 3, 2022
Merged

Remove delete() call from CompressorFileStorage.get_available_name #1107

merged 2 commits into from
Apr 3, 2022

Conversation

cuu508
Copy link
Contributor

@cuu508 cuu508 commented Apr 2, 2022

This PR is an alternative to #1105 and #1100, and intends to fix #1099. It changes CompressorFileStorage:

  • drops the deletion logic in CompressorFileStorage.get_available_name()
  • this means that get_available_name will sometimes return filenames with an underscore and a random string appended at the end to ensure uniqueness
  • overrides the save() method to add one additional last step: if the filename contains an underscore then move it into the correct location.

So, instead of deleting a file and then writing new data in the same filename, compressor would write the data in a temporary file, then move it to the correct place. Python docs say os.replace is an atomic operation, so this would avoid the brief moment of file not existing between delete and write.

Notes:

  • I didn't add any new test cases. In theory there could be a test case which creates compressed files with clashing filenames, and then tests if the produced files contain any underscores (they shouldn't). But not sure if it's worth testing that.
  • GzipCompressorFileStorage and BrotliCompressorFileStorage override the save method again and do some more file IO. I'm not sure if we could run into race conditions there too.

compressor/storage.py Outdated Show resolved Hide resolved
@diox
Copy link
Member

diox commented Apr 3, 2022

I didn't add any new test cases. In theory there could be a test case which creates compressed files with clashing filenames, and then tests if the produced files contain any underscores (they shouldn't). But not sure if it's worth testing that.

I think it's worth testing (I know the current CompressorFileStorage implementation doesn't have any tests - we should change that). Something along the lines of what you suggest should be enough. Let me know if you don't have the motivation to do that (you already done a lot of work, I appreciate the time spent on this!) and I'll step in if needed.

GzipCompressorFileStorage and BrotliCompressorFileStorage override the save method again and do some more file IO. I'm not sure if we could run into race conditions there too.

They do this with the low-level primitives directly though, so they might run into different issues. I think it's fine to ignore them for this.

@cuu508
Copy link
Contributor Author

cuu508 commented Apr 3, 2022

No problem – added a small testcase which saves the same file and tests if the filename returned by save() contains any underscores or not.

Copy link
Member

@diox diox left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 let's merge and get some people experiencing issues with this to test it!

@diox diox merged commit 00910e0 into django-compressor:develop Apr 3, 2022
@cuu508 cuu508 deleted the another-issue-1099-fix branch April 3, 2022 13:15
kmtracey added a commit to kmtracey/django-compressor that referenced this pull request Sep 30, 2022
django-compressor#1107 moved file-name-mangling avoidance into a `save` override, but the doc suggests calling `_save` which bypassess the new file-name-mangling-avoidance code. Updating a project to use django-compressor 4.0 that had a storages class which followed this doc resulted in mangled-named files appearing in the file system (and ultimately css changes not getting built/deployed, since the changes were in the mangled-name files while the rest of the process was using the "bare" name).
diox pushed a commit that referenced this pull request Sep 30, 2022
* Update doc in light of new mangled name avoidance

#1107 moved file-name-mangling avoidance into a `save` override, but the doc suggests calling `_save` which bypassess the new file-name-mangling-avoidance code. Updating a project to use django-compressor 4.0 that had a storages class which followed this doc resulted in mangled-named files appearing in the file system (and ultimately css changes not getting built/deployed, since the changes were in the mangled-name files while the rest of the process was using the "bare" name).

* Update changelog.txt
MichaelMatschiner added a commit to MichaelMatschiner/django-compressor that referenced this pull request Dec 26, 2022
* Update doc in light of new mangled name avoidance

django-compressor/django-compressor#1107 moved file-name-mangling avoidance into a `save` override, but the doc suggests calling `_save` which bypassess the new file-name-mangling-avoidance code. Updating a project to use django-compressor 4.0 that had a storages class which followed this doc resulted in mangled-named files appearing in the file system (and ultimately css changes not getting built/deployed, since the changes were in the mangled-name files while the rest of the process was using the "bare" name).

* Update changelog.txt
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

Successfully merging this pull request may close these issues.

Intermittent failure in offline compression
2 participants