From: Chuck H. <ch...@gl...> - 2010-09-24 17:37:32
|
On Sep 24, 2010, at 9:59 AM, Robin Smith wrote: > Hi Chuck > > Right that does sound exactly like the issue we are having so thanks > for your help and i guess we will end up following a similar fix as > the one described however i already foresee another issue with this > solution. > > Imagine i create a cache that expires every hour, if i use the code > that you have supplied the first lot of EO's in the cache will work > perfectly as their timestamp are set to distant future. However an > hour later when the cache is refreshed some new EO's get pulled in to > the cache, the section of code that set the "expiration timestamp for > the snapshot" doesnt get called again and we are back to square one. That code was for entities that never change and so are never refreshed. > What i'm wondering is why when the EO is added to the cache initially > why isn't this expire timestamp being set then? It doesnt even need to > be distant future i would just expect the snapshot timeout to mimic > that of the cache. So if the cache has a timeout of 1 hour then so > should the snapshot its holding, otherwise whats the point of a cache. That is part of reason this is not in Wonder: this class is a total Swiss Army Knife and I had no idea which solution(s) would be appropriate. In my case, I don't have access to the EC, and hence the fetchTimestamp, to control the TTL. I don't want my cache objects to be refetched every hour. If the cache is set to one hour and 30 minutes later an object is fetched, does its snapshot expire in 30 minutes or 60 minutes? The other part of the reason is that I was unsure if this would cause Bad Things (tm) to happen. I can say now that it has not. Chuck > On 24 September 2010 17:30, Chuck Hill <ch...@gl...> wrote: >> >> On Sep 24, 2010, at 7:42 AM, Mike Schrag wrote: >> >>>> resulting array does contain my EO's but they have no variables. >>> I'm not quite sure what you mean by this ... It will be a fault, yes, but the snapshot will already be loaded, so tripping the fault shouldn't result in an actual fetch from the database. Are you saying you have your own custom instance variables on those EO's? That's a little dicey. You can't really count of those surviving. You also shouldn't steal the EC from the cache, because you're almost certainly going to run into problems accessing it on multiple threads. >> >> >> I think what is happening is that you have an fetchTimestamp on the EC that is older that the snapshot for the cached object. When it is faulted into that EC, EOF will refresh the snapshot. I ran into the same issue. Here is how I avoided this for objects that I never wanted to get refetched: >> >> ERXEnterpriseObjectCache cache = new ERXEnterpriseObjectCache(entityName, keyPath, restrictingQualifier, timeout, >> shouldRetainObjects, shouldFetchInitialValues, shouldReturnUnsavedObjects); >> >> /** >> * OK, things get nasty here. You HAVE been warned! >> * >> * The cache has an interaction with the EOEditingContext fetchTimestamp()/defaultFetchTimestampLag(). After >> * the objects have been fetched into the cache, if the defaultFetchTimestampLag() passes before they are >> * re-fetched, when they are faulted into a new editing context (localInstanceOfObject), the snapshot will be discarded >> * and the objects re-fetched, one by one. This rather eliminates the value of the cache. >> * >> * There are a few options to fix this: >> * - use a large defaultFetchTimestampLag() and ensure that all the places that need fresh data use >> * a fetch specification that refreshes re-fetched objects. This also means that you must pre-fetch all >> * the objects that need fresh data. This makes the defaultFetchTimestampLag() rather useless to control >> * data freshness. >> * >> * - use a large defaultFetchTimestampLag() and implement ERChangeNotification to keep all the EOF stacks >> * in sync. This ensures current data without needing to use defaultFetchTimestampLag(). >> * >> * - use a custom EODatabaseContext.delegate and implement the delegate method >> * databaseContextShouldFetchObjectFault(EODatabaseContext, Object) to use the existing snapshot regardless of age. >> * To implement this, the delegate will need to know that the entity is being cached. This can be done by setting >> * a flag in EOEntity.userInfo in this method. >> * >> * - make the objects as "Cache in Memory" in the EOModel. The large drawback of this is that the objects will never >> * be refreshed. Refreshing fetch specifications do not affect entities cached in memory. >> * >> * - mark the snapshots of the cached objects as expiring at some time in the distant future. As they expire from the >> * cache they will be re-fetched and refreshed from the database. This option was chosen as it more closely matches >> * what should happen. It does require access to a protected method in EODatabase. It is possible that future >> * versions of WebObjects will break this implementation, but there should be some way of achieving the result. >> */ >> EOEntity entity = EOUtilities.entityNamed(ec, entityName); >> EODatabaseContext dbContext = EOUtilities.databaseContextForModelNamed(ec, entity.model().name()); >> EODatabase database = dbContext.database(); >> NSArray objectsInCache = cache.allObjects(ec); >> for (int i = 0; i < objectsInCache.count(); i++) >> { >> EOEnterpriseObject eo = (EOEnterpriseObject) objectsInCache.objectAtIndex(i); >> // Sets the expiration timestamp for the snapshot to NSTimestamp.DistantFuture.getTime() >> _setTimestampForCachedGlobalID().invoke(database, ec.globalIDForObject(eo)); >> } >> >> return cache; >> >> >> Chuck >> >> -- >> Chuck Hill Senior Consultant / VP Development >> >> Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems. >> http://www.global-village.net/products/practical_webobjects >> >> >> >> >> >> >> >> > > > > -- > Robin Smith > Software and Infrastructure Engineer BEng (Hons) MBCS > > Click Travel Ltd > www.clicktravel.com > For companies on the move -- Chuck Hill Senior Consultant / VP Development Practical WebObjects - for developers who want to increase their overall knowledge of WebObjects or who are trying to solve specific problems. http://www.global-village.net/products/practical_webobjects |