Cacheing for XRL

Poster Content
nk4um Moderator
Posts: 848
July 15, 2013 21:48

Hi Gary,

I have reviewed the code. I think I have found an immediate problem. I had assumed that you were returning the processed SQL as a String - but it is wrapped in a utility class. FlSql. This object does not override equals. When any pass by value resource is placed in a the PBV space - then the equals method on the representation is used to compare when two spaces that are dynamically generated are actually exactly equivalent.

This is what you have so you must implement equals on the representation. I add this method to FlSql. Please let me know if this fixes it...

@Override
    publicboolean equals(Object obj)
    {
        if(obj instanceof FlSql)
        {   FlSql objSql=(FlSql)obj;
            returnthis.getSql().equals(objSql.getSql());
        }
        elsereturn false;
    }

P.

PS I am on skype now if you want to do this realtime.

Like · Post Reply
nk4um Moderator
Posts: 848
July 15, 2013 21:21

Hi Gary - hmmmmm. OK we need to carefully look at the cache scope and make sure it is coherent. It likely we just need to change the ordering a little to get what we need.

The cache key depends upon the scope and the identifier. If too much of the scope is differing then you will not get good overlap.

Can you please send me visualizer traces of the problem channels and I can review them tomorrow first thing. Then we can set up a screen share tomorrow morning your time to tune the caching of the framework.

FYI the visualizer can be used to do a cache comparison of two traces to show exactly what is preventing the cache hit. Select a trace and hit "compare caching" select another trace and hit "compare caching" - the two traces will be shown side by side in a cache equivalence view.

Please send me two visualizer traces of a channel that is not caching as expected and I'll look at it straight away.

Cheers,

Peter

Like · Post Reply
nk4um User
Posts: 92
July 15, 2013 21:00Still have caching issue

So after major reconstructive surgery to the architecture and changing the resolution scope of the application, we are back where we started. Unable to cache with xrl:includes to the point of ROC not being able to work at a performance level that is considered acceptable. Instead of one database query that joins customer address to state, we tried using a customer resource that does an xrl:include to res:/state/MN. This works out to ALWAYS be 2 queries when accessing the customer address, and is only cached when accessing through the HTTP layer, to the point where I am considering doing xrl:includes that do HTTPGet requests to localhost, since internal requests do not cache. I have tried setting all pass by references to pass by value, but now it looks like we are stumped by the transaction scope where we are using a transactedConnection. Since both my GET and POST requests happen in the same space, they are both using transactedConnection. In essence, I want to get to the point where a URI is the key to my resource and that if I have xrl:includes to that resource, it will be cached. I should have been keeping track along with all the other changes at what point did we lose cacheability, or do I even remember ever having it, I seem to remember it working at some point, but with all the subsequent development it has been lost.

Like · Post Reply
nk4um User
Posts: 92
October 28, 2011 14:40

The link to the documentation did not work for me. I checked with Apposite to see if I had the latest and all but one unrelated module I was up to date.

Like · Post Reply
nk4um Moderator
Posts: 848
October 24, 2011 16:34

There's also this document too...

http://localhost:1060/book/view/book:guide:physicalreference/doc:physicalreference:caching

In the context of cache scope keying, Tony describes pass-by-request as an "Anti-Pattern". (Of course if caching is not you main goal then its not off limits).

Like · Post Reply
nk4um Moderator
Posts: 848
October 24, 2011 16:28

Hi Gary - ok now I see where things are going awry...

This is nested request is the culprit...

<argumentname="operand">
  <request>
    <identifier>active:sqlQuery</identifier>
    <argumentname="operand">res:/resources/state/stateCache.sql</argument>
  </request>
</argument>

The problem here is that you're using a pass-by-request for this, which is lazily evaluated and has an indeterminate scope (at least to your application). You can't assume that the lazy sub-request will have a stable scope (as far as cache keying is concerned).

FYI in NK5 we've added quite a lot of explanatory documentation about scope and its affect on caching here...

http://localhost:1060/book/view/book:roc:guide/doc:roc:caching

The upshot is that nested requests like this are not advisable. If you're starting to get complex assemblies of requests then its a much better idea to put them into a sequential DPML script.

However to move forward a very simple solution is to just pull the query request out into an endpoint of its own and reference it in the original xslt endpoint...

<config>
  <endpoint>
    <grammar>res:/stateCache/MN</grammar>
    <request>
      <identifier>active:xslt</identifier>
      <argumentname="operator">res:/resources/state/state.xslt</argument>
      <argumentname="operand">res:/stateQuery</argument>
    </request>
  </endpoint>
  <endpoint>
    <grammar>res:/stateQuery</grammar>
    <request>
      <identifier>active:sqlQuery</identifier>
      <argumentname="operand">res:/resources/state/stateCache.sql</argument>
    </request>
  </endpoint> ...
</config>

Let me know if this helps. Also let me know if the NK5 docs on caching and scope help too.

Cheers,

Peter

Like · Post Reply
nk4um User
Posts: 92
October 24, 2011 16:11Continue cacheing issue

We are still having a problem with the cacheing issue. Instead of a WebEx type meeting, I created a simple set of Endpoints that replicates the problem.

The first endpoint res:stateCache/MN styles a response from active:sqlQuery. If I make some calls to this over HTTP, the first call executes active:sqlQuery but the second call to /stateCache/MN is cached at the HttpBridge. All is cool.

I then put in a XRL call. Second endpoint. It calls into a simple XML with an xrl:include that references the res:/stateCache/MN.

Now res:/stateCache/MN was reference when I came in the first time with http://domain/stateCache/MN. I am expecting that when I make a request to http://domain/stateXrl that the xrl:include request to res:/stateCache/MN would NOT make another sqlQuery request. However, using the visualizer this is what I am seeing. It is also what I am seeing in all cases to sqlQuery inside the request. The res:/state/stateCache.sql and the configRDBMS.xml are showing that they are from Cache.

If you tell me that xrl requests to sqlQuery do not get cached, this would be a major blow to my framework as it is something that I was relying on as I do a lot of composition of resources using XRL.

module.xml

          <endpoint>
                   <grammar>res:/stateCache/MN</grammar>
                   <request>
                       <identifier>active:xslt</identifier>
                       <argument name="operator">res:/resources/state/state.xslt</argument>
                               <argument name="operand">
                                   <request>
                                       <identifier>active:sqlQuery</identifier>
                                       <argument name="operand">res:/resources/state/stateCache.sql</argument>
                                   </request>
                       </argument>
                   </request>
               </endpoint>
               <endpoint>
                   <grammar>res:/stateXrl</grammar>
                   <request><identifier>active:xrl2</identifier>
                   <argument name="template">res:/resources/state/xrl.xml</argument></request>
               </endpoint>

State:xslt <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:nk="http://netkernel.org" version="1.0">

   <xsl:output method="xml"/>
   <xsl:template match="/">
       <state>
           <xsl:apply-templates />
       </state>
   </xsl:template>
   <xsl:template match="/resultset/row">
           <xsl:attribute name="stateCode">
               <xsl:value-of select="STATE_CODE"/>
           </xsl:attribute>
           <abbreviation><xsl:value-of select="STATE_ABBR"/></abbreviation>
           <name><xsl:value-of select="STATE_DESC"/></name>
   </xsl:template>

</xsl:stylesheet>

Simple SQL select * from state_code where state_abbr = 'MN'

XRL file. <root xmlns:xrl="http://netkernel.org/xrl">

   <xrl:include>
       <xrl:identifier>res:/stateCache/MN</xrl:identifier>
   </xrl:include>

</root>

Like · Post Reply
nk4um User
Posts: 92
September 23, 2011 19:21Review

Hi Peter,

What time suits you? On Tuesday so far, only my afternoon is free from 3pm CST. I could come in early - say 8am CST for an hour. Otherwise I do not have any hours during the day, just a half hour at 12:30pm CST.

Gary

Like · Post Reply
nk4um User
Posts: 92
September 23, 2011 19:19

Posted by pjr (View)
Hi Gary,

You know I now realise this is the main area we should have spent time on when we were face-to-face earlier this week!

From my recent knowledge of what your doing I think this is actually down to cross-talk between architectural layers resulting in a changing spacial scope for different requests. Therefore although the identifier of the resource is the same its cache key is spacially different.

What I suggest is that we arrange a time (in your 5% band!) to share a screen and look through this aspect in detail. I'm slammed with jobs to do today but how about Tuesday next week?

It was great to visit you this week and it gave me a much better perspective about what you've been up to ;-)

Cheers,

Peter

Like · Post Reply
nk4um Moderator
Posts: 848
September 23, 2011 11:24Continue Our Review

Hi Gary,

You know I now realise this is the main area we should have spent time on when we were face-to-face earlier this week!

From my recent knowledge of what your doing I think this is actually down to cross-talk between architectural layers resulting in a changing spacial scope for different requests. Therefore although the identifier of the resource is the same its cache key is spacially different.

What I suggest is that we arrange a time (in your 5% band!) to share a screen and look through this aspect in detail. I'm slammed with jobs to do today but how about Tuesday next week?

It was great to visit you this week and it gave me a much better perspective about what you've been up to ;-)

Cheers,

Peter

Like · Post Reply
nk4um User
Posts: 92
September 23, 2011 00:07Change to pass by value still not working

I have changed my internal code now to be passByValue. There are no pass by references. However, when I look at the visualizer I see that my resource res:/state/9 is still not coming from cache. If I look at the representation cache, I see that there are 4 instances of res:/state/9 with 1 hit each instead of one instance with 4 hits. In a previous post, you indicated that there was a pbv:template that was by reference. This is not in my code, but rather in the XRL code. From what I have now, it looks like the only cache point I have is at http://localhost/state/9 and it cannot cache at res:/state/9. My implementation is relying on the cache of some of these instances so that I can compose resources together. Each resource has a database request. If I end up having to make 3 database queries instead of composing 3 resources with only one database query and 2 cached responses then my implementation is going to be very expensive.

It only goes to res:/state/9 if coming in through the HTTPBridgeOverlay. It looks like it could be an issue with XRL? I am expecting xrl:include with the identifier reference to res:/state/9 (Cached when going though HTTPBridgeOverlay) to be cached when coming from xrl:include.

Any ideas?

Like · Post Reply
nk4um Moderator
Posts: 579
September 10, 2011 13:53Documentation updated for pass-by-request

I've added the following to the documentation describing the nested requests (pass-by-request):

Using pass-by-request is useful for explicit chaining of requests and also has the advantage of lazy evaluation of the requests which can be useful if that argument may never need to be evaluated due to some conditional processing. However when using pass-by-request it is very is easy to inhibit cachability of your resources. This is due the the complexity of the request scope that can occur with nested sub-requests. Therefore it is not recommended to use pass-by-request for anything other than prototyping unless you really know what you are doing! Using DPML is good alternative which allows for nested requests in a declarative way and has been optimised to enable good cachability.
Like · Post Reply
nk4um Moderator
Posts: 579
September 9, 2011 16:33

What request are you saying needs to be changed? ... Are you suggesting I execute each of these in turn, collect the response XML and pass each of those in by value.
Yes that approach would do it.

Why is the resource res:/state/29 that is displayed in the Resource Cache still not cached.
It is being cached but because it has pass-by-request in it's scope it is not re-usable. (You can see this in the visualizer output, there is the pbv:template that is your request chain) By executing those requests early and passing them by value you will avoid this problem. Like I said, pass-by-request is quite bad with respect to caching. It's nice for convenience, but has this side effect. That needs to be better documented.

... Thus, I need to have a baseAccessor class that tries to discover the origin of the request so that it can identify the structure of the passed parameters
Yes this base class is ok. I think it is similar to the approach you used in Netkernel 3, rationalising all the possible ways data could be send to the accessor.

However you need create a two layer pattern. Have a second accessor that is abstracted from HTTP that just receives it's arguments using a well defined interface. This second layer should be cachable then. Put all your sub-requests and work in this second accessor. This isn't too much work, all the code should pretty much cut and paste across and both accessors can be in the same space. Thinking about the layers of resources and their cachability is important to structuring your app.

If you like I can call you and we can discuss this in detail. It may make sense for me to see your code, maybe I could help you refactor it. Once you see the pattern it will make more sense. What do you think?

Tony

Like · Post Reply
nk4um User
Posts: 92
September 9, 2011 16:00What request

Hi Tony,

What request are you saying needs to be changed? The xrl:include that calls to res:/state/29 or the attachGoldenThread, or the set of calls that I chain together. Right now, I chain from inside out, freemarker, sqlQuery, xslt and xrl as passByRequest and then make a single call to execute. Are you suggesting I execute each of these in turn, collect the response XML and pass each of those in by value.

Why is the resource res:/state/29 that is displayed in the Resource Cache still not cached.

With regards to the httpRequest, this is my work around because after almost 3 days of writing an overlay to convert POST to SINK, I found out that would not work because sqlQuery requires a SOURCE. Also, depending on whether I come into the space from HTTP or from a Test Space, the parameters will be in a different structure. Thus, I need to have a baseAccessor class that tries to discover the origin of the request so that it can identify the structure of the passed parameters and normalize them into a Map of parameters that the work accessors can use. Thus the HttpRequest does an exist first to determine if coming from HTTP, but I am checking for either POST or SINK requests.

Gary

Like · Post Reply
nk4um Moderator
Posts: 579
September 9, 2011 12:37

Hi Gary, thanks for the detailed information. I think I understand what is happening.

I think you are using addArgumentByRequest in the com.findlaw.nk.data.DataAccessAccessor. I can't be sure from the visualizer trace but it is certainly getting lazily evaluated down inside the xrl and xslt accessors.

I would suggest directly sourcing the query directly and passing by value. This will help. Pass by request is actually quite bad for cachability because the scope of evaluation of the argument is often quite different to what you might expect because it is evaluated later. It is something that we are starting to realize needs to be discouraged when you want to achieve good cachability. (Documentation needs to be improved in this regard)

This is another problem I discovered too. This is that your java accessor is making requests to the httpRequest: resources. This will limit cachability of that layer and that is the layer you have your golden thread. In this regard I would suggest that you separate out your http specific functionality out and have a two layer approach, with the second layer being cachable and having the golden thread.

I hope all this makes sense.

Cheers, Tony

Like · Post Reply
nk4um User
Posts: 92
September 8, 2011 22:30Cacheing continued

Hi Tony,

So the jar file you provided did not work. So I looked into a few other things that could possibly help us. It might be my understanding of how the cacheing works and something within my code or setup that I need to change.

So firstly if I run the requests where I would expect to see res:/state/29 cached, then look into Resolutioion Cache, res:/state/29 is marked as cached as well as active:java+class@com.findlaw.nk.data.DataAccessAccessor+entity@state+id@29+part@ which is what the res:/state/29 grammar maps to. If I run http://localhost:9511/state/29 it is cached at the HttpBridgeOverlay level.

When I run the visualizer, though it indicates that it resolves all the components that make up res:/state/29. Most of the resources such as sql and xslt are marked as (from cache), but where it references res:/state/29 it goes into MapperOverlay and when it gets down to having to execute the SQL there is a SQLQueryAccessor that sources active:sqlQuery+oper and@pbv%3Aoperand. This in my mind is executing a call to the DB. It actually does this twice for the exact same resource.

Here is my Grammar for this resource.

<endpoint>
  <grammar>res:/
    <choice>
      <groupname="entity">
        <regex>country</regex>
      </group>
      <groupname="entity">
        <regex>county</regex>
      </group>
      <groupname="entity">
        <regex>lookup</regex>
      </group>
      <groupname="entity">
        <regex>metro</regex>
      </group>
      <groupname="entity">
        <regex>practice</regex>
      </group>
      <groupname="entity">
        <regex>security</regex>
      </group>
      <groupname="entity">
        <regex>staff</regex>
      </group>
      <groupname="entity">
        <regex>state</regex>
      </group>
      <groupname="entity">
        <regex>tuple</regex>
      </group>
    </choice>/
    <choice>
      <groupname="id">
        <regextype="alphanum" />
      </group>
      <groupname="id">
        <regextype="nmtoken" />
      </group>
    </choice>
    <optional>
      <groupname="part">
        <regextype="anything" />
      </group>
    </optional>
  </grammar>
  <request>
    <identifier>active:java</identifier>
    <argumentname="class">com.findlaw.nk.data.DataAccessAccessor</argument>
    <argumentname="entity">arg:entity</argument>
    <argumentname="id">arg:id</argument>
    <argumentname="part">arg:part</argument>
  </request>
</endpoint>

Here is the cacheing strategy logic within my accessor

        String resource = String.format("res:/resources/%s/cacheConfig.xml", uriBreakDown.resourcePath);
        // Attach a golden thread - response is cached by defaultif (context.exists(resource))
        {
            String entity = uriBreakDown.entity;
            INKFRequest request = context.createRequest("active:attachGoldenThread");
            request.addArgument("id", entity);
            context.issueRequest(request);
        }
        else
        {
            //Since cache configuration not found - do not cache the response
            response.setNoCache();
        }

I have confirmed through debugging and viewing of Visualizer, that when making the request to res:/state/29 it identifies that the cacheConfig.xml resource exists and attaches the golden thread.

Like · Post Reply
nk4um Moderator
Posts: 579
September 8, 2011 14:27

Ok, we have two plans of attack. First I'm going to send you a patched cache jar that is going into the next release. Let's see if that fixes the problem. Otherwise the cache compare tool that I developed for the last conference can be used to determine if there are any scope differences.

I'll send the patched jar by email.

Cheers, Tony

Like · Post Reply
nk4um User
Posts: 92
September 7, 2011 21:42

This I believe is a separate issue. It appears that cacheing is done at the HttpBridge level for my localhost/state/29, but if internally from another request I have a call to localhost/findlawcustomer/123 that has a sub-request to res:/state/29 and this makes another DB request even though I have res:/state/29 attached to golden thread. Am I missing something in my cacheing. Most of my other resources, sql, xslt etc are from cache, but the DB query still gets made again. Ideally, res:/state/29 is fully cached.

Like · Post Reply
nk4um Moderator
Posts: 579
September 7, 2011 21:23

Hi Gary, sorry for the communication mix up. I thought you had said previously that the connection pool fix I sent you had sorted out this issue too. Is this not the case?

Cheers, Tony

Like · Post Reply
nk4um User
Posts: 92
September 7, 2011 21:03

Hi Tony,

I sent you the trace in an email. Do you require any further information.

Like · Post Reply
nk4um Moderator
Posts: 579
September 1, 2011 12:31

Hi Gary, please can you send me the visualizer trace for this non-caching. It maybe be an unintentional scope issue or it may be related to the cache bug which I discovered yesterday. (These bugs always have a habit of striking twice so I wouldn't be surprised!)

Either way the visualizer trace should tell.

Cheers, Tony

Like · Post Reply
nk4um User
Posts: 92
August 31, 2011 22:31Cacheing for XRL

I am noticing that if I access a resource from HTTP (http://domain/state/MN) it gets converted to res:/state/MN. When I request the resource again from HTTP, it gets it from cache. However, if I am inside NK and I access res:/state/MN from a stylesheet using xrl as in

<xrl:include>

   <xrl:identifier>res:/state/MN
    </xrl:identifier>

</xrl:include>

this will not be cached. The /state/MN is cached at the HttpBridgeOverlay, while the internal request does not go through this overlay and my cacheing below that is not working. Looking at the visualizer, domain/state/MN goes into my MapperOverlay within my space. The grammar is able to identify that it should make a call to an Accessor and maps to active:java+class@co m.findlaw.nk.data.Da taAccessAccessor+entity@state+id@MN. I attach this context to a goldenThread, but that does not help.

Also, it appears the XRL request ends up creating another database pool thus not allowing for succesful pooling of database connections.

Like · Post Reply