flutter_cache_manager icon indicating copy to clipboard operation
flutter_cache_manager copied to clipboard

stalePeriod clarification

Open nt4f04uNd opened this issue 4 years ago • 15 comments

i used to think that maxAgeCacheObject, which was i guess replaced with stalePeriod worked like so: we download file -> mark some expiry date for it -> when it's expired we redownload it

with current docs it seems that's not the case https://github.com/Baseflow/flutter_cache_manager/blob/46f0a0466d62350b48a520a5561fd59e0c546dda/flutter_cache_manager/lib/src/cache_manager.dart#L32-L33

so if i have stalePeriod that equals to 1 day and user opens my app each 12 hours, for instance, and the file is being reused, my cache will never be invalidated? if that's true, how do i change this?

nt4f04uNd avatar Feb 23 '21 14:02 nt4f04uNd

Yes, that's exactly why there was a rename with a better documentation. You can only control how long you want to have the file on disk. The server controls how long the image is valid using the cache-control max-age header. If you set the stalePeriod on 1 day, but the max-age is 2 hours the file can be served from cache after 4 hours, but the library will check at the server if there is a newer version of the file.

renefloor avatar Feb 23 '21 14:02 renefloor

does flutter_cache_manager_firebase handle that? if i replace the file in storage it doesn't seem to refetch the new version of file

(i use it for videos)

nt4f04uNd avatar Feb 23 '21 14:02 nt4f04uNd

I don't know what kind of cache headers are set by firebase. You could check that using postman or something similar.

renefloor avatar Feb 23 '21 14:02 renefloor

it sets max-age=0 by default. does it mean that file will be automatically replaced on update? (i'm currently migrating to newer version from maxAgeCacheObject)

nt4f04uNd avatar Feb 23 '21 15:02 nt4f04uNd

Although the name changed the behaviour shouldn't have changed.

When the max-age is 0 it uses a default period of 7 days, because most people will still want to have some cache. When setting the header to 'no-cache' it is really set to 0 seconds. You can see that code here: https://github.com/Baseflow/flutter_cache_manager/blob/develop/flutter_cache_manager/lib/src/web/file_service.dart#L87

renefloor avatar Feb 23 '21 15:02 renefloor

i just tried setting the stalePeriod to 0, it doesn't work at all and never invalidates the cache

nt4f04uNd avatar Feb 23 '21 16:02 nt4f04uNd

How did you test this? And it shouldn't invalidate the cache, just remove the files.

renefloor avatar Feb 23 '21 16:02 renefloor

And it shouldn't invalidate the cache, just remove the files.

yep, that's what i meant actually

How did you test this?

i have an app tied up with the firebase storage. i opened the file once in my app, then changed it in storage, then opened the file again and saw the same cached file, it was not refetched. i tried it multiple times and waited for a few minutes - cached files still weren't deleted, even after app restart

nt4f04uNd avatar Feb 23 '21 16:02 nt4f04uNd

hmm, actually wait a bit, i will test it again

nt4f04uNd avatar Feb 23 '21 16:02 nt4f04uNd

@nt4f04uNd I just did the following test:

void main() {
  runApp(MyApp());
  checkCache();
}

Future<void> checkCache() async {
  var i = 0;
  while (i < 50) {
    CustomCacheManager.instance
        .getFileStream('https://via.placeholder.com/${(i % 5) + 1}',
            withProgress: false)
        .where((e) => e is FileInfo)
        .forEach((element) {
      var fileInfo = element as FileInfo;
      print("${fileInfo.originalUrl} from: ${fileInfo.source}");
    });

    await Future.delayed(Duration(seconds: secondsBetweenPulls));
    i++;
  }
}

class CustomCacheManager {
  static const key = 'customCacheObject';
  static CacheManager instance = CacheManager(Config(key,
      stalePeriod: Duration(seconds: stalePeriodInSeconds), maxNrOfCacheObjects: 1000));
}

Having the following settings it keeps the file in the cache:

var secondsBetweenPulls = 1;
var stalePeriodInSeconds = 30;

I/flutter (30423): https://via.placeholder.com/1 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/2 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/3 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/4 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/5 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/1 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/2 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/3 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/4 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/5 from: FileSource.Cache

The following settings doesn't keep the file in the cache:

var secondsBetweenPulls = 10;
var stalePeriodInSeconds = 10;

I/flutter (30423): https://via.placeholder.com/1 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/2 from: FileSource.Cache
I/flutter (30423): https://via.placeholder.com/3 from: FileSource.Online
I/flutter (30423): https://via.placeholder.com/4 from: FileSource.Online
I/flutter (30423): https://via.placeholder.com/5 from: FileSource.Online
I/flutter (30423): https://via.placeholder.com/1 from: FileSource.Online

renefloor avatar Feb 23 '21 16:02 renefloor

thanks for a great test, i can confirm it works for values you provided, but it doesn't work for me with these

var secondsBetweenPulls = 120;
var stalePeriodInSeconds = 120;

i didn't really try to tweak them to some other values, but in my app when i set stalePeriod to two minutes or so, it simply doesn't work

here's reproducible that uses your test https://github.com/nt4f04unds-archive/issues/tree/flutter_cache_manager_283

use this command to clone it as it has a lot of branches

git clone -b flutter_cache_manager_283 --single-branch [email protected]:nt4f04unds-archive/issues.git
logs
I/flutter (12918): https://via.placeholder.com/3 from: FileSource.Online
I/flutter (12918): https://via.placeholder.com/3 from: FileSource.Cache
I/flutter (12918): https://via.placeholder.com/3 from: FileSource.Cache
I/flutter (12918): https://via.placeholder.com/3 from: FileSource.Cache
I/flutter (12918): https://via.placeholder.com/3 from: FileSource.Cache
I/flutter (12918): https://via.placeholder.com/3 from: FileSource.Cache

nt4f04uNd avatar Feb 23 '21 17:02 nt4f04uNd

You changed the example from downloading 5 different images to only 'https://via.placeholder.com/3'. The library isn't continuously checking the cache, but only 10 seconds after something happened. So every time after you request this file it checks if it is recently used and it will never be stale (because you just requested it). If you change that file to 'https://via.placeholder.com/${(i % 5) + 1}' I expect it to work.

renefloor avatar Feb 24 '21 08:02 renefloor

ok thanks for detailed explanations could you put those in documentation? this would be really helpful

nt4f04uNd avatar Mar 10 '21 00:03 nt4f04uNd

The current documention says:

When are the cached files updated? A valid url response should contain a Cache-Control header. More info on the header can be found here, but in summary it says for how long the image can be expected to be up to date. It also contains an 'eTag' which can be used to check (after that time) whether the file did change or if it is actually still valid.

Following the provided link about Cache-Control header, we can see this:

no-cache and max-age=0, must-revalidate indicates same meaning. Clients can cache a resource but must revalidate each time before using it. This means HTTP request occurs each time though, it can skip downloading HTTP body if the content is valid

But for flutter_cache_manager it is:

When the max-age is 0 it uses a default period of 7 days, because most people will still want to have some cache. When setting the header to 'no-cache' it is really set to 0 seconds.

@renefloor Wouldn't it be better for max-age=0 to behave like what's written in the Mozilla's documentation, which has the same meaning to no-cache?

If not, adding the default to 7 days to the documentation would be really helpful.

billyonggoorigaming avatar Mar 22 '21 08:03 billyonggoorigaming

I agree that it should be better documented. I think max-age=0 is often set because devs just miss setting it. However, we got many complaints about the library not caching when we adhered to the 'max-age'. The Cache-Control: no-cache header is often added more deliberately in my experience.

renefloor avatar Mar 22 '21 08:03 renefloor