backing logic in functional style

187 views
Skip to first unread message

Pohl Longsine

unread,
Apr 13, 2012, 5:46:55 PM4/13/12
to mustac...@googlegroups.com

Sam,

I read the early part of this blog post with great interest.  In particular, I am keen to prototype a BigPipe-esque design in my own project, using Mustache.java.   The following passage piqued my curiosity:


"You can also use this to defer sections of the page to write them out later, a la Big Pipe. This has been invaluable to easily maintaining Bagcheck’s low-latency design. The downside to this is that you need to write your Java code in a functional style, I suggest that you use Google collections to do it right."

I was already coming to the conclusion that arriving at a good design for my template-backing logic is central to the goal.  I'm already familiar with Guava, and I'm curious if you have any more thoughts to offer about using a functional style in the backing-logic layer.   Could you say a few more words about this?   The closest I have seen in this forum is about using the Guava Function interface to implement {{#i18n}}foo{{/i18n}}, but I suspect that the above passage was hinting at something a little deeper.



(and Thank you for Mustache.java)

Sam Pullara

unread,
Apr 14, 2012, 5:48:47 PM4/14/12
to mustac...@googlegroups.com
This was intended to suggest that you use lazy generators rather than using greedy collections as the concurrent evaluation system I had in place could take advantage of that to automatically multithread your code. I've changed the implementation of mustache.java around somewhat since then as aggressive concurrent evaluation was detrimental to performance when it was unnecessary but you can still take advantage of concurrent evaluation with the right backing code.

If you want to evaluate something concurrently with the rest of the evaluation of the template but still want it to come out in the order of the template instead of returning the actual value from the field or method, return a Callable. You can see some tests of this behavior in InterpreterTest. Right now you do need to explicitly close the writer returned from execute to get the right blocking behavior, so be careful with that.

In terms of BigPipe-style handling, I should really release a small example framework where it is used. The general idea is that you return a referenceable div, then asynchronously begin work and add a Future to a list to be evaluated at the end of the body that will transform results into javascript insertions.

Sam

Pohl Longsine

unread,
Apr 16, 2012, 12:23:59 PM4/16/12
to mustac...@googlegroups.com


On Saturday, April 14, 2012 4:48:47 PM UTC-5, Sam Pullara wrote:
This was intended to suggest that you use lazy generators rather than using greedy collections as the concurrent evaluation system I had in place could take advantage of that to automatically multithread your code. I've changed the implementation of mustache.java around somewhat since then as aggressive concurrent evaluation was detrimental to performance when it was unnecessary but you can still take advantage of concurrent evaluation with the right backing code.


Thank you for this bit of historical context.  That is helpful.
 
If you want to evaluate something concurrently with the rest of the evaluation of the template but still want it to come out in the order of the template instead of returning the actual value from the field or method, return a Callable. You can see some tests of this behavior in InterpreterTest. Right now you do need to explicitly close the writer returned from execute to get the right blocking behavior, so be careful with that.

Thank you again for this tidbit.  I went looking through the source code, trying to find the point where you return what I presumed to be a wrapper that implements Writer so that I could see how you implement the blocking behavior, but from my reading it looks like you're returning the very same Writer that I pass in, unwrapped.   Could you refer me to the class & line number where you return a wrapper?   If you don't wrap, could you explain how the servlet would end up waiting for all of the Callables to complete?
 
In terms of BigPipe-style handling, I should really release a small example framework where it is used. The general idea is that you return a referenceable div, then asynchronously begin work and add a Future to a list to be evaluated at the end of the body that will transform results into javascript insertions.

This is exactly what I was planning, so this is encouraging.   Are partials handled as though they were Callable?  I ask because it seems natural that I would want to define the contents of a pagelet in another template and have it asynchronously inserted like this:

<script>arrived("my_pagelet_id", "{{>my_pagelet_file");</script>

Or should I avoid this idea and instead implement my pagelet as a Callable in the backing-code layer that compiles its own mustache file?

Pohl Longsine

unread,
Apr 16, 2012, 1:19:28 PM4/16/12
to mustac...@googlegroups.com
I just found the LatchedWriter class, and I see how it is used as a wrapper in those targeted situations where an ExecutorService has been set.  

I think I also have answered my own question about partials.  Please check my sanity on this:   I'm guessing that I should not concern myself with whether partials are implemented as Callables, but rather concern myself with whether the backing-logic for the variables within that pagelet template are implemented as a Callable.   In other words:  I should go ahead and use the partial syntax that I suggested, and let the backing code behind my_pagelet_file handle concurrency.

Sam

unread,
Apr 16, 2012, 7:53:17 PM4/16/12
to mustache.java
It isn't the most beautiful thing in the world, but I added this to
the main code base. You now just use it off the shelf I think as of
0.7.3-SNAPSHOT. Here is the test that I am using (I'll be doing more
tests, but so far this one works so i thought I would get it in):

<html>
<head><title>{{title}}</title></head>
<body>
{{>deferredpartial}}
{{{deferred}}}
</body>
</html>

Then when you evaluate it, you return DEFERRED for the partial value.
As so:

public void testDeferred() throws IOException {
DefaultMustacheFactory mf = new DeferringMustacheFactory(root);
mf.setExecutorService(Executors.newCachedThreadPool());
Object context = new Object() {
String title = "Deferred";
Object deferred = new
DeferringMustacheFactory.DeferredCallable();
Object deferredpartial = DeferringMustacheFactory.DEFERRED;
};
Mustache m = mf.compile("deferred.html");
StringWriter sw = new StringWriter();
m.execute(sw, context).close();
assertEquals(getContents(root, "deferred.txt"), sw.toString());
}

I've set it up so you can override some aspects of the behavior by
extending DeferringMustacheFactory. The general idea is that when you
defer a partial, it will immediately write out the insertion point and
then spin up a new task to evaluate the partial, adding the resulting
Future to the DeferredCallable registered under the name "deferred".
Improvements to the API welcome!

Sam
> >>http://www.javarants.com/2011/10/09/new-features-and-extensions-in-mu...
>
> >> "You can also use this to defer sections of the page to write them out
> >> later, a la Big Pipe<https://www.facebook.com/note.php?note_id=389414033919>.
> >> This has been invaluable to easily maintaining Bagcheck’s low-latency
> >> design. The downside to this is that you need to write your Java code in a
> >> functional style, I suggest that you use Google collections<http://code.google.com/p/guava-libraries/> to

Pohl Longsine

unread,
Apr 17, 2012, 12:25:55 PM4/17/12
to mustac...@googlegroups.com
I can't overstate how awesome it is that you have provided a means to control concurrency at the granularity of partials.  I look forward to trying this out and giving you feedback.  Thank you.

Pohl Longsine

unread,
Apr 18, 2012, 11:35:02 AM4/18/12
to mustac...@googlegroups.com
I've had some time to ponder this mechanism, and now I'm sure I grasp its intended use.

The thing that concerned me the most is how DeferringMustacheFactory involves itself in emitting the html for the div targets and the script tags, and in managing the ids for the divs.

I see that I am expected to return a subclass of DeferringMustacheFactory if I want to override this behavior.  Suppose, for example, that what I'd really like is a means to put all of this into the template itself, where I would like the contract for my "pipes" to be defined.   I can create a custom subclass of DeferringMustacheFactory that overrides both writeTarget() with a no-op implementation, and writeDeferral() with an implementation that appends only the escaped result:

 protected void writeTarget(Writer writer, Long divid) throws IOException {

      // append nothing. 

  }


 protected static void writeDeferral(StringBuilder sb, Deferral deferral, Object o) {

    sb.append(o.toString().replace("<""&lt;").replace("\"""\\\"").replace("\n""\\n"));

  }




This would allow me to define my html so that my {{^deferredpartial}} code would merely kick-off the concurrent execution, and the {{{deferred}}} code would be used where I would want the HTML literal to appear as a function argument to my own javascript function:

<script>arrived("my_pagelet_id", "{{{deferred}}}");</script>


So I'm pleased at how flexible your answer is.   It both handles the easy case where Mustache.java tries to make pipes as easy as possible, and allows the more complex case, where all of the HTML and javascript is in the templates where they belong.

I guess the missing piece is that I really would need a way to define a code that lets me control, in the template, where the flushing happens, because in my example above the flush() would happen before the script tag is closed, which would defeat the purpose of the pipe.

<script>arrived("my_pagelet_id", "{{{deferred}}}");</script>{{flush}}


...is that solution distasteful?   I'm not sure how (or even if) the backing code would be involved for a flush hint.   The java.io.Flushable interface may be useful here, since that would give a safe way to allow backing code to do nothing more harmful than a flush.   I'll think about this some more.

Pohl Longsine

unread,
Apr 19, 2012, 8:27:50 AM4/19/12
to mustac...@googlegroups.com
Sam,

Do you have any thoughts about what I'm describing here?  I should be able to do this with what you've provided so far.  For example, I can sneak a reference to my servlet's OutputStream into a scope object before I execute my template to hack-together my own {{flush}} hint:

       public String flush() {
               stream.flush();
               return "";
       }

...although obviously I'd have to pass in the raw servlet output stream, and not the stream wrapper returned from the execute method, since I need to prepare the scope objects before execute is called.   Do you see any problem with this idea?

Can you think of a more natural way to satisfy my use case?

Sam Pullara

unread,
Apr 19, 2012, 11:52:57 AM4/19/12
to mustac...@googlegroups.com
I am looking at another way of doing it. Just hadn't had time to
finish it up. You can do what you are saying with the current system
but I am exploring more natural ways to build it...

Sam

Pohl Longsine

unread,
Apr 19, 2012, 12:21:10 PM4/19/12
to mustac...@googlegroups.com
Excellent, I look forward to seeing what you come up with.  I'll plug-on with my current prototype in the meantime.

I thought of one more issue in the shower this morning that may effect your design, and it ain't pretty:   Suppose I have a pagelet whose data comes from a system owned by another team who is having a hard time responding in a timely manner.   For example, say I have a pagelet for an advertisement sidebar that's nice-to-have, but not essential to the functioning of my application.  The provider, however, might occasionally have problems meeting their SLA.

My servlet, therefore, might want to pass a timeout parameter into the execute() method so that it can cut bait (to use a fishing metaphor) and close the servlet's output stream in a timely manner, protecting my servlet container's thread pool from depletion.

I'll also want to be able to emit a different script tag when a pagelet fails to respond in time, so that client-side javascript can be made aware of the failure, and perhaps repair it later with an AJAX call.  In terms of the current design, that might manifest as a protected writeDeferralError() method in the DeferringMustacheFactory.

Sam Pullara

unread,
Apr 19, 2012, 12:29:14 PM4/19/12
to mustac...@googlegroups.com
This is definitely in scope. I'm trying to put one together where all
the logic occurs in your backing code and all the output is in the
template.

Sam

Reply all
Reply to author
Forward
0 new messages