{"action":"created","issue":{"url":"https://api.github.com/repos/daokoder/dao/issues/363","labels_url":"https://api.github.com/repos/daokoder/dao/issues/363/labels{/name}","comments_url":"https://api.github.com/repos/daokoder/dao/issues/363/comments","events_url":"https://api.github.com/repos/daokoder/dao/issues/363/events","html_url":"https://github.com/daokoder/dao/issues/363","id":56925927,"number":363,"title":"Failure isolation in tasklets","user":{"login":"Night-walker","id":5074460,"avatar_url":"https://avatars.githubusercontent.com/u/5074460?v=3","gravatar_id":"","url":"https://api.github.com/users/Night-walker","html_url":"https://github.com/Night-walker","followers_url":"https://api.github.com/users/Night-walker/followers","following_url":"https://api.github.com/users/Night-walker/following{/other_user}","gists_url":"https://api.github.com/users/Night-walker/gists{/gist_id}","starred_url":"https://api.github.com/users/Night-walker/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Night-walker/subscriptions","organizations_url":"https://api.github.com/users/Night-walker/orgs","repos_url":"https://api.github.com/users/Night-walker/repos","events_url":"https://api.github.com/users/Night-walker/events{/privacy}","received_events_url":"https://api.github.com/users/Night-walker/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-02-07T21:02:18Z","updated_at":"2015-02-07T21:24:04Z","closed_at":null,"body":"An unhandled exception within a task should not propagate to other tasks. It should be isolated in the corresponding future value, ensuring that the program won't ruin like a card house when a single card is pulled out. That is, future value should be viewed not as a guaranteed value, but as a possible one.\r\n\r\nFailure isolation is necessary for a robust, failure-resistant concurrency implementation. That is what you can see in Erlang and Rust. Not in Go, right -- but there panics are not 'ordinary' exceptions. Not in the sense of Dao exception handling -- panicking in Go is a last resort, a red button for self-destruction when all the defenders have fallen and the foes are ramming the last door. Even though Dao adopted the revised defer-panic-recover concept, its use spans over a lot of trivial cases which can often be resolved without bloodshed.\r\n\r\nSo, it's generally good if exception is not allowed to break out of its task and sink the mighty Titanic because a negligent sailor forgot to close the valve. If you really want to end the miserable life of your program in a single motion, there is an old but still practiced approach of leaving a death note and committing `sys.exit()`.\r\n\r\nBut isolating a failure doesn't mean it should be allowed to be ignored as if nothing happened. If the task failed and its future value was not examined during its lifetime, the destructor of this future value should throw a warning signalling the user that a failure was overlooked.\r\n\r\nThe described change could be incorporated into the interace either by extending `Future::value()` result with possible `Error` (or `list<Error>`), or perhaps by defining its result as `@T|none` and adding a separate method for fetching possible error(s). The latter variant allows to benefit from `@T|none => @T` auto-casting, keeping the code simple when you are confident that no error can occur.\r\n\r\nThat's all."},"comment":{"url":"https://api.github.com/repos/daokoder/dao/issues/comments/73383837","html_url":"https://github.com/daokoder/dao/issues/363#issuecomment-73383837","issue_url":"https://api.github.com/repos/daokoder/dao/issues/363","id":73383837,"user":{"login":"dumblob","id":2451044,"avatar_url":"https://avatars.githubusercontent.com/u/2451044?v=3","gravatar_id":"","url":"https://api.github.com/users/dumblob","html_url":"https://github.com/dumblob","followers_url":"https://api.github.com/users/dumblob/followers","following_url":"https://api.github.com/users/dumblob/following{/other_user}","gists_url":"https://api.github.com/users/dumblob/gists{/gist_id}","starred_url":"https://api.github.com/users/dumblob/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dumblob/subscriptions","organizations_url":"https://api.github.com/users/dumblob/orgs","repos_url":"https://api.github.com/users/dumblob/repos","events_url":"https://api.github.com/users/dumblob/events{/privacy}","received_events_url":"https://api.github.com/users/dumblob/received_events","type":"User","site_admin":false},"created_at":"2015-02-07T21:24:04Z","updated_at":"2015-02-07T21:24:04Z","body":"Hm, this tricky question is not easy to decide immediately for me as the proposed approach would require *always* to check the returned future value for errors, which is quite a contrary to what exceptions in Dao are good for. I'll try to find some data foundation about which approach seems better. Or maybe a combination - \"internally\" catch exception to the future value (while stopping the execution of the particular thread) and when reading the future value, the caught exception would be \"rethrown\", but this time in the collecting/main thread.\r\n\r\n> or perhaps by defining its result as `@T|none` and adding a separate method for fetching possible error(s).\r\n\r\nThis would disallow to return `@T|none` from the routine/method itself (where `none` might be a legitimate/expected result), so I'd rather avoid this approach."}}