VB and donut hole caching

3 views
Skip to first unread message

Louis DeJardin

unread,
Jun 30, 2009, 4:51:41 PM6/30/09
to Spark View Engine Dev

Support for Visual Basic checked in, was a pretty straightforward
implementation to create a code generator for another target language.

Thinking of jumping into donut hole caching next

http://sparkviewengine.codeplex.com/WorkItem/View.aspx?WorkItemId=3155

http://haacked.com/archive/2009/05/12/donut-hole-caching.aspx


Will involve a few key things... One is a <cache> element that will
wrap material that will be skipped on a cache-hit. Another is a cache
provider interface, default implemenation probably based on the
system.web.caching. And finally (because rendering is much less
expensive than data acquisition) probably also introduce a value
holder to lazy-load data.

I'm thinking the data class would be something that takes a lambda in
the constructor and has a key and value properties. The Value property
can call the lambda at-most-once just-in-time.


So in an action:

public ActionResult ShowProduct(string productCode)
{
var repos = new ProductRepository();

ViewData["prod"] = new ValueHolder(productCode, key=> { return
repos.FetchByCode(key); });
}


and in view:

<viewdata prod="ValueHolder[[Product]]"/>

<cache key="stuff.Key">
<p>Product Name: ${prod.Value.Name}</p>
<p>Quantity In Stock: ${prod.Value.QuantityInStock}</p>
</cache>

any thoughts? anyone have particular experiences with the
system.web.caching namespace for things to watch out for?

Jarrett Vance

unread,
Jul 10, 2009, 6:31:02 PM7/10/09
to spar...@googlegroups.com
I'm interested in your progress with caching.  It has been on my mind lately and everything points to this being a hard problem to deal with when using the WebFormsViewEngine.  I'm wondering if with Spark, you could bypass the legacy caching mechanisms and create your own lower level mechanism.

I've been thinking from the context of a modular widget system that invokes sub-actions.  This results in something I think of as an action plan that ultimately writes to Response.Output.

For example:

Action ViewBlogPost(id)
-> Render Master View
  -> Sub-action LoginWidget
    -> Render LoginWidget Partial
  -> Render Blog Post View
     -> Sub-action PopularPostsWidget
        -> Render PopularPosts Partial
     -> Sub-action TwitterWidget
        -> Render Twitter Partial
  -> Sub-action AnalyticsWidget
    -> Render AnalyticsWidget Partial

Results in the following action plan.
Master[0], LoginWidget[0], Master[1], BlogPost[0], PopularPosts[0], BlogPost[1], Twitter[0], BlogPost[2], Master[2], Analytics[0], Master[3]

For complete caching flexibility, each action in the plan is associated with a cache dependency.  Then, the action plan would only call the action to re-render the parts of the output that have a cache miss.

Is this possible?

Louis DeJardin

unread,
Jul 11, 2009, 3:37:58 AM7/11/09
to spar...@googlegroups.com
Actually that's kind of similar to how it's panning out. The
boundaries are defined by the cache elements, rather than by partial
file or other rendering boundaries, so you could cache output in
whatever hunks you see fit.

Each occurance of the cache element visited as code is generated
becomes it's own distinct scope (key) which will be run or not
depending on cache miss or hit. You can also provide addtl values in
<cache key="xxx"> (value of expression xxx combined with scope key at
run time) if the contents vary by productId, for example, or username,
or sessionid.

The cache memory itself is abstracted by an ICacheService with Get and
Store methods, and the default cache service calls the native ASP.NET
Cache methods Get and Insert. That way it can get the benefits of the
existing memory pressure algorithm, duration and non-used expiration,
etc.

One big question would be how to provide a mechanism to offer some
determistic cache entry invalidation. You can have a simple ttl
duration of course, but beyond that what's the cleanest way of hooking
cache entries into some sort of origination of a signal that some
change has invalidated those entries?

Louis DeJardin

unread,
Jul 11, 2009, 7:08:58 PM7/11/09
to spar...@googlegroups.com
Sorry if the response makes no sense also. On a bberry on vacation, so
can't edit for clarity very well. :)

In a nutshell you'd say

<viewdata productId="int" product="ValueHolder[[Product]]" />
...more stuff...
<cache key="productId" duration="10.minutes()">
Product ${product.Value.Name}
Unit price ${product.Value.UnitPrice}
#Html.RenderPartial("ShowSpecials", new{prod=product.Value});
!{Html.ActionLink(...)}
</cache>
...stuff after...

So you can cache inside partials or around them or at whatever
granularity you can say what key it varies by.

The assumption is you would use a ValueHolder<T> class in your view
data, and the T Value {get} property would call a Func<T> lambda to
acquire T just once the first time it's referenced. Know what I mean?
That way you can avoid the real cost, which is data acquisition, if
there's a cache hit but keep the code in the action where it belongs.
Reply all
Reply to author
Forward
0 new messages