Interesting CDN/performance issue I have so I thought I'd bring it up.
I'm using the CDN module with CloudFront in origin pull mode. Basically that means that my site serves up all of its images with a URL like http://mycdn.amazon.com/picture.jpg (not http://mysite.com/picture.jpg), and then when the user hits amazon, CloudFront serves up a cached image. If Amazon doesn't have a cached image, they come and visit my site and have the imagecache generated and sent back first to Amazon and then the end user that requested it. Very straight-forward, very standard.
One of the issues I ran into initially with this method was that when a user on the Drupal site replaces an existing photo, CloudFront was serving up the previously cached version of it. The filename was the same, so Amazon had no way to know it changed (until it hits the CloudFront cache expiration), and I didn't want to send them a force-cache-expiration command because it takes 30 seconds to 1 minute or more to clear it out. My solution to this was to use the filefield_paths module, which I use to modify the filename of the uploaded image with tokens. One of my tokens is the md5 checksum of the current timestamp, so the resulting image name is myimage-6ada540363d39257b9b163ae857ef28d.jpg. So every time the user uploads a new file, filefield_paths renames the master image, and since the image is now using a new name all of the ImageCache presets are regenerated upon request and Amazon has no cache. It's like instant cache expiration and it works very well. The old images just time out from CloudFront.
OK so now on to the rub with this module. With imagecrop, now a derivative ImageCache preset can change without warning, and without the master filefield/imagefield changing. What happens is that a user goes in to the node edit page, creates a crop, the derivative ImageCache image is created, cached at the CDN, and it's done. But... the user doesn't like their initial crop, so they go to re-do it or make changes. The new ImageCache file has the same filename, so the version at the CDN is served back to the user and they get confused because it looks like the crop isn't working. It's because they get the old image from the CDN because the filename did not change.
What I need to have happen now, is that whenever a user creates a new crop setting - the master imagefield image is renamed according to my standard filefield_paths routine. That would then essentially flush out any remaining cached copies of the image at Amazon and to the user it looks like their change is taking effect right away. I'll take a shot at implementing this, and I'm hoping there is a hook somewhere in imagecrop so I can take some action when it happens. If not this will turn into a feature request for such a hook :)
I wrote a lot of stuff here, hopefully it makes sense. Thoughts/comments are welcome.
| Comment | File | Size | Author |
|---|---|---|---|
| #8 | 1250506-8.patch | 991 bytes | rjbrown99 |
Comments
Comment #1
rjbrown99 commentedThinking more about this. It would seem the place to do this would be in imagecrop.module, create_image_object(). Specifically, before running an imagecache_build_derivative() to start creating new derived images.
Perhaps adding a hook there? I haven't thought through all of the implications of this yet, nor have I fully explored how imagecrop uses the files within its UI.
Comment #2
nils.destoop commentedYeah, adding a hook looks like a good idea. I'll create one for both D6 and D7 version.
Comment #3
nils.destoop commentedI'v added "hook_imagecrop_settings_update" to both d6 and d7 version.
Comment #4
rjbrown99 commentedAwesome, thank you. Seems like a good place to do it on the form submit action.
I'll roll up an example implementation of the hook for renaming of the file. I should have that done within the next few days, so if you like keep this open and I'll post my code back and close it out.
Thanks for the assistance and support!
Comment #5
rjbrown99 commentedOK, here's some documentation - perhaps for a DEVELOPER.txt?
This is not perfect, but here's an implementation of the hook that uses filefield_paths to rename the file. In my case, my filefield_paths token inserts that custom timestamp/md5 hash so the files always get different names.
Comment #6
rjbrown99 commentedI declare this fixed! :) Thanks for the hook, very helpful.
Comment #7
rjbrown99 commentedOK it's not really fixed :(
I think the hook is in the wrong place. It works in the form submit action for the final photo, but it does not work when the user is actively resizing/rescaling images in the viewport. IE, I select a dropdown and choose a different size for the photo but before I save it. When that happens, the js callback hits imagecrop_docrop() only and not the submit. The end result is that the image inside of the viewport is not updated because the CDN is still serving the same cached name of the image.
If the hook is in imagecrop_docrop() that would seem to fix it, because it would handle both the submit as well as any realtime changes by the user when they fiddle with the scale dropdown.
Comment #8
rjbrown99 commentedHere's a patch for 6.x. It moves the hook to imagecrop_docrop, which now seems to work for me - at least so far.
Comment #9
rjbrown99 commentedYup, that works for me. Here's a revised version of my hook implementation:
Comment #10
rjbrown99 commentedStill working this...
Right now, with the above patch, everything works properly when you are in the crop popup box. The image is renamed, imagecache created, cached at the CDN, boom looks good. The problem is that when the actual node is saved/submitted (not the crop - the actual node save), I have another function which triggers a regeneration of the image by using imagecache_generate_image(). The issue with this is that the image is NOT created using imagecrop, or at least it doesn't work properly. It generates an image of the correct size, with no cropping or scaling applied. Hmm.
Comment #11
wim leersSubscribing.
It seems this has become a feature request by now… :)
Comment #12
nils.destoop commentedThe problem with imagecache_generate_image(), is that ' imagecache_build_derivative' doesn't give any information to the preset actions, what preset is currently beïng saved.
Because of this, imagecrop needs to look at the current url, to strip out the requested preset. When only imagecache_build_derivative is beïng called, no imagecache url is beïng requested.
Maybe i should take a look for a patch for both imagecache (d6) and core (d7)
Comment #13
bradjones1Bumping this to 7.x to gather some attention to this very useful proposal. I basically have the same use-case as explained above, without having pit-stopped at filefield_paths. Last update is 4 years ago so if the 6.x patch isn't getting much love, let's try for 7.x.
Comment #14
jennypanighetti commentedI too would like a hook for when the new cropped image is saved. @bradjones1, do you have a workaround for this?
Comment #15
bradjones1This is on my list of things to do for a personal project but it hasn't happened yet... I think it would be rather straightforward, though. If/when I get to it, I'll post a patch.
I'm also open to being hired to work on this, depending on your urgency.
Comment #16
jennypanighetti commentedI actually found another issue's comment (can't remember where) and found hook_imagecrop_settings_update($record). I could get the info I need from $record and perform the action I needed.