Skip to content

isMenuItemsStale stalenessLevel issue #16

Open
@bkai

Description

@bkai

Talking about ch24/iHotelApp/iHotelApp/ directory.

AppCache.m:

+(BOOL) isMenuItemsStale
{
...
NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:@"MenuItems.archive"];    
NSTimeInterval stalenessLevel = [[[[NSFileManager defaultManager] attributesOfItemAtPath:archivePath error:nil] fileModificationDate] timeIntervalSinceNow];
...
}

stalenessLevel is computed from the time of the last modification of the corresponding data file. Thus, in order to have the correct time value, we need that every new data are written to local file as soon as we receive it from the remote engine in iHotelAppMenuViewController viewWillAppear method. But this is not done sooner than in viewWillDisappear method.

This "post-write" strategy is taken also in AppCache cacheData:toFile: method, where (see [leastRecentlyUsedCacheData writeToFile:archivePath atomically:YES];) the data gets written to disk only after it can't remain in memory any more.

When combined with "pre-write" stalenessLevel concept, some stale data are declared as not stale.

Fix is rather simple provided one caching strategy will be chosen as preferred.

Code excerpts follow.

iHotelAppMenuViewController:

-(void) viewWillAppear:(BOOL)animated {

  self.menuItems = [AppCache getCachedMenuItems];  
  [self.tableView reloadData];

  if([AppCache isMenuItemsStale] || !self.menuItems) {

    [AppDelegate.engine fetchMenuItemsOnSucceeded:^(NSMutableArray *listOfModelBaseObjects) {

      self.menuItems = listOfModelBaseObjects;
      [self.tableView reloadData];
    } onError:^(NSError *engineError) {
      [UIAlertView showWithError:engineError];
    }];
  }

  [super viewWillAppear:animated];
}

-(void) viewWillDisappear:(BOOL)animated {

  [AppCache cacheMenuItems:self.menuItems];
  [super viewWillDisappear:animated];
}

AppCache.m:

+(void) cacheData:(NSData*) data toFile:(NSString*) fileName
{
  [memoryCache setObject:data forKey:fileName];
  if([recentlyAccessedKeys containsObject:fileName])
  {
    [recentlyAccessedKeys removeObject:fileName];
  }

  [recentlyAccessedKeys insertObject:fileName atIndex:0];

  if([recentlyAccessedKeys count] > kCacheMemoryLimit)
  {
    NSString *leastRecentlyUsedDataFilename = [recentlyAccessedKeys lastObject];
    NSData *leastRecentlyUsedCacheData = [memoryCache objectForKey:leastRecentlyUsedDataFilename];
    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:fileName];  
    [leastRecentlyUsedCacheData writeToFile:archivePath atomically:YES];

    [recentlyAccessedKeys removeLastObject];
    [memoryCache removeObjectForKey:leastRecentlyUsedDataFilename];
  }
}

+(BOOL) isMenuItemsStale
{
  // if it is in memory cache, it is not stale
  if([recentlyAccessedKeys containsObject:@"MenuItems.archive"])
    return NO;

    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:@"MenuItems.archive"];  

  NSTimeInterval stalenessLevel = [[[[NSFileManager defaultManager] attributesOfItemAtPath:archivePath error:nil] fileModificationDate] timeIntervalSinceNow];

  return stalenessLevel > kMenuStaleSeconds;
}

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions