5 Replies Latest reply on Nov 13, 2014 5:41 PM by Bhess

    When are WebID's generated in relation to AFSDK caching?

    Roger Palmen

      From documentation i learn that WebID's are a combination of AF GUID, and AF Path. The Path is a fallback whent he GUID is not found. Do i understand correctly, that every time i request e.g. an attribute (not the value), the WebID is generated based on the GUID and path currently in the AFSDK cache of the PI WebAPI?


      Now my key question: if i replace (delete AF element, create new AF element with same path/name) the AFelement from another computer, how will that update the AFSDK cache and when will that render a new WebID?




      I know the question is spread over the Web API subject and the AFSDK cache subject., but they can't be fully separated as i don't know if the PI Web API keeps any references to AFSDK objects to prevent garbage collection.



        • Re: When are WebID's generated in relation to AFSDK caching?

          Correct that the WebID is generated for each request.  It is not cached/persisted anywhere.


          If you replace an element in another context, that element will have a different GUID assigned by AF.  When you go to look up that element in PI Web API, one of two things will happen:


           1.  If the element already exists in the PI Web API cache, the PI Web API cache refresh interval hasn't elapsed (default refresh interval is 5 minutes), and you don't send an explicit Cache-Control header asking for a refresh, you'll get the stale deleted element served out of the cache, old WebID and all.


           2.  Otherwise, if any of those other preconditions is not true, you'll get the new element.  You can look this up successfully with the old WebID, due to the fallback to path as the lookup mechanism.  However, the WebID in the response will be different-- it will contain the new GUID.

            • Re: When are WebID's generated in relation to AFSDK caching?
              Roger Palmen

              Thanks! This clarifies a lot. There is some information on caching, but piecing this together is the difficult part for me.


              Zooming in into the so-called "PI Web API caching", do i correctly presume that this is nothing more than the AFSDK cache?


              That seems to be what i can conclude from the caching topic in the WebAPI HTML help. Although the AFSDK might create an additional separation between the read and write cache, but that's not my main concern.


              So looking at the AFSDK cache, the only reason why an object in the cache is refreshed, is when the cachetime has expired?

                • Re: When are WebID's generated in relation to AFSDK caching?

                  Under the hood, it's all the AF cache.  However, PI Web API tries to wrap some of the behaviors of the AF SDK cache in order to make the behavior more useful for a web client.


                  In AF SDK, cache expiration and refresh is not deterministic.  In the native AF SDK cache, after the cache time has elapsed (default 10 minutes, but configurable using the static AFCache.CacheTime property), the internal cache's object references change from strong to weak, making those objects eligible for garbage collection.  However, if there's no memory pressure on the system, or GC doesn't happen for some other reason, the stale objects can remain in the AF cache and be served indefinitely.


                  This tends to be okay for a desktop application or short-running process.  Even if you left your PI System Explorer window open overnight, there's a refresh button right there that'll get the changes for you if stale objects happen to be kicking around in the cache.  It's far less acceptable to make an API request and be served an object that's two days old.


                  The read and write cache are concepts that are specific to PI Web API.  They're separated to try to prevent the situation where a slow running background process that's doing writes is contending with concurrent readers for a lock.  Since the AF SDK is not natively threadsafe, care has to be taken when serving the same objects to multiple consumers simultaneously, especially if there are writes involved.  Though we're talking a bit internally about moving to a single cache per user in a future release, to try to simplify this.  That would have to go along with a recommendation that the slow running background writer be given his own user account, so he'll be guaranteed his own cache, which is probably a best practice regardless.


                  And finally-- in AF SDK, there are two ways in which an object is brought up to date:


                   1.  With a manual Refresh() call (either on the object itself, or on an ancestor AFDatabase, PISystem, or PISystems)


                   2.  Through AF cache expiration:


                        a. The object is loaded into memory in the AF SDK


                        b. The cache time specified in AFCache.CacheTime elapses, or the maximum number of cached objects in AFCache.MaxObjects is hit, or AFCache.Clear() is called.  The internal cache's reference changes from strong to weak


                        c.  No other active objects in the .NET runtime have a strong reference to the object (important note here: if you're holding on to a reference to the object yourself, it will never be updated without a manual call to Refresh(), since the .NET runtime will view it as ineligible for garbage collection)


                       d.  The object gets garbage collected, and no longer exists in the runtime


                       e.  A subsequent request retrieves a new copy of the same object from the AF server