LiveNode Server

Andrew Kluthe andrew at ctech.me
Tue Apr 7 16:21:23 EDT 2015


>>1. Livecode messaging is fully asynchronous. Not semi-async.

Right, when I said semi-async I was referring to the single threadedness of
livecode (which node shares) along with all the baked into livecode stuff
that blocks up messages currently: accessing a large file on disk, posting
some information to a web service with a large json payload being returned.
It's async, with some pretty hard to work around exceptions (url library
specifically has been the primary source of past frustration in this way).

>>3. Livecode does not have closures = passing anonymous callbacks as
params to functions so they can be executed later

As for anonymous callbacks, I totally agree. Most early Node development
had to overcome the callback hell that these patterns introduce. However,
almost all of the nodejs projects and libraries I've worked with leveraged
them heavily or exclusively. Promsies seem to have become the standard way
of dealing with the callback hell that node was so famous for for a long
time. Why does node use anonymous functions over the method you linked to
in the article? Anonymous functions are marked for garbage collection
immediately after being returned. All other functions at the global scope
run the risk of needlessly using memory after they run. I've gotten into
some hairy situations with memory management with these kinds of named
callbacks (specifically for database access and return of lots of results
when not scoped correctly).

Passing a function (not just a name of a function to be used with a send or
a dispatch later on) as a parameter even in your article still demonstrates
something LC just can't do currently. In the article he's still using
closures, it's just got a name instead of being anonymous. It's still a
closure. LC has ways to accomplish similar things by passing names of
functions and using dispatch, but I think it's not exactly the same.
Closures are part of the reason node.js works the way it does and closures
are one of the pirmary reasons javascript was chosen for node. It's
certainly possible to do async without them, but closures are what makes it
easy and kind of a fundamental principle to working in node.js.

>>4. But we can easily call / dispatch calls to functions by passing names
around and we can limit scope by using private handlers or libraries.

Sure, there is nothing STOPPING us from implementing named callbacks in the
current fashion or passing the named callback references dynamically as you
and I mentioned, but from experience trying it this way I feel like it
makes maintaining large projects built this way a lot more difficult. To
the point where I ended up completely redoing most of the livecode stuff
I've written in this way early on because it was getting to be a nightmare
to maintain a completely separate callback functions rather than the sort
of nested structure you get in node with callbacks. It takes a lot of
discipline in placement and grouping of the code that is related in this
way to come back later and make sense of it. In summary: it can be done,
but that doesn't mean that it SHOULD be done.

Kind of a weird long post there. Sorry for the length and probable
repetition of my points.


Also, this was something really neat I've used recently to make node work
in-process with some .NET applications we have. Something that does this
with node and LC would indeed be the bees knees.

http://www.hanselman.com/blog/ItsJustASoftwareIssueEdgejsBringsNodeAndNETTogetherOnThreePlatforms.aspx

Specifically the part about it allowing us to write node extensions in C#
in addition to the standard C and C++ way of doing it. I'd love to be able
to hook node into extensions written in livecode.


On Tue, Apr 7, 2015 at 12:24 PM Richard Gaskin <ambassador at fourthworld.com>
wrote:

> David Bovill wrote:
>
>  > OK. A few questions... I'll post them as assertions to aid clarity.
>
> Personally I find it clearer to read questions as questions, but with
> that explanation I can work with this:
>
>  >   1. Livecode messaging is fully asynchronous. Not semi-async.
>
> What is "semi-asynchronous" in the context of LC?
>
> There is a distinction between "asynchronous" and "non-blocking" that
> I'm not entirely clear on, so I'll use "non-blocking" for now:
>
> Socket I/O messaging can be non-blocking when the "with <message>"
> option is used, e.g.:
>
>     accept connections on port 8888 with message "GotConnection"
>
> But this is of limited value within a single LC instance, since doing
> anything with that message is likely going to involve blocking code
> (e.g., reading a file or accessing a database, doing something with that
> data, and then returning it).
>
> So messages will keep coming in, but they'll queue up.  This may be fine
> for light loads, but when expecting multiple simultaneous connections it
> would be ideal to handle the tasks more independently.
>
> Many programs do this with threading, but we don't have threading in LC.
>
> Instead of multithreading we can use multiprocessing, having multiple
> instances of LC apps each working on a separate task.
>
> The challenge is that to hand off a socket request to a child process
> entirely would require us to have some way of handing over the socket
> connection itself.  I believe fork allows this, but I know of no way to
> launch new instances of an LC app in a way that will hand over the
> socket connection to them.
>
> In lieu of being able to fork, two options I know of are the ones I
> noted earlier; others may be possible as well, but these seem common
> enough to be reasonable starting points:
> <http://lists.runrev.com/pipermail/use-livecode/2015-April/213208.html>
>
>
>
>  >   2. There are a bunch of functions that are currently synchronous in
>  > LiveCode that make it difficult to create asynchronous code - such as
>  > certain network call like POST.
>
> Yes, as above.
>
>
>  >   3. Livecode does not have closures = passing anonymous callbacks as
>  > params to functions so they can be executed later
>
> Not per se, but as you note:
>
>  >   4. But we can easily call / dispatch calls to functions by passing
>  > names around and we can limit scope by using private handlers or
>  > libraries.
>  >
>  > Here is an article about why you should not use anonymous callbacks
>  > that seems interesting in the context of readabiity and literate
>  > programming languages:
>  >
>  >   * Avoiding anonymous JavaScript functions
>  > http://toddmotto.com/avoiding-anonymous-javascript-functions/
>
> Good find.  While most of that is very JS-specific, the
> readability/complexity argument applies in LC well.  As a general rule,
> I feel that "do" is a last resort when all more direct means of
> accomplishing something have been exhausted, and even "dispatch",
> "send", and "value" can have similar impact in terms of
> debugging/maintenance.
>
> I almost never use "do" anywhere, and on servers I limit use of the
> others for another reason not mentioned in the article, security: since
> they execute arbitrary code by design, "do", "dispatch", "send" and
> "value" can potentially be sources of injection when used on any part of
> incoming data.
>
> I use "dispatch" in one place in my server framework, but only after
> checking an incoming command argument against a list of known one-word
> commands; any request missing a command parameter, or having one not
> found on that list, returns an "invalid command" error message.
>
> --
>   Richard Gaskin
>   Fourth World Systems
>   Software Design and Development for the Desktop, Mobile, and the Web
>   ____________________________________________________________________
>   Ambassador at FourthWorld.com                http://www.FourthWorld.com
>
> _______________________________________________
> use-livecode mailing list
> use-livecode at lists.runrev.com
> Please visit this url to subscribe, unsubscribe and manage your
> subscription preferences:
> http://lists.runrev.com/mailman/listinfo/use-livecode
>



More information about the use-livecode mailing list