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

Detect and download updated image #52

Closed
andreaslindahl opened this issue Feb 3, 2016 · 15 comments
Closed

Detect and download updated image #52

andreaslindahl opened this issue Feb 3, 2016 · 15 comments
Labels

Comments

@andreaslindahl
Copy link

I'm having trouble getting Nuke to detect images that's been updated on the server - the cached image is used instead. It seems like Nuke doesn't check if the file has been updated on the server by default? Is there a way to force this functionality?

@kean
Copy link
Owner

kean commented Feb 3, 2016

Nuke uses NSURLSession's cache management without any modifications. It's most probably that your server sets a really long max-age in cache headers - cache responses are not revalidated until they are expired.

There at least two ways to adjust that behaviour:

  1. Server should set a max-age value depending on how often do you want responses to be revalidated.
  2. Server should set must-revalidate in Cache-Control header to force image to be revalidated each time it's requested.

Update: must-revalidate doesn't work as I expected, you should use no-cache or set max-age to 0 instead (see the end of discussion)

There are also some ways to control it programatically. I've actually written an entire guide on this topic. You might want to check it out.

@andreaslindahl
Copy link
Author

I'm using Amazon S3 for storing files. The Etag header is set, but the max-age header is not set (if max-age is what Amazon refers to as Expiry date below):

Last Modified: Wed Feb 03 08:00:12 GMT+100 2016
ETag: 8069ea92d9e4aff1db9d6ccb38899fdc
Expiry Date: None

Update:

Here's the response headers. See anything that might cause caching problems?

Cache-Control:must-revalidate
Date:Wed, 03 Feb 2016 10:51:51 GMT
ETag:"40815c43cd4f6bacfc247011966b724b"
Last-Modified:Wed, 03 Feb 2016 10:49:36 GMT
Server:AmazonS3
x-amz-id-2:oBOSLSmUFZ19Z5XJ0e/5TRMXE3VeyBya/HCzMWbLpKEU43JfLqI9MrPIKkS1y72kLaCrGVvN9G4=
x-amz-request-id:5BDEE42876386064

@kean
Copy link
Owner

kean commented Feb 3, 2016

Cache-Control:must-revalidate yeah that seems alright.

Update: must-revalidate doesn't work as I expected, you should use no-cache or set max-age to 0 instead (see the end of discussion)

@kean
Copy link
Owner

kean commented Feb 3, 2016

Nuke also has a memory cache for fast access to processed images. It doesn't have any revalidation mechanisms (yet, it will in Nuke 2), because it gets cleared frequently. It might add some confusion, because images would not get revalidated if they are present in memory cache. I doubt that it's a problem, but just so you know.

There isn't anything else that might interfere with cache management in NSURLSession. It should just work if the headers are correct (and seems that they are).

@andreaslindahl
Copy link
Author

After upgrading to 2.0 I'm having trouble getting updated images, even though I'm using NSURLRequestCachePolicy.ReloadIgnoringCacheData:

let cachePolicy : NSURLRequestCachePolicy = .ReloadIgnoringCacheData
let request = ImageRequest(URLRequest: NSURLRequest(URL: imageUrl, cachePolicy: cachePolicy, timeoutInterval: 360))
self.nk_setImageWith(request, placeholder: UIImage(named: "placeholder"))

Worked fine in the previous version.

@kean
Copy link
Owner

kean commented Feb 8, 2016

There a separate options for controlling memory cache now:

/** Defines constants that can be used to modify the way ImageManager interacts with the memory cache.
 */
public enum ImageRequestMemoryCachePolicy {
    /** Return memory cached image corresponding the request. If there is no existing image in the memory cache, the image manager continues with the request.
     */
    case ReturnCachedImageElseLoad

    /** Reload using ignoring memory cached images. Doesn't affect on-disk caching.
     */
    case ReloadIgnoringCachedImage
}
public struct ImageRequest {

    /** The request memory cache policy. Default value is .ReturnCachedImageElseLoad.
     */
    public var memoryCachePolicy = ImageRequestMemoryCachePolicy.ReturnCachedImageElseLoad

}
@kean
Copy link
Owner

kean commented Feb 8, 2016

NSURLRequestCachePolicy no longer affects memory cache in any way, only NSURLSessionTask.

@andreaslindahl
Copy link
Author

Oh, ok. thanks!

@kean
Copy link
Owner

kean commented Feb 8, 2016

That's pretty much the only change in the behaviour in Nuke 2. Everything else should work as expected.

@andreaslindahl
Copy link
Author

I'm still having trouble getting updated images unless I set the memoryCachePolicy to ReloadIgnoringCachedImage however. It seems like the Etag is ignored. I have verified that the ETag header is updated when the image is updated on the server and the Cache-Control header is set to "must-revalidate" but this doesn't seem to matter - the old, cached image is used instead.

The Last-Modified header is also updated, by the way.

Setting the memoryCachePolicy to ReloadIgnoringCachedImage solves the problem, of course, but since this bypasses the cache entirely it doesn't seem like a good solution...

@andreaslindahl
Copy link
Author

I probably shouldn't bother you with these questions, since they seem to be more about how NSURLRequest and NSURLCache works. :)

@kean
Copy link
Owner

kean commented Feb 8, 2016

Yeah, I'm sorry, I can't really help with debugging that :(

I would recommend trying to set a max-age=0. See http://stackoverflow.com/questions/1046966/whats-the-difference-between-cache-control-max-age-0-and-no-cache

If you can't control server side, you can update Cache-Control on the client in optional public func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, willCacheResponse proposedResponse: NSCachedURLResponse, completionHandler: (NSCachedURLResponse?) -> Void)

@kean
Copy link
Owner

kean commented Feb 8, 2016

Or just ask on stackoverflow :)

@kean
Copy link
Owner

kean commented Feb 8, 2016

Actually, yeah, I might have misunderstood how must-revalidate works. I haven't used it myself.

@kean
Copy link
Owner

kean commented Feb 8, 2016

I believe that must-revalidate means "once the cache expires, refuse to return stale responses to the user even if they say that they are acceptable". Whereas no-cache implies must-revlidate plus the fact the response becomes stale right away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2 participants