Async, Futures and Promises

Since I brought it up, Andrew challenged me to start a separate thread for this, here it is. :slight_smile:

I’ve spent the last month in JS-land and, I have to say, I hope that any future for Lucee prioritizes non-blocking development with whatever product they evolve in to. Even so, Javascript callbacks suck - though they have made me write better code in some ways. My biggest beef with server-side javascript has been scopes and callbacks, which force you to work effectively work backward through the request and make debugging and testing a nightmare. Even promise-based development in JS requires you to jump through callback hoops.

With that in mind, with distributed data, auto-scaling, API’s abounding, and the like, I’d love to see something beyond cfthread incorporated in to the core.

Being able to develop sequentially, blocking when needed, and yet still open up non-blocking sections that can sprint on their own through the process of gathering data would be ideal.

(Very basic) Pseudo code example for a concept:

public void function process_stuff(event,prc){
//Anything up to a closing semicolon is executed asynchronously
async{
var stuff = getModel(‘Stuff’).findAll();
//get other stuff
promise(
//scope or null
prc,
//variable name, either scope or, if scope is null, it becomes a local variable
‘moreStuff’,
//async event to ensure
getModel(‘OtherStuff’).findAll()
);

}
//await example - would begin blocking again until the next action is completed
await(
    prc.moreStuff,
    function(){
        //do stuff with moreStuff
    });
  
//future() usage example, would block function execution until the promise arguments are met      
event.setValue(‘doubleStuff’,{future(stuff),future(prc.moreStuff)});

}

The idea with the future() method as a function argument would be to keep it non-blocking until the argument, itself, was called called explicitly. So, if we didn’t want to deal with await, we could just have the future() serve as a pseudo-await() like so:

doStuffWithMoreStuff(future(prc.morestuff)) - which would, in effect, do the same thing as the await() block above.

I’m not a language development expert like many here, so this is a very uninformed poof-of-concept. There would also have to be a server-size timeout mechanism to handle awaits and futures that never materialize - as you could lock up an entire request, and possibly a server, with an incomplete callback or unfulfilled promise.

Anyway, I wanted to open the topic up to discussion, as I think it’s an important one for the future of Lucee.

Jon

Lets be clear it was Adam Cameron not me or someone else called Andrew who
suggested a separate thread :slight_smile:

I’m not really that familiar with the topic, so can you explain how this
differs from using cfthread with either the “join” or “run” actions
specified, as from the above it would appear to me to be the same thing.

Kind regards,

Andrew
about.me http://about.me/andrew_dixon
mso http://www.mso.net - Lucee http://lucee.org - MemberOn 10 March 2015 at 18:56, Jon Clausen <@Jon_Clausen> wrote:

Since I brought it up, Andrew challenged me to start a separate thread for
this, here it is. :slight_smile:

I’ve spent the last month in JS-land and, I have to say, I hope that any
future for Lucee prioritizes non-blocking development with whatever product
they evolve in to. Even so, Javascript callbacks suck - though they have
made me write better code in some ways. My biggest beef with server-side
javascript has been scopes and callbacks, which force you to work
effectively work backward through the request and make debugging and
testing a nightmare. Even promise-based development in JS requires you to
jump through callback hoops.

With that in mind, with distributed data, auto-scaling, API’s abounding,
and the like, I’d love to see something beyond cfthread incorporated in to
the core.

Being able to develop sequentially, blocking when needed, and yet still
open up non-blocking sections that can sprint on their own through the
process of gathering data would be ideal.

(Very basic) Pseudo code example for a concept:

public void function process_stuff(event,prc){
//Anything up to a closing semicolon is executed asynchronously
async{
var stuff = getModel(‘Stuff’).findAll();
//get other stuff
promise(
//scope or null
prc,
//variable name, either scope or, if scope is null, it becomes a local variable
‘moreStuff’,
//async event to ensure
getModel(‘OtherStuff’).findAll()
);

}
//await example - would begin blocking again until the next action is completed
await(
    prc.moreStuff,
    function(){
        //do stuff with moreStuff
    });

//future() usage example, would block function execution until the promise arguments are met
event.setValue(‘doubleStuff’,{future(stuff),future(prc.moreStuff)});

}

The idea with the future() method as a function argument would be to keep
it non-blocking until the argument, itself, was called called explicitly.
So, if we didn’t want to deal with await, we could just have the future()
serve as a pseudo-await() like so:

doStuffWithMoreStuff(future(prc.morestuff)) - which would, in effect, do
the same thing as the await() block above.

I’m not a language development expert like many here, so this is a very
uninformed poof-of-concept. There would also have to be a server-size
timeout mechanism to handle awaits and futures that never materialize - as
you could lock up an entire request, and possibly a server, with an
incomplete callback or unfulfilled promise.

Anyway, I wanted to open the topic up to discussion, as I think it’s an
important one for the future of Lucee.

Jon


You received this message because you are subscribed to the Google Groups
“Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an
email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/etPan.54ff3e57.54fc792c.f65b%40jonclausen-mbp.local
https://groups.google.com/d/msgid/lucee/etPan.54ff3e57.54fc792c.f65b%40jonclausen-mbp.local?utm_medium=email&utm_source=footer
.
For more options, visit https://groups.google.com/d/optout.

Would you get a promise for an async block without blocking on its return?

Rather, “Could you”.

Maybe I’m just not getting it, but the entire body of process_stuff blocks
until the “async” code is completed? What is the benefit of using promises
here? Would you get a promise for an async block without blocking on its
return? Maybe I’m missing something, but it’s shorter syntax for doing a
cfthread and joining it, which means no added benefit for me.

I would like the idea better of JS-style promises better:

process_stuff(event) {
// this is more similar to the way JS promises appear to work.
// the benefit is, you do not have to block process_stuff from returning

  • it is truely async.
    var promise = runAsync(function() {
    return getModel(“Stuff”).findAll();
    }) // promise returned from runAsync
    // if the async function is complete at the time the handler is
    attached, the handler is immediately run. otherwise it is run as a callback
    on the async function’s completion.
    .onSuccess(function(returnValue) {
    event.setValue(“stuff”, returnValue);
    // then maybe:
    // event.continue();
    })
    .onFailure(function() {
    // handle exception
    })
    .onCompletion(function() {
    // do something whether it is successful or failed
    });

    // or more fluently (although it doesnt look right if you run something
    async and do not attach any handlers…)
    var promise = when(function() {}) // when() returns a promise
    .succeeds(function(){})
    .fails(function() {})
    .completes(function() {})
    ;

    // then, if you absolutely must block until the promise is done
    processing:
    promise.block();
    }On Tuesday, March 10, 2015 at 3:26:35 PM UTC-5, Jon Clausen wrote:

Sure. Sorry, meant “Adam”, typed “Andrew”… Oops.

The fundamental issue with threads is that they require an explicit join
at some point. A future() or await() would accomplish somewhat the same
thing, but the join mechanism would would be blocking on the explicit call
for the promised variable. Plus, CFThread is, IMHO unnecessarily verbose
for what it accomplishes. Let’s take my pseudo code in cfthread:

public void function process_stuff(event,prc){
//I have to implicitly create the thread, and have to scope it afterward
thread action=“run” name=“stuff”{
thread.returnValue=getModel(‘Stuff’).findAll();
}

//Ditto
thread action="run" name="otherstuff"{
    thread.returnValue=getModel('OtherStuff').findAll();
}

// here's where I wait for them all to come together again,
// everything is blocked from here on out  
// plus I have to be very verbose and re-scope
thread action="join" thread="stuff,otherstuff";

now I re-scope the variables *sigh*
var stuff = cfthread.stuff;
prc.otherstuff = cfthread.otherstuff;

//do more stuff with stuff *sigh*
for(thing in moreStuff){
    //do things to stuff
}

event.setValue('doubleStuff',{stuff,prc.moreStuff})

}

If you go back to my original example, blocking for “stuff” doesn’t happen
until the variable is explicitly called in event.setValue(), while blocking
does occur for prc.moreStuff in the await tag, I could also make promises
to be passed as futures to the other arguments or even pass futures in to
scopes.

Let’s take this one step further. The server has control of the request
(as in cfflush). Let’s say we were to add a function, ( e.g. -
toDocumentObject(varName,future,[exclude]) ) which would automatically
deliver a JSON object before the document was closed. Rendering could begin
and our request would appear to have very low latency, but something like
AngularJS could pick up the object and use it tor render data once it has
been added to the document. For something like data from a web service,
this could really speed things up, without slowing things down waiting for
the third-party request to process.

toDocumentObject(myStuff,future(stuff),[{“private”:true}]);

This would allow the developer to block for necessary data but use a
single request, rather than a separate AJAX call to pull the JS variables
needed to render the non-essentials.

CFThread, IMHO, is cumbersome and requires to begin blocking far to early.

Jon

On March 10, 2015 at 3:27:39 PM, Andrew Dixon (andrew...@gmail.com <javascript:>) wrote:

Lets be clear it was Adam Cameron not me or someone else called Andrew who
suggested a separate thread :slight_smile:

I’m not really that familiar with the topic, so can you explain how this
differs from using cfthread with either the “join” or “run” actions
specified, as from the above it would appear to me to be the same thing.

Kind regards,

Andrew
about.me http://about.me/andrew_dixon
mso http://www.mso.net - Lucee http://lucee.org - Member

On 10 March 2015 at 18:56, Jon Clausen <jon_c...@silowebworks.com <javascript:>> wrote:

Since I brought it up, Andrew challenged me to start a separate thread
for this, here it is. :slight_smile:

I’ve spent the last month in JS-land and, I have to say, I hope that any
future for Lucee prioritizes non-blocking development with whatever product
they evolve in to. Even so, Javascript callbacks suck - though they have
made me write better code in some ways. My biggest beef with server-side
javascript has been scopes and callbacks, which force you to work
effectively work backward through the request and make debugging and
testing a nightmare. Even promise-based development in JS requires you to
jump through callback hoops.

With that in mind, with distributed data, auto-scaling, API’s abounding,
and the like, I’d love to see something beyond cfthread incorporated in to
the core.

Being able to develop sequentially, blocking when needed, and yet still
open up non-blocking sections that can sprint on their own through the
process of gathering data would be ideal.

(Very basic) Pseudo code example for a concept:

public void function process_stuff(event,prc){
//Anything up to a closing semicolon is executed asynchronously
async{
var stuff = getModel(‘Stuff’).findAll();
//get other stuff
promise(
//scope or null
prc,
//variable name, either scope or, if scope is null, it becomes a local variable
‘moreStuff’,
//async event to ensure
getModel(‘OtherStuff’).findAll()
);

}
//await example - would begin blocking again until the next action is completed
await(
    prc.moreStuff,
    function(){
        //do stuff with moreStuff
    });
   
//future() usage example, would block function execution until the promise arguments are met       
event.setValue(‘doubleStuff’,{future(stuff),future(prc.moreStuff)});

}

The idea with the future() method as a function argument would be to keep
it non-blocking until the argument, itself, was called called explicitly.
So, if we didn’t want to deal with await, we could just have the future()
serve as a pseudo-await() like so:

doStuffWithMoreStuff(future(prc.morestuff)) - which would, in effect, do
the same thing as the await() block above.

I’m not a language development expert like many here, so this is a very
uninformed poof-of-concept. There would also have to be a server-size
timeout mechanism to handle awaits and futures that never materialize - as
you could lock up an entire request, and possibly a server, with an
incomplete callback or unfulfilled promise.

Anyway, I wanted to open the topic up to discussion, as I think it’s an
important one for the future of Lucee.

Jon

You received this message because you are subscribed to the Google Groups
“Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an
email to lucee+un...@googlegroups.com <javascript:>.
To post to this group, send email to lu...@googlegroups.com <javascript:>
.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/etPan.54ff3e57.54fc792c.f65b%40jonclausen-mbp.local
https://groups.google.com/d/msgid/lucee/etPan.54ff3e57.54fc792c.f65b%40jonclausen-mbp.local?utm_medium=email&utm_source=footer
.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google Groups
“Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an
email to lucee+un...@googlegroups.com <javascript:>.
To post to this group, send email to lu...@googlegroups.com <javascript:>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/lucee/CAG1WijXain_PBHg8f%3DeB7RCKbCcUbJ7CsWkGrWyMfWej2JQPdA%40mail.gmail.com
https://groups.google.com/d/msgid/lucee/CAG1WijXain_PBHg8f%3DeB7RCKbCcUbJ7CsWkGrWyMfWej2JQPdA%40mail.gmail.com?utm_medium=email&utm_source=footer
.
For more options, visit https://groups.google.com/d/optout.

Yes, my pseudo code doesn’t illustrate the benefit beyond a few examples, and you’re right the function body is blocked in the end. I don’t mind the JS style promises, either (other than the callback nesting) and I like the .on[Result] methods for error handling.

What I do like about the example I proposed was that the promise can scope the variable in to a referenced object in one call and that key can reference the future fulfillment of the promise - in or outside of the function body. It basically creates a separate type object that exists as that type until it is fulfilled, when it turns in to the assigned type.

The JS style promise in your example doesn’t incorporate the future() call, which can be in or outside of the function body. This makes handling the variable tricky and probably gives nightmares to purists, but it gives flexibility in request assembly. You could even include a default argument in the future, if the promise isn’t fulfilled and omit the “onFailure” methods to let let it fail gracefully, without all of the conditionals (let logging handle it?)

future(myVar,”The requested information could not be retrieved”).

JonOn March 10, 2015 at 5:37:38 PM, Jesse Shaffer (@Jesse_Shaffer) wrote:

Maybe I’m just not getting it, but the entire body of process_stuff blocks until the “async” code is completed? What is the benefit of using promises here? Would you get a promise for an async block without blocking on its return? Maybe I’m missing something, but it’s shorter syntax for doing a cfthread and joining it, which means no added benefit for me.

I would like the idea better of JS-style promises better:

process_stuff(event) {
// this is more similar to the way JS promises appear to work.
// the benefit is, you do not have to block process_stuff from returning - it is truely async.
var promise = runAsync(function() {
return getModel(“Stuff”).findAll();
}) // promise returned from runAsync
// if the async function is complete at the time the handler is attached, the handler is immediately run. otherwise it is run as a callback on the async function’s completion.
.onSuccess(function(returnValue) {
event.setValue(“stuff”, returnValue);
// then maybe:
// event.continue();
})
.onFailure(function() {
// handle exception
})
.onCompletion(function() {
// do something whether it is successful or failed
});

// or more fluently (although it doesnt look right if you run something async and do not attach any handlers…)
var promise = when(function() {}) // when() returns a promise
.succeeds(function(){})
.fails(function() {})
.completes(function() {})
;

// then, if you absolutely must block until the promise is done processing:
promise.block();
}

On Tuesday, March 10, 2015 at 3:26:35 PM UTC-5, Jon Clausen wrote:
Sure. Sorry, meant “Adam”, typed “Andrew”… Oops.

The fundamental issue with threads is that they require an explicit join at some point. A future() or await() would accomplish somewhat the same thing, but the join mechanism would would be blocking on the explicit call for the promised variable. Plus, CFThread is, IMHO unnecessarily verbose for what it accomplishes. Let’s take my pseudo code in cfthread:

public void function process_stuff(event,prc){
//I have to implicitly create the thread, and have to scope it afterward
thread action=“run” name=“stuff”{
thread.returnValue=getModel(‘Stuff’).findAll();
}

//Ditto
thread action="run" name="otherstuff"{
    thread.returnValue=getModel('OtherStuff').findAll();
}

// here's where I wait for them all to come together again,
// everything is blocked from here on out   
// plus I have to be very verbose and re-scope
thread action="join" thread="stuff,otherstuff";

now I re-scope the variables *sigh*
var stuff = cfthread.stuff;
prc.otherstuff = cfthread.otherstuff;

//do more stuff with stuff *sigh*
for(thing in moreStuff){
    //do things to stuff
}

event.setValue('doubleStuff',{stuff,prc.moreStuff})

}

If you go back to my original example, blocking for “stuff” doesn’t happen until the variable is explicitly called in event.setValue(), while blocking does occur for prc.moreStuff in the await tag, I could also make promises to be passed as futures to the other arguments or even pass futures in to scopes.

Let’s take this one step further. The server has control of the request (as in cfflush). Let’s say we were to add a function, ( e.g. - toDocumentObject(varName,future,[exclude]) ) which would automatically deliver a JSON object before the document was closed. Rendering could begin and our request would appear to have very low latency, but something like AngularJS could pick up the object and use it tor render data once it has been added to the document. For something like data from a web service, this could really speed things up, without slowing things down waiting for the third-party request to process.

toDocumentObject(myStuff,future(stuff),[{“private”:true}]);

This would allow the developer to block for necessary data but use a single request, rather than a separate AJAX call to pull the JS variables needed to render the non-essentials.

CFThread, IMHO, is cumbersome and requires to begin blocking far to early.

Jon

On March 10, 2015 at 3:27:39 PM, Andrew Dixon (andrew...@gmail.com) wrote:

Lets be clear it was Adam Cameron not me or someone else called Andrew who suggested a separate thread :slight_smile:

I’m not really that familiar with the topic, so can you explain how this differs from using cfthread with either the “join” or “run” actions specified, as from the above it would appear to me to be the same thing.

Kind regards,

Andrew

mso - Lucee - Member

On 10 March 2015 at 18:56, Jon Clausen jon_c...@silowebworks.com wrote:
Since I brought it up, Andrew challenged me to start a separate thread for this, here it is. :slight_smile:

I’ve spent the last month in JS-land and, I have to say, I hope that any future for Lucee prioritizes non-blocking development with whatever product they evolve in to. Even so, Javascript callbacks suck - though they have made me write better code in some ways. My biggest beef with server-side javascript has been scopes and callbacks, which force you to work effectively work backward through the request and make debugging and testing a nightmare. Even promise-based development in JS requires you to jump through callback hoops.

With that in mind, with distributed data, auto-scaling, API’s abounding, and the like, I’d love to see something beyond cfthread incorporated in to the core.

Being able to develop sequentially, blocking when needed, and yet still open up non-blocking sections that can sprint on their own through the process of gathering data would be ideal.

(Very basic) Pseudo code example for a concept:

public void function process_stuff(event,prc){
//Anything up to a closing semicolon is executed asynchronously
async{
var stuff = getModel(‘Stuff’).findAll();
//get other stuff
promise(
//scope or null
prc,
//variable name, either scope or, if scope is null, it becomes a local variable
‘moreStuff’,
//async event to ensure
getModel(‘OtherStuff’).findAll()
);

}
//await example - would begin blocking again until the next action is completed
await(
    prc.moreStuff,
    function(){
        //do stuff with moreStuff
    });
    
//future() usage example, would block function execution until the promise arguments are met        
event.setValue(‘doubleStuff’,{future(stuff),future(prc.moreStuff)});

}

The idea with the future() method as a function argument would be to keep it non-blocking until the argument, itself, was called called explicitly. So, if we didn’t want to deal with await, we could just have the future() serve as a pseudo-await() like so:

doStuffWithMoreStuff(future(prc.morestuff)) - which would, in effect, do the same thing as the await() block above.

I’m not a language development expert like many here, so this is a very uninformed poof-of-concept. There would also have to be a server-size timeout mechanism to handle awaits and futures that never materialize - as you could lock up an entire request, and possibly a server, with an incomplete callback or unfulfilled promise.

Anyway, I wanted to open the topic up to discussion, as I think it’s an important one for the future of Lucee.

Jon


You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/etPan.54ff3e57.54fc792c.f65b%40jonclausen-mbp.local.
For more options, visit https://groups.google.com/d/optout.


You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+un...@googlegroups.com.
To post to this group, send email to lu...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/CAG1WijXain_PBHg8f%3DeB7RCKbCcUbJ7CsWkGrWyMfWej2JQPdA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

You received this message because you are subscribed to the Google Groups “Lucee” group.
To unsubscribe from this group and stop receiving emails from it, send an email to lucee+unsubscribe@googlegroups.com.
To post to this group, send email to lucee@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/lucee/d18d2857-119a-4f2f-b1e7-69578281d6ba%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Since I brought it up, Andrew challenged me to start a separate thread for
this, here it is. :slight_smile:

Cheers, Jim, for starting this thread :-p

If ppl are confused or unclear about how futures / promises etc work, and
why one might want to use them, and how they differ from just using thread
blocks, perhaps some background reading might help:

Implementations:
http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html

http://promise.rubyforge.org/
http://docs.scala-lang.org/overviews/core/futures.html

(I list these because some language implementations/docs might make things
more clear than others, and there are idiosyncrasies with both).

In production I’ve used them with PHP via Guzzle, and kinda document their
usage in a coupla blog articles:

Note that these are more focusing on Guzzle itself, but this uses futures
for making async HTTP calls, so there’s “real world” usage in there.

I’m sure other ppl have got some real-world examples they could share too?
Examples always make understanding easier, IMO. I also think knocking
together a CFML implementation of an approach to this should be fairly
easy, and something I’ve thought about doing, so if I find time amongst my
PHP work & other bits ‘n’ pieces, I might write some code.

I suggest this RTFM because it’s all pretty well-trod ground outside of
CFML, so it might be good preparation for participating in this
conversation. I - for one - still think I have some reading to do before I
start piping up further, forming opinions, or asking questions.

I will say, though, that I think this is a really good idea.On Tuesday, 10 March 2015 18:56:29 UTC, Jon Clausen wrote:


Adam