too easy for me to crash my dart server with unhandled errors, is there a good pattern to mitigate?

620 views
Skip to first unread message

Seth Ladd

unread,
Jun 27, 2013, 1:03:03 PM6/27/13
to General Dart Discussion
Hi server-side Dart developers and library authors,

I'm writing a lot of server-side Dart code these days, and I keep running into exceptions that crash my server because they are unhandled. What is a good pattern to follow so that I ensure all exceptions are handled and don't take down the running process?

There's a LOT of async code going on (HTTP server, Postgress, Google+ API, and more). I feel like I'm chaining correctly and putting in a lot of onError and whenComplete etc but I still run into "unhandled exceptions". Even if I do an awesome job (or maybe I'm doing a really poor job?) of putting in all the error handlers, I still use a lot of code that I didn't write which may throw exceptions from deep within async chains.

What I'm looking for is:

1) A global, for-real way to handle all unhandled exceptions. So nothing slips through and takes down the server.

2) A way to get the full stack trace of where the exceptions originally occurred (no matter how asyncy), so I can do something about it.

I see two APIs that might help me, but marked as Experimental: runZonedExperimental and getAttachedStackTrace. So I feel like it's a know problem, but one we don't have a solution for (yet)

Are there good patterns for this? What have others done?

Thanks!
Seth

Justin Fagnani

unread,
Jun 27, 2013, 1:48:25 PM6/27/13
to General Dart Discussion
One thing you could try is to start an isolate via spawnFunction() and either use the optional unhandledExceptionCallback argument to either handle the exception and continue (return true), or kill the isolate (return false) and start a new one. Most of your server logic will then be in a top-level function that's no main(), and main() will simply start the worker isolate and monitor it.

I of couse would love to see a unhandledExceptionCallback for the current isolate as well as for spawnUri().

-Justin



--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 

Florian Loitsch

unread,
Jun 27, 2013, 1:49:51 PM6/27/13
to General Dart Discussion
You can give async:runZonedExperimental a try. It should catch all uncaught errors except the ones from isolates and the DOM.
See tests/lib/async/catch_errors.dart for an example on how to use it.

caveat: as the name suggests. This is still experimental.


--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 



--
Give a man a fire and he's warm for the whole day,
but set fire to him and he's warm for the rest of his life. - Terry Pratchett

Bob Nystrom

unread,
Jun 27, 2013, 2:22:32 PM6/27/13
to General Dart Discussion
On Thu, Jun 27, 2013 at 10:03 AM, Seth Ladd <seth...@google.com> wrote:
I feel like I'm chaining correctly and putting in a lot of onError and whenComplete etc but I still run into "unhandled exceptions".

Are you using onError, or catchError()? My understanding is that you almost always want the latter.
 
Are there good patterns for this?

For pub, our basic rules are:
  1. Avoid asynchrony whenever possible. The maintenance overhead is rarely worth the performance (for us).

  2. Any method which internally uses a Future must return a Future, and all async errors must be piped to that future.

  3. If a method returns a Future, all runtime errors must be reported through that and not thrown synchronously.

  4. Write a giant pile of tests. Test all of your failure modes.

  5. Cry and be sad once you start dealing with Streams too.
It's certainly not been easy for us but pub is relatively good at not top-leveling errors at this point. It has an easier job because it doesn't stay running for very long, though.

Cheers,

- bob
Message has been deleted
Message has been deleted

Florian Loitsch

unread,
Jun 27, 2013, 5:13:29 PM6/27/13
to General Dart Discussion
shouldn't have answered while rushing out of the office. You had already discovered `runZonedExperimental`...


On Thu, Jun 27, 2013 at 7:49 PM, Florian Loitsch <floi...@google.com> wrote:
You can give async:runZonedExperimental a try. It should catch all uncaught errors except the ones from isolates and the DOM.
See tests/lib/async/catch_errors.dart for an example on how to use it.

caveat: as the name suggests. This is still experimental.


On Thu, Jun 27, 2013 at 7:03 PM, Seth Ladd <seth...@google.com> wrote:
Hi server-side Dart developers and library authors,

I'm writing a lot of server-side Dart code these days, and I keep running into exceptions that crash my server because they are unhandled. What is a good pattern to follow so that I ensure all exceptions are handled and don't take down the running process?

There's a LOT of async code going on (HTTP server, Postgress, Google+ API, and more). I feel like I'm chaining correctly and putting in a lot of onError and whenComplete etc but I still run into "unhandled exceptions". Even if I do an awesome job (or maybe I'm doing a really poor job?) of putting in all the error handlers, I still use a lot of code that I didn't write which may throw exceptions from deep within async chains.

What I'm looking for is:

1) A global, for-real way to handle all unhandled exceptions. So nothing slips through and takes down the server.

2) A way to get the full stack trace of where the exceptions originally occurred (no matter how asyncy), so I can do something about it. 

I see two APIs that might help me, but marked as Experimental: runZonedExperimental and getAttachedStackTrace. So I feel like it's a know problem, but one we don't have a solution for (yet)
It's a known problem. You can use best practices to reduce the bugs in your code, but in order to deal with them dynamically you currently need experimental APIs.


Are there good patterns for this? What have others done?

Thanks!
Seth

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 



--
Give a man a fire and he's warm for the whole day,
but set fire to him and he's warm for the rest of his life. - Terry Pratchett

Seth Ladd

unread,
Jun 28, 2013, 12:11:56 AM6/28/13
to General Dart Discussion
Thanks Justin. This is an HTTP server, so once we have transferables (and I assume, a transferable socket) then I look forward to exploring an isolate-based server architecture.

And yes, +1 for unhandledExceptionCallback from the current isolate. That would be really really helpful.

Seth Ladd

unread,
Jun 28, 2013, 12:19:18 AM6/28/13
to General Dart Discussion
Thanks Bob! Responses below.


On Thu, Jun 27, 2013 at 11:22 AM, Bob Nystrom <rnys...@google.com> wrote:

On Thu, Jun 27, 2013 at 10:03 AM, Seth Ladd <seth...@google.com> wrote:
I feel like I'm chaining correctly and putting in a lot of onError and whenComplete etc but I still run into "unhandled exceptions".

Are you using onError, or catchError()? My understanding is that you almost always want the latter.

I used Future's onError only once or twice, because I had to be selective. Luckily, almost all of my Future chains can end with a single catchError (thanks to getAttachedStackTrace)
 
 
Are there good patterns for this?

For pub, our basic rules are:
  1. Avoid asynchrony whenever possible. The maintenance overhead is rarely worth the performance (for us).

This is not really an option for us, because as you know, async in infectious. Because we use so many 3rd party pub packages, all it takes is one to return a Future or Stream.
 

  1. Any method which internally uses a Future must return a Future, and all async errors must be piped to that future.

This is a great bit of advice, and something we strive hard to maintain. I'm discovering that the server-side frameworks that we're using need to take this to heart. We may deal with futures all through our stack, but the server framework is still designed for a single callback on a request. It's fun to see how Dart's async features drive the design of frameworks and how they can be extended.

One challenge is when a function encounters an if/else. When I start branching on which Future I'll run or if I return a value or Future from inside of then(), I need to really ensure I return and chain the right things.
 

  1. If a method returns a Future, all runtime errors must be reported through that and not thrown synchronously.

  2. Write a giant pile of tests. Test all of your failure modes.

True dat. However, no matter how good, I don't feel most developers can cover 100% of all cases. We really need a global exception handler as a safety net. I'd hate for Dart to get a reputation of crashy.
 

  1. Cry and be sad once you start dealing with Streams too.
To be fair, I haven't found Streams add that much more cognitive load. Once you're in async with Futures, you're always with async. So I'm hoping and currently finding that the same advice applies for futures and streams.

 
It's certainly not been easy for us but pub is relatively good at not top-leveling errors at this point. It has an easier job because it doesn't stay running for very long, though.

Cheers,

- bob

--

Seth Ladd

unread,
Jun 28, 2013, 12:21:55 AM6/28/13
to General Dart Discussion
On Thu, Jun 27, 2013 at 2:13 PM, Florian Loitsch <floi...@google.com> wrote:
shouldn't have answered while rushing out of the office. You had already discovered `runZonedExperimental`...

I've started to deploy it, happy that we have something like it. I didn't realize it can't capture DOM exceptions, but luckily for us that's OK since we're dealing with the server.

I'd like the server-framework to run the callbacks inside of a runZoned for me. Much like wrapping the callback in a try/catch just in case there's a problem with the request.

This is great real-life experience, I look forward to seeing lots of Dart servers out there! :)

Yulian Kuncheff

unread,
Jun 28, 2013, 1:31:45 AM6/28/13
to mi...@dartlang.org
This is good to know. I might rearchitecture my code to properly take advantage of RunZoned in Fukiya.

@Seth: for now, I did a try/catch in my code as you suggested, so you should no longer die on exceptions thrown in handlers. I will probably look into making all the futures in my code into RunZoned, and I think I have most with onErrors.

Tom Yeh

unread,
Jun 28, 2013, 1:59:17 AM6/28/13
to mi...@dartlang.org
It can be protected at the container, like we did In Rikulo Stream. By assuming all handlers being asynchronous, one can catch all exceptions (except compile errors) at the container (or the very first general handler) and then forward the error, if any, into a (Java-like) general error handling mechanism, such as Stream's error handling.

Iván Zaera Avellón

unread,
Jun 28, 2013, 4:25:34 AM6/28/13
to misc
WARNING: long and dense text, sorry. But please read it because it took me long to write it ;-).

The solution implemented in Rikulo works nice (at least I'm using it and I have no problem). But that's only true if you pipe all Futures from the first time your request handler is invoked to the deepest method in the chain. As others said, this is not an easy work. But it can be done.

For instance, if you have a standard CRUD application you need to pick a request from the client, get something from the database, and render a view. Of these three operations, the access to the DB is async. Once you have something async everythings has to turn to async (asynchrony is viral). This means that, if you want to do something useful in a webapp you'd probably need async code. 

Worse, if you write a framework/architecture and plan to have callbacks implemented by users of the framework you normally allow those callbacks to return Future because you can't know if the user will do something async or not. That's the case of Rikulo's handler, which before was sync and you needed to call close on the request to finish it and now everything is piped through the returned Future.

To show it with some code let's see how I handle a request for a list of authors:

Future handle( HttpConnect connect ) { 
  return _database.find( connect.request.uri.queryParameters ).then( (authors) {
      return renderJsonObject( connect, authors );
  }.then( (_) {
      print("done with the request");
  });
}

I have used return instead => to make it more clear. As you see I don't put catchError()'s. I could have put some, but as long as I chain the Futures correctly the errors will finally end catched in Rikulo with the Future I'm returning. It will be something like:

handle(connect).then( (_) {
  print("request handled .....");
}).catchError( (err) {
 connect.response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
});

The bad news is that all this fails if just one Future is not chained. For instance, if I remove the return from renderJsonObject and that method fails nobody will catch the error and it will crash the server. It's even worse because if you use a third party library and it forgets to chain one Future then you are done. You will fail and can't do anything to fix it (apart from modifying the third party lib, of course). This happened to me while using mongodb driver and had to issue some pull requests to Vadim to chain all Futures.

BTW, and related to the previous paragraph, I strongly recommend not to use Completers unless it is absolutely necessary. This is because Completers are error prone in the sense that it's very easy to forget to wire an error to a completer. We tend to wire the result and forget some/all errors (this is a human condition, it's not that we don't care, it's that it's so difficult). This was the case of mongodb, it used Completers, now it's using Future chaining in most places (I think).

And just to end, one final tip: if you wrap calls inside a new Future() you get some extra protection for free because any sync errors happening will get piped through the Future. Example:

Future handle( HttpConnect connect ) { 
  .
  .
  throw "Bad error";
  .
  return _database.find( connect.request.uri.queryParameters ).then( (authors) {
      return renderJsonObject( connect, authors );
  }
}

With this code, if you call handle() and .catchError(), you won't get the "Bad error" and the server will crash. But if you do:

Future safeHandle( connect ) => new Future( () => handle(connect) );

safeHandle(connect).then( (_) {
  print("request handled .....");
}).catchError( (err) {
 connect.response.statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
});

It will do, because the safeHandle will catch the "Bad error" and will pipe it through the future. 

This technique is also valid to allow a callback function to be implemented synchronously or asynchronously at the wish of the implementor while not impacting the caller. Example:

libFunctionPrintGreeting() {
  new Future( () => callback() ).then( (greeting) {
    print(greeting);
  });
}

This way I can implement callback() sync or async:

callback() => "hola";

or 

callback() {
  return getGreetingFromDb();
}

Future getGreetingFromDb() {
  // async code
}

The End. Thanks for getting here :-).





2013/6/28 Tom Yeh <tom....@gmail.com>
Message has been deleted

Iván Zaera Avellón

unread,
Jun 28, 2013, 5:59:25 AM6/28/13
to misc
>I think this is normal behavior in this case.

I know. I was just explaining how it works :-).

Definitely it would be good to have something that "auto-chains" Futures. Relying on the programmers to chain all Futures is, to say the least, dangerous. 

Imagine the case I mentioned: you are using a 3rd party lib and the author forgot to chain one Future or didn't pipe an error to a Completer. There's *absolutely* no way to fix this now unless your 3rd party lib is changed. And, in the server, this means: it crashes until the library is fixed. Not very robust for a server, I suspect...

>This not works in current Dart implemetation.
>
>void test() {
>  new Future(() {
>    new Future(() => throw null);
>  }).catchError((e) {
>    print(e); // Never called
>  } );
>}

This example shows what I say. If the inner Future (the one that throws null) could be automagically wired to the outer by the "compiler" it would save a lot of headaches. I often forget to put the "return" and leave some tree of Futures unchained. Sometimes it is easy to see it, but others it takes me a long time to figure out where's the missing return. In other words: it is usually easy to diagnose that you haven't chained some future, but it is very difficult to fix.

>You cannot run future in parallel effective even in cooperative mode.
>
>void test() {
>  new Future(() {
>    new Future(() => throw null);
>    new Future(() => throw null);
>    new Future(() => throw null);
>  }).catchError((e) {
>    print(e);
>  } );
>}

I think (correct me if I'm wrong) that what you are trying to do here can be effectively achieved with one of the static functions found in Future:

  /**
   * Wait for all the given futures to complete and collect their values.
   *
   * Returns a future which will complete once all the futures in a list are
   * complete. If any of the futures in the list completes with an error,
   * the resulting future also completes with an error. Otherwise the value
   * of the returned future will be a list of all the values that were produced.
   */
   static Future<List> wait(Iterable<Future> futures)




2013/6/28 mezoni <andrew...@gmail.com>
>> For instance, if I remove the return from renderJsonObject and that method fails nobody will catch the error and it will crash the server.

I think this is normal behavior in this case.
This is due the fact the inner future not attached to outer future.
Outer future are method body of "handle" and inner future are call to "renderJsonObject".
Exceptions propagated only through continuations (chains).
This type of exception handling may be not supported in Dart.
This is default behavior in Microsoft NET (all task detached from parents).
But in Microsoft NET this is not a problem because they proposed new way of async writing code with "await".
Awaitable not required continuations. It trap exceptions similar to synchronous.
You can write
try {
  await SomeExceptionalTask();
  print("Hello");
  } catch(e) {
}

This code will generated to state machine. State machine not required continuations.
It works as executor of synchronous code blocks. Only states switched asynchronously.

But Dart work not as state machine.
But as I understand from your words outer future ignore exceptions in inner future.

This not works in current Dart implemetation.

void test() {
  new Future(() {
    new Future(() => throw null);
  }).catchError((e) {
    print(e); // Never called
  } );
}

I often say that Dart futures are obsolete.
But Dart continue improving obsolete technology.
This not means lack of "await".
Not. This is lack effective cooperative-parallelism.

You cannot run future in parallel effective even in cooperative mode.

This is not supported in Dart.

void test() {
  new Future(() {

    new Future(() => throw null);

    new Future(() => throw null);

    new Future(() => throw null);

  }).catchError((e) {
    print(e);
  } );
}

Alos you cannot simple to cancel the jobs running in cooperative-parallel way.

This words not helps to something. This is just attention.
Message has been deleted

Iván Zaera Avellón

unread,
Jun 28, 2013, 6:59:32 AM6/28/13
to misc
>Not. If you you forgotten to add return here then the exceptions becomes unhandled.

Of course. But he have agreed that if you forget any return, then you are invalidating the whole Future chaining. I thought you just wanted to run some async tasks in parallel and handle the errors in a central place. That can be achieved with Future.wait() method if, of course, you chain *all* Futures correctly.

>And you are sure that they are run in a cooperative-parallelism mode but not in sequence mode?

No idea how it is implemented. Intuitively they should run all in parallel passing through the event loop. That would mean that if they have a more complex async calls tree inside them (not just a plain return null) that calls would be interspersed in the event loop, like any other async code.

I will have a look to the "Typescript promise await", thanks for the tip. I'm relatively new to async server programming (only did async I/O in Windows and Unix some time ago, but nothing more serious) and I think it's very interesting to have something coherent in Dart. These days people are normally used to synchronous programming and not having a good async model in Dart can lead to tons of garbage code in the following years >:-).




2013/6/28 mezoni <andrew...@gmail.com>
>> If the inner Future (the one that throws null) could be automagically wired to the outer by the "compiler" it would save a lot of headaches.

Often this done not "automagically by compiler".
This often done in programmatic way by your own wish.

>> I think (correct me if I'm wrong) that what you are trying to do here can be effectively achieved with one of the static functions found in Future:
>> static Future<List> wait(Iterable<Future> futures)

Not. If you you forgotten to add return here then the exceptions becomes unhandled.
It just wait when all completed but not attached to outer future.

And you are sure that they are run in a cooperative-parallelism mode but not in sequence mode?

void test() {
  new Future(() {
    Future.wait(
     [new Future(() => throw null),
     new Future(() => throw null)
     ]);
  }).catchError((e) {
    print(e); // Never called
  } );
}

Also exists another way to solve this problems. But is also required some style of programming and supplied libraries.

It allows to simulate the state machine (or similar) but code are written in human way.

This is not a "then hell" but...
... I don't want to say now but I am trying to write supplied library that will be allow write async code similar to synchronous (with some approximation).

This idea half from my head and half from "Typescript Promise await" proposal.
This is not the same as "Typescript Promise await" proposal but similar.
The same idea but different implementation and usage.

If I have the time and desire I'll write it.
If you want to know about what I say please look at "Typescript Promise await" library and guess yourself.

dam...@altern.org

unread,
Jun 28, 2013, 7:04:41 AM6/28/13
to mi...@dartlang.org
I am also having trouble catching all exceptions. My problem is that I never know exactly what can be thrown by a method. To be safe, I should always use something like this (and the equivalent with Futures):

try {
  breedMoreLlamas();
} on OutOfLlamasException {           // A specific exception
  buyMoreLlamas();
} on Exception catch(e) {             // Anything else that is an exception
  print('Unknown exception: $e');
} catch(e) {                          // No specified type, handles all
  print('Something really unknown: $e');
}

...but in practice this is too heavy.

I wish I could declare the exceptions thrown by methods and futures. The analyzer could then detect when I forget to catch an exception, as with Java. I feel like Dart is missing an important feature here... If the point is to make Dart "lighter", I think a better approach could be to make exception declaration (and/or checks) optional. It would be better than nothing.

Iván Zaera Avellón

unread,
Jun 28, 2013, 7:18:00 AM6/28/13
to misc
That's a good point. There's no consensus in Java about if all exceptions should be checked (mandatory to catch) or runtime (optional to catch). I personally prefer a mix of the two.

It would not be Dartish (IMHO) to make catching exceptions mandatory, but there should be at least a way to declare them, as you say. If we annotate parameter types I don't see why we shouldn't annotate exceptions. With that we could get hints from the analyzer.

Unfortunately right now we have to different mechanisms to propagate exceptions: one for sync code (try/catch) and another for async (catchError) which don't merge too well. How would you annotate a function that can throw a sync exception and return an async error (I know this is not a good practice, but it is in fact, possible)? Something like:

Future<String> badPractice() throws Exception

would mean it can sync throw Exception, but how would you specify that it can throw Exception async too?




2013/6/28 <dam...@altern.org>

dam...@altern.org

unread,
Jun 28, 2013, 7:33:17 AM6/28/13
to mi...@dartlang.org
How would you annotate a function that can throw a sync exception and return an async error (I know this is not a good practice, but it is in fact, possible)? Something like:

Future<String> badPractice() throws Exception

would mean it can sync throw Exception, but how would you specify that it can throw Exception async too?

I guess this bad practice could become forbidden. It would be nice to unify a bit more async and sync errors, and this could get in the way. Otherwise we could use an "async" keyword to declare async exceptions :

     Future<String> badPractice() throws Exception, async Exception

dam...@altern.org

unread,
Jun 28, 2013, 7:38:57 AM6/28/13
to mi...@dartlang.org
... or there could be a type of exception with the class AsyncException, possibly deriving from Exception. Other async exceptions would derive from it. Maybe this new class could also help unifying sync and async errors...
Message has been deleted

Alex Tatumizer

unread,
Jun 29, 2013, 5:00:28 PM6/29/13
to mi...@dartlang.org
This Zone thing - I'm surprised in didn't make headlines in the mailing list. I expected BREAKING NEWS or something, but it never materialized.
Strange - because it's a BIG DEAL.
Maybe it is not 100% figured out yet, but definitely, it's a good step toward disentangling current mess of error processing in async runtime.
I just wanted to say: I appreciate it. 

Is it really difficult to intercept DOM callbacks to cover all bases?
One of the consequences:, the effect won't be limited to dart VM - code generated by dart2js  would enable sane error processing in browsers, which is currently completely missing.

I also lilke the fact that Zone is a self-contained "small" concept. If any monadic mechanism ever emerges, it would be much simpler to implement on top of Zones. 
Message has been deleted

mrmtampa

unread,
Jun 30, 2013, 6:47:39 AM6/30/13
to mi...@dartlang.org
Bookmark this thread!!!

This is a prime example of why I love this list. There is no other place a newb like me could get these insights.

Thanks


Alex Tatumizer

unread,
Jun 30, 2013, 11:20:24 AM6/30/13
to mi...@dartlang.org
> Given the fact that the question was raised about this many times and a long time ago

This was exactly my point. Issue was raised so many times, within so long time ... and when it finally materialized - ... nothing
No fireworks, no brass orchestra, no jubilation  - nothing, total silence.

In fact, the last celebration I remember on this board was when "map" suddenly renamed itself to "mappedBy" and then, following public outrage, back to "map". The ensued carnival lasted for about a week - that was a genuine triumph of human mind.

I believe dart needs both negative and positive feedback, or else next time we request something - what will be the motivation of doing it? Why bother if no one really appreciates the results?

Sure, this Zone thing is not yet fully figured out, and may require some extra polish, but it's a very good step in the right direction, and I bet it's not the last step! We will see async operations in their full glory some day!


Message has been deleted
Message has been deleted

Alex Tatumizer

unread,
Jun 30, 2013, 6:06:52 PM6/30/13
to mi...@dartlang.org
> Style of organising private code (and thoughts) in Dart team is not clear for me..
It's because Dart is moving ahead at such tempo that the code cannot keep pace...

> No. I don't like Future's.
Futures are not supposed to be liked, they are not intended for use by human programmers. They are good only for code generation within more humane concept. Don't lose hope! (But don't hold your breath either :-)

Alex Tatumizer

unread,
Jun 30, 2013, 10:40:46 PM6/30/13
to mi...@dartlang.org
I think mezoni's example demonstrates a potential bug in implementation of Future.
Wasn't there an intention to run ".then" for synchronously completed futures in the next cycle?
If so, this should apply to all kinds of Futures, including those completed implicitly.
All Futures in the above example complete implicitly, though some of them are semi- futures (for the lack of better word (*).
Maybe Bob can comment on that.

(*) the invocation of "then" can return future or non-future, which makes things a bit nuanced.
This one doesn't return future, but could:
.then((unused) {
    print('$name phase2');
    hardWork(ms);
  }).

 Whether the next "then" should be called immediately or not is not clear - but to make things consistent, it better wait for the next cycle, no?

Message has been deleted
Message has been deleted

Jim Trainor

unread,
Jul 1, 2013, 4:59:46 AM7/1/13
to mi...@dartlang.org
Is Google developed Dart only for Dart Team or it developed it for world-wide community?

This must be a rhetorical question.

Regarding api design, etc....

Dart took the Future pattern from Java.  Streams appear in Java concurrent programming also so that may be a borrowed idea as well, although the term "stream" is fairly generic and seems to appear in all sorts of different environments.  Both no doubt are used identically elsewhere also.

Pretty much exactly that same model is what made it possible for Java developers to (finally) perform the sort of multiplexed non-blocking io that is necessary to build scalable servers. (See java nio. That same behaviour is what makes responsive applications - a different sort of scalability.) I don't think the Dart team needed to do a requirements analysis, or engage in a broad discussion, to know it was good direction.   Before this Java developers stumbled under the misguided notion that running multitudes of threads all performing synchronous IO idea was a good idea on a server.  It's really useful to travel back in time 10 or 20 years and write a server the way it was done then - using a select(), poll(), or kqueue() or windows completion port driven event loop, in C, performing multiplexed IO to understand how efficient this is. If you can get your hands into a device driver the value will sink in further. An ancient FTP server can handle thousands of concurrent connections on modest hardware.

On the client side there are only a few cases where awareness of the Future implementations relationship to the event loop is necessary.   The only cases I've found are situations where a component takes some sort of automated clean up action the next time the event the runs.  I've only encountered two cases: 1) indexed_db closed the current transaction at the start of the next transaction if no database operations are pending (solution: using Completer.sync() to execute the futures that will queue up next db ops without leaving the event loop), and 2) the js-interop implementation releases proxy scopes at the next event loop (solution: retain proxies that are bound to code that will execute beyond the current event loop iteration).

Forgive me if I'm stating common knowledge.



Florian Loitsch

unread,
Jul 1, 2013, 5:30:10 AM7/1/13
to General Dart Discussion
We never invoke the callback immediately when registering `then` (or `catchError`) callbacks. However we do invoke chained `then`s in sequence once it starts executing.
There are two reasons:
- we know that the frame stack is empty (or at least tail-called) and that executing the next `then` thus just avoids going back to the event-loop.
- it makes it easier to reason about a program.

For the second point, imagine the following synchronous program:

foo() { ... }
bar() { foo(); someGlobal = 499: return 42; }
toto() { use(bar()); print(someGlobal); }

Now imagine that foo becomes asynchronous:

Future foo() { ... }
bar() { return foo().then((_) { someGlobal = 499; return 42; }; }
toto() { bar().then(use).then((_) { print(someGlobal); }); }

In the synchronous version the code was able to rely on the fact that the global `someGlobal` was not changed when returning from `bar`. We want to keep the same guarantee for asynchronous code. You will still run into asynchronous pit-falls, but being able to rely on uninterrupted execution when returning from a function is nice.

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 

Florian Loitsch

unread,
Jul 1, 2013, 5:33:50 AM7/1/13
to General Dart Discussion
Thanks.
Fwiw: we only expose a small sub-part of the zones-work so far (and even that is marked as experimental). Once the other core-libraries stabilize I want to spend more time on it.

On Sat, Jun 29, 2013 at 11:00 PM, Alex Tatumizer <tatu...@gmail.com> wrote:
This Zone thing - I'm surprised in didn't make headlines in the mailing list. I expected BREAKING NEWS or something, but it never materialized.
Strange - because it's a BIG DEAL.
Maybe it is not 100% figured out yet, but definitely, it's a good step toward disentangling current mess of error processing in async runtime.
I just wanted to say: I appreciate it. 

Is it really difficult to intercept DOM callbacks to cover all bases?
We are working on it. There are some concerns that it would cost too much performance-wise, but we will look into it.
The biggest difficulty is that callbacks that are registered by non-asynchronous primitives (like `requestAnimationFrame` that doesn't use Futures or Streams) would need to be tracked down. They would need to be wrapped to execute in their correct zone.
 
One of the consequences:, the effect won't be limited to dart VM - code generated by dart2js  would enable sane error processing in browsers, which is currently completely missing.

I also lilke the fact that Zone is a self-contained "small" concept. If any monadic mechanism ever emerges, it would be much simpler to implement on top of Zones. 

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 
Message has been deleted
Message has been deleted
Message has been deleted

William Hesse

unread,
Jul 1, 2013, 6:56:48 AM7/1/13
to General Dart Discussion
Mezoni's first example code is misleading, I think, because a computation-bound program running at 100% cpu cannot also be a responsive asynchronous program, responding quickly to user events, in a single-threaded system like Dart.  If a system should be responding to external events, and scheduling asynchronous IO calls efficiently, then long-running computations should be run in a different isolate, and return their results asynchronously.

If the entire program just does computations, as in his example, then it doesn't matter in what order the computations are run from the event queue, because there is no parallelism anyway.

Perhaps an "onIdle" pseudoevent could be added to the standalone Dart event loop, if people wanted to opportunistically run computations, when no other events are pending.



On Mon, Jul 1, 2013 at 11:34 AM, mezoni <andrew...@gmail.com> wrote:
>> Is Google developed Dart only for Dart Team or it developed it for world-wide community?

>> This must be a rhetorical question.
>> Regarding api design, etc....
>> Dart took the Future pattern from Java.  Streams appear in Java concurrent programming also so that may be a borrowed idea as well, although the term "stream" is fairly generic and seems to appear in all sorts of different environments.  Both no doubt are used identically elsewhere also.

This question is not about that what already implemented (but also include this).
This question about how goes this process and which results of thereof (also including productivity of Dart Team).
Breaking changes are the consequences of bad designing.
Breaking changes take a time for refactoring.

Conceptually Dart developed for community.
The community consists not only of the boys from the village.
They also programmers (often Java and C#).
But Dart in many cases goes as follows.
- Ignore community
- Make work as its own wish

Currently I am saying about Dart SDK written in Dart language.

There is no discussion about that:
- Why this done in this way but not in another
- Why you not ask community about how this would better implement

Or you want to say that Dart SDK infrastucture organized as the best project in the world?

Think about Synfony 1.X and Synfony 2.X.
Think about Zend Framework infrastucture.

In many case Dart SDK ideas goes from Java.
But Dart SDK organized not as Java SE.
Dart SDK organized sometimes as Synfony 1.X and sometimes as I cannot find similar analogy (plain PHP small framework?).

All internal implementation in Dart SDK are used private interfaces.

But at the same time, these interfaces describe the well-known technologies.
Why this private implementation based on private (well-known) interfaces?
Why this interfaces not public for best practice and re-use in Dart?
This is bad design.

This is closed to itself Dart SDK.
Dart SDK not ready for using as basis for future enhancement and alternative implementations.
This make Dart SDK are less universal becuase enhancement and alternatives not supported within this project infrastructure.

Rhetorical question in this case.
Who can implement this functionality for using with Dart SDK?
Only Dart Team! No alternatives, re-using or enhancement allowed.
Only Dart Team know forever which is the best way of using this product!

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 



--
William Hesse
Message has been deleted

Florian Loitsch

unread,
Jul 1, 2013, 2:39:36 PM7/1/13
to General Dart Discussion
On Mon, Jul 1, 2013 at 5:10 PM, mezoni <andrew...@gmail.com> wrote:
>> Mezoni's first example code is misleading,

I agree with you. Just tested (mix of sync and async actions). No difference.

>> Fwiw: we only expose a small sub-part of the zones-work so far (and even that is marked as experimental). Once the other core-libraries stabilize I want to spend more time on it.

Florian, good work.
But why zones? Why not
- UnitOfWork
- WorkItem
- AsyncWork
- AsyncContext
- TimeShare
- Batch
- Work
- TimeCycle
- TimeSlice
- TimeSpan
- TimeSlot
- Timetable
- Schedule
- AsyncFlow
- Flow
- TimeFlow
- TimeAction
- Force
- Extent
The only one that would fit, is "Extent". I don't have a strong preference on the name, yet. I don't think that "Extent" is much better, but I could be convinced otherwise. 
 
And why _Zone interface private?
So that we have more time to improve it before making it public. Once it is public we can't change it that easily anymore. We already expose parts of it, but it goes through a very small interface which has "Experimental" in its name. Since the function is furthermore static it will be easy to adapt code that already starts using it. 

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 



--

Alex Tatumizer

unread,
Jul 1, 2013, 5:18:38 PM7/1/13
to mi...@dartlang.org
I think Zone is a very good and fitting word for the concept - it's a part of appeal of the whole idea (words, including the phonetics, are important - we are talking about the language after all). I fail to see how "extent" or anything else from the list could beat it. I liked it the minute I saw it.
(In English, "Zone" doesn't have negative connotations like in Russian(*))

(*) Used colloquially, means  prisoner's camp or penitentiary institution in general. This is probably the most common use case. Other meanings are approximately like in English.
So what? Whatever async function runs in a Zone, becomes its prisoner :-)
  
Message has been deleted
Message has been deleted

Seth Ladd

unread,
Jul 2, 2013, 12:15:57 PM7/2/13
to General Dart Discussion
Hi Alex,

It wasn't breaking news or a bigger announcement because it's an experimental feature. When the library engineers are more confident, we will be happy to document it more and tell more people about it.

We, too, are happy it exists. :)  But we're waiting until it gets more baked before we make it more broadly known.

Thanks,
Seth


--
Message has been deleted
Message has been deleted

Kai Sellgren

unread,
Jul 3, 2013, 6:51:47 AM7/3/13
to mi...@dartlang.org
I completely forgot the new dart:async features. They're so hidden. Now that I've upgraded our server-side code to the latest SDK, I will give them a shot.

I've noticed that when using isolate exception handlers, you may easily leak resources. For that reason alone, I have an exception handler which logs the error to a log file and sends it down the web socket connection to the browser's console for me to see and then restarts the server.

But the most important thing to do is to ensure there's someone handling the error. I always pipe futures so that errors go down the chain. And if there's something that I don't want to chain, I manually handle the problems.

This has tremendously stabilized our server code. It's unfortunate though to see lots of code that does not do this, and causes your server to crash if the 3rd party code throws. This is why I believe that simply writing good code is not enough.

Paul Brauner

unread,
Jul 3, 2013, 7:03:43 AM7/3/13
to General Dart Discussion



On Fri, Jun 28, 2013 at 7:59 AM, Tom Yeh <tom....@gmail.com> wrote:
It can be protected at the container, like we did In Rikulo Stream. By assuming all handlers being asynchronous, one can catch all exceptions (except compile errors) at the container (or the very first general handler) and then forward the error, if any, into a (Java-like) general error handling mechanism, such as Stream's error handling.

+1 I'm using rikulo stream for one of my server and I sometimes forget to catch certain errors but I'm protected by the framework.

Paul

 


On Friday, June 28, 2013 1:03:03 AM UTC+8, Seth Ladd wrote:
Hi server-side Dart developers and library authors,

I'm writing a lot of server-side Dart code these days, and I keep running into exceptions that crash my server because they are unhandled. What is a good pattern to follow so that I ensure all exceptions are handled and don't take down the running process?

There's a LOT of async code going on (HTTP server, Postgress, Google+ API, and more). I feel like I'm chaining correctly and putting in a lot of onError and whenComplete etc but I still run into "unhandled exceptions". Even if I do an awesome job (or maybe I'm doing a really poor job?) of putting in all the error handlers, I still use a lot of code that I didn't write which may throw exceptions from deep within async chains.

What I'm looking for is:

1) A global, for-real way to handle all unhandled exceptions. So nothing slips through and takes down the server.

2) A way to get the full stack trace of where the exceptions originally occurred (no matter how asyncy), so I can do something about it.

I see two APIs that might help me, but marked as Experimental: runZonedExperimental and getAttachedStackTrace. So I feel like it's a know problem, but one we don't have a solution for (yet)

Are there good patterns for this? What have others done?

Thanks!
Seth

Message has been deleted

Iván Zaera Avellón

unread,
Jul 3, 2013, 7:18:28 AM7/3/13
to misc
> +1 I'm using rikulo stream for one of my server and I sometimes forget to catch certain errors but I'm protected by the framework.

I'm using it too, but that is only true if you don't fail to pipe all Futures which is, to say the least, difficult.

We definitely need something in the language to handle uncatched errors. Specially those that are inside 3rd party libs you cannot modify. Something like a global try/catch but for async code.

As far as I have understood that is supposed to be provided by Zone's. Am I right? I mean: will we be able to catch errors from unpiped futures using a zone in an arbitrary place of the application code or is it for anything different? I have had no time to look at them yet :-(...



2013/7/3 Paul Brauner <po...@google.com>

Florian Loitsch

unread,
Jul 3, 2013, 8:52:20 AM7/3/13
to General Dart Discussion
On Wed, Jul 3, 2013 at 1:18 PM, Iván Zaera Avellón <iza...@gmail.com> wrote:
> +1 I'm using rikulo stream for one of my server and I sometimes forget to catch certain errors but I'm protected by the framework.

I'm using it too, but that is only true if you don't fail to pipe all Futures which is, to say the least, difficult.

We definitely need something in the language to handle uncatched errors. Specially those that are inside 3rd party libs you cannot modify. Something like a global try/catch but for async code.

As far as I have understood that is supposed to be provided by Zone's. Am I right? I mean: will we be able to catch errors from unpiped futures using a zone in an arbitrary place of the application code or is it for anything different? I have had no time to look at them yet :-(...
Yes. runZonedExperimental will catch these futures. As long as they don't come from a callback of the DOM (or if we missed another asynchronous primitive). If we missed a place we would like to know. 



--

Iván Zaera Avellón

unread,
Jul 3, 2013, 9:00:40 AM7/3/13
to misc
(or if we missed another asynchronous primitive). If we missed a place we would like to know. 

And in the server? The same?

Regards,
Ivan


2013/7/3 Florian Loitsch <floi...@google.com>

Florian Loitsch

unread,
Jul 3, 2013, 10:56:18 AM7/3/13
to General Dart Discussion
On Wed, Jul 3, 2013 at 3:00 PM, Iván Zaera Avellón <iza...@gmail.com> wrote:
(or if we missed another asynchronous primitive). If we missed a place we would like to know. 

And in the server? The same?
Zones are both client and server. 

Iván Zaera Avellón

unread,
Jul 3, 2013, 12:51:25 PM7/3/13
to misc

Ok.

My question was regarding the "forgotten async primitives" (whatever they are ;-)). I was assuming these are different in client and server.

For instance it looks like dart:io may have its own async primitives and it only works in server. But never mind I was just supposing things...

I will give the zones a try and if I see something strange will let the list know.

Thx.

Florian Loitsch

unread,
Jul 3, 2013, 1:03:14 PM7/3/13
to General Dart Discussion
On Wed, Jul 3, 2013 at 6:51 PM, Iván Zaera Avellón <iza...@gmail.com> wrote:

Ok.

My question was regarding the "forgotten async primitives" (whatever they are ;-)). I was assuming these are different in client and server.

Well I wouldn't know which ones we forgot. Otherwise I would have fixed them ;)
 

For instance it looks like dart:io may have its own async primitives and it only works in server. But never mind I was just supposing things...

They should use the standard async primitives and thus work. To my knowledge there are no server primitives *except* isolate communications that don't work with zones.
 

I will give the zones a try and if I see something strange will let the list know.

Sounds good. thanks. 

Iván Zaera Avellón

unread,
Jul 5, 2013, 5:12:31 AM7/5/13
to misc
Hi again:

Tried to run the following code:

<<<<
void main() {
  runZonedExperimental( () {
    Socket.connect("localhost", 44444).then( (Socket s) {
      print("_socket_: $s");
    });
  }, onError: (err) => print("_ops_: $err"), onDone: () => print("_done_") );
}
>>>>

and nothing is caught by the zone. I get this in the console:

<<<<
Uncaught Error: SocketException: Connection failed
Unhandled exception:
SocketException: Connection failed
#0      _DefaultZone.handleUncaughtError.<anonymous closure> (dart:async/zone.dart:148:7)
#1      _asyncRunCallback._asyncRunCallback (dart:async/event_loop.dart:9:15)
#2      _asyncRunCallback._asyncRunCallback (dart:async/event_loop.dart:13:7)
#3      _createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:8:13)
#4      _Timer._createTimerHandler._handleTimeout (timer_impl.dart:91:28)
#5      _Timer._createTimerHandler._handleTimeout (timer_impl.dart:99:7)
#6      _Timer._createTimerHandler.<anonymous closure> (timer_impl.dart:107:23)
#7      _ReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:81:92)
>>>>

Am I doing something wrong? Or is it a forgotten primitive ;-)?

BTW: Would it make sense to return a Future from runZonedExperimental() instead of passing two parameters, onError and onDone?That way syntax would be prettier. Only that I'm not sure if it can be done because the returned Future could be chained and/or combined with other standard Futures and maybe that would interfere with the zonification.

Cheers,
Ivan





Florian Loitsch

unread,
Jul 5, 2013, 7:24:44 AM7/5/13
to General Dart Discussion
On Fri, Jul 5, 2013 at 11:12 AM, Iván Zaera Avellón <iza...@gmail.com> wrote:
Hi again:

Tried to run the following code:

<<<<
void main() {
  runZonedExperimental( () {
    Socket.connect("localhost", 44444).then( (Socket s) {
      print("_socket_: $s");
    });
  }, onError: (err) => print("_ops_: $err"), onDone: () => print("_done_") );
}
>>>>

and nothing is caught by the zone. I get this in the console:

<<<<
Uncaught Error: SocketException: Connection failed
Unhandled exception:
SocketException: Connection failed
#0      _DefaultZone.handleUncaughtError.<anonymous closure> (dart:async/zone.dart:148:7)
#1      _asyncRunCallback._asyncRunCallback (dart:async/event_loop.dart:9:15)
#2      _asyncRunCallback._asyncRunCallback (dart:async/event_loop.dart:13:7)
#3      _createTimer.<anonymous closure> (dart:async-patch/timer_patch.dart:8:13)
#4      _Timer._createTimerHandler._handleTimeout (timer_impl.dart:91:28)
#5      _Timer._createTimerHandler._handleTimeout (timer_impl.dart:99:7)
#6      _Timer._createTimerHandler.<anonymous closure> (timer_impl.dart:107:23)
#7      _ReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:81:92)
>>>>

Am I doing something wrong? Or is it a forgotten primitive ;-)?
Argh. Didn't see that coming. (As you can see, I actually never tested IO).
It's even worse that you think: a catchError on the Socket future won't even receive the error now. The reason is, that errors never cross zones (at least if the zone handles errors). Callbacks from the system go through isolate-communication (that's why you see the _ReceivePortImpl in the stacktrace), and since these don't respect zones yet they execute in a different zone.
I will try to fix this asap. Thanks.
 

BTW: Would it make sense to return a Future from runZonedExperimental() instead of passing two parameters, onError and onDone?That way syntax would be prettier. Only that I'm not sure if it can be done because the returned Future could be chained and/or combined with other standard Futures and maybe that would interfere with the zonification.

Iván Zaera Avellón

unread,
Jul 5, 2013, 7:37:49 AM7/5/13
to misc
A Stream instead of a Future? :-o

Does that mean that we can get more than one error from a zone?


2013/7/5 Florian Loitsch <floi...@google.com>

Florian Loitsch

unread,
Jul 5, 2013, 9:03:10 AM7/5/13
to General Dart Discussion
On Fri, Jul 5, 2013 at 1:37 PM, Iván Zaera Avellón <iza...@gmail.com> wrote:
A Stream instead of a Future? :-o

Does that mean that we can get more than one error from a zone?
Yes. Every asynchronous error. Otherwise we would need to terminate pending callbacks, ...
It's something that we could do (and that I had implemented at some point), but it doesn't compose well.

Florian Loitsch

unread,
Jul 5, 2013, 12:55:19 PM7/5/13
to General Dart Discussion

Although errors are caught now, the zone doesn't see when it is done. I'm not sure, yet, why this is the case.
The done handler is, in general, not really useful. There are too many ways that a Future-handler is not executed. If the handler triggers it is a guarantee that no other callback will occur in the zone, but a zone can already be dead but simply not know it, because there is some future that wasn't triggered. This could even be, because another zone intercepted an error message on a future-chain. :(

Alex Tatumizer

unread,
Jul 5, 2013, 1:33:30 PM7/5/13
to mi...@dartlang.org
@Florian: how do you think, won't it be a good idea to "cut all links" after a single error in the zone: just NOT CALL any "then" handlers after other futures complete? (So the zone essentially disintegrates)
(This is not necessarily related to the question at hand though).

Florian Loitsch

unread,
Jul 5, 2013, 2:15:32 PM7/5/13
to General Dart Discussion
On Fri, Jul 5, 2013 at 7:33 PM, Alex Tatumizer <tatu...@gmail.com> wrote:
@Florian: how do you think, won't it be a good idea to "cut all links" after a single error in the zone: just NOT CALL any "then" handlers after other futures complete? (So the zone essentially disintegrates)
(This is not necessarily related to the question at hand though).

Say you have a library that uses: future.whenComplete(() => releaseResources);
If another error in the same zone marks your zone as dead you have a resource leak.

So basically: stopping every callback in a zone the moment there was an error only works if every asynchronous callback is programmed against this pattern. Once the Zone class is exposed it should be possible to implement it, but you should be certain that all your nested callbacks are aware of it.

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 

Alex Tatumizer

unread,
Jul 5, 2013, 2:41:55 PM7/5/13
to mi...@dartlang.org
If error occurs, situation may become so flaky and unpredictable that your "release" future will be never called anyway. Some Zone-wide mechanism of "finally" is needed: instead of "then" another handler should be called, no?
(Missing concept :-)

Florian Loitsch

unread,
Jul 5, 2013, 2:56:22 PM7/5/13
to General Dart Discussion
On Fri, Jul 5, 2013 at 8:41 PM, Alex Tatumizer <tatu...@gmail.com> wrote:
If error occurs, situation may become so flaky and unpredictable that your "release" future will be never called anyway. Some Zone-wide mechanism of "finally" is needed: instead of "then" another handler should be called, no?
That's only true if you consider callbacks that are dependent.
asyncTry(() {
  new Future(someLengthyProcess);
  new Future(someOtherLengthyProcess);
}, catchError: (e) ...);

If `someLengthProcess` throws (asynchronous or not), but someOtherLengthyProcess is still in a sane state it should be able to rely on its `whenComplete`, `then` or `catchError` to be called.

If we moved completely towards `asyncTry` you could add `finallyDo` as named argument to `asyncTry` and guarantee only that these closures are invoked when there is an error.
This is, what I had already implemented, but it goes against the current asynchronous model, and we dropped it again.

(Missing concept :-)

--
For other discussions, see https://groups.google.com/a/dartlang.org/
 
For HOWTO questions, visit http://stackoverflow.com/tags/dart
 
To file a bug report or feature request, go to http://www.dartbug.com/new
 
 

Alex Tatumizer

unread,
Jul 5, 2013, 4:15:24 PM7/5/13
to mi...@dartlang.org
I actually meant different implementation of the same idea.
Actually, your "zone" more or less implements the logic of error processing as I proposed in circuit writeup.
Except that in circuit, the behavior was supposed to be a bit less straightforward.
Let's forget about circuit and talk about Zone to avoid confusion.

suppose in Zone, there's function "stop"  (as a method of Zone itself!).
zone.stop(value); // "value" can be error or whatever - whoever calls stop, knows what it is

Note that "stop" means termination (zone doesn't care why someone called "stop" - because of error, or just normal termination)..

3 things are done on stop by Zone:
1) Zone disintegrates (stops propagating to "then" handlers)

2) "onstop" handler for Zone is called. It is similar to "finally". [ I didn't mean to create a lexically scoped block as in your example asyncTry(), because it certainly doesn't fit in async concept.]. It's just a callback:
zone.onstop((value)=> doSomething);

3) If any pending futures are still there, and have special "onstop" hanlder, these handlers can be called, too.

This gives some flexibility on how to implement cleanup.

This feature can be added at any time. We can revisit it when you complete your current design.
//Alex

Alex Tatumizer

unread,
Jul 5, 2013, 7:04:36 PM7/5/13
to mi...@dartlang.org
@Florian: BTW, did you consider the option to make Zone look like Future for outside world?
With its own completer, errors, then(), etc.?
With such design, things become truly composable.

Streams do not fit in this concept directly though. One needs "special" zones which for outside world look like they produce streams.
That's what I tried to achieve in circuit design. 
Message has been deleted

Alex Tatumizer

unread,
Jul 7, 2013, 12:53:10 PM7/7/13
to mi...@dartlang.org
On second thought, retrofitting Zone with features of Future doesn't look like a good idea.
The very word "Zone" doesn't imply that kind of thing. Zone is a place where something is going on, not a "going-on" itself.
We can define a circuit running in a zone - then the circuit naturally becomes a "modular Future".

I don't know whether you have plans to explore circuit concept though, so I can't say much at that point.
If not, I can try to do it myself (eventually - don't hold your breath :-), and Zone will really help - implementing correct collection and forwarding of errors from large surface area is a big deal!

If someone is interested, one note about relationship between Futures and Streams.
Intuitively, it's clear that these two concepts are related - both are major building blocks for async programming.
However, I was not able to clearly formulate the connection between them directly. I needed two more words for this: token and pipe.
Token gets a Future as input and produces value as output.
Pipe gets a stream of Futures as input and produces stream of values as output.
So token becomes just a trivial degenerate case of Pipe.
(I was thinking about renaming Token into Latch to better emphasize this connection).

It may look like we need too many "words" to cover async programming. But if you think about it, it's not surprising.
We need to find asynchronous equivalents to all constructs of synchronous programming: sequential execution, loops, ifs, try-catch-finally, subroutine, etc.
(plus parallel execution with a bunch of new problems). I even composed a table of correspondence, but omitted it from dart write-up to keep it short.
Unfortunately, it's still not short enough to be read within 1 minute, so there's very small chance anyone would read at at all. To be sure, there's nothing earth-shattering there, it's ok if someone just develops same or similar idea independently.



Reply all
Reply to author
Forward
0 new messages