{"action":"created","comment":{"url":"https://api.github.com/repos/codurance/site/pulls/comments/62031637","id":62031637,"diff_hunk":"@@ -0,0 +1,82 @@\n+---\n+layout: post\n+name: Akka-basics\n+title: 'Akka basics'\n+date: 2016-04-30 00:20:00 +00:00\n+author: Felipe Fernández\n+image:\n+    src: /assets/img/custom/blog/akka.jpg\n+    attribution:\n+      text: Akka_20120331 by Helena Whitlock, SGU\n+      href: https://www.flickr.com/photos/geologicalsurveyofsweden/8703286181\n+tags:\n+- akka\n+- OOP\n+- functional programming\n+\n+---\n+\n+As [the previous post](http://codurance.com/2016/04/28/async-systems-with-sync-clients) explained our system is based on Akka. Before going into more detail about our solution, I'd like to explain what is Akka about and why is so awesome.\n+\n+Akka is a toolkit and not a framework, you can simply use the bits that you need for your service. In this series we'll focus on the core features and we won't go through Akka Stream, Akka-Http or Akka Cluster (since they're out of scope, not because they're not fantastic).\n+\n+Akka provides a different abstraction to deal with concurrency, paralellism and fault-tolerance. That abstraction is called Actor Model. If you have experience with old Java ecosystem you will know how hard is writing safe and correct multithreaded code. Providing human-friendly abstractions like Actors it's a revolution similar to what Java did with memory management.\n+\n+## Actors all the way\n+\n+Threads are an expensive resource, hence we need to use them judiciously. Blocking threads while we're waiting for some IO operation to respond is really inefficient. Actors use threads in a different way, as a result of which they're pretty lightweight ([several million actors per GB of heap memory](http://doc.akka.io/docs/akka/2.4.4/intro/what-is-akka.html))\n+\n+Actors mix Object Oriented and Functional Programming principles. OOP is basically about messages as Alan Kay [stated](http://lists.squeakfoundation.org/pipermail/squeak-dev/1998-October/017019.html)\n+\n+> I'm sorry that I long ago coined the term \"objects\" for this topic because it gets many people to focus on the lesser idea. The big idea is \"messaging\".\n+\n+An actor exchanges immutable messages and keeps their own encapsulated state: every interaction needs to be done through messages.\n+\n+## Fault tolerance\n+\n+There is not a clear and shared error model in Java, and you can realise that after working in a couple of projects. The origin of that is a confusing abstraction called Exception and its subtypes Checked and Unchecked Exceptions. The only real difference is that checked expections force us to deal with the issue in the direct caller, except for that they don't hint at the strategy that we should apply.\n+\n+I strongly recomment [this](http://joeduffyblog.com/2016/02/07/the-error-model/) post about it. A powerful idea in the post is that bugs aren't recoverable errors. This quote is contained on that post, [original source](https://wiki.haskell.org/Error_vs._Exception):\n+\n+> I was involved in the development of a library that was written in C++. One of the developers told me that the developers are divided into the ones who like exceptions and the other ones who prefer return codes. As it seem to me, the friends of return codes won. However, I got the impression that they debated the wrong point: Exceptions and return codes are equally expressive, they should however not be used to describe errors. Actually the return codes contained definitions like ARRAY_INDEX_OUT_OF_RANGE. But I wondered: How shall my function react, when it gets this return code from a subroutine? Shall it send a mail to its programmer? It could return this code to its caller in turn, but it will also not know how to cope with it. Even worse, since I cannot make assumptions about the implementation of a function, I have to expect an ARRAY_INDEX_OUT_OF_RANGE from every subroutine. My conclusion is that ARRAY_INDEX_OUT_OF_RANGE is a (programming) error. It cannot be handled or fixed at runtime, it can only be fixed by its developer. Thus there should be no according return code, but instead there should be asserts.\n+\n+Akka provides a great way for dealing with failures/errors based on these tenets:\n+\n+* Single responsibility principle. Failure management is delegated to supervisors, creating focused business actors. We agreed some time ago that lifecycle management, e.g. object creation, should be moved to factories, therefore an object is not responsible for creating itself. Resuming or restarting an object, after some failure happened, is part of that lifecycle management and Akka enforces you to move that responsibility to supervisors.\n+\n+* Default recovery strategies. It's important to understand which are our options after the system is under some failure condition. Is DB temporarily down? Has some input, in combination with the existing data, created an undesired state? Is that a bug? Do we need to abandon that particular request or that part of the system is messed up until some patch is applied? Those questions will determine our response to that incident, and Akka provides some [built-in strategies](http://doc.akka.io/docs/akka/2.4.4/scala/fault-tolerance.html#fault-tolerance-scala).\n+\n+```\n+override val supervisorStrategy =\n+  OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {\n+    case _: ArithmeticException      => Resume\n+    case _: NullPointerException     => Restart\n+    case _: IllegalArgumentException => Stop\n+    case _: Exception                => Escalate\n+  }\n+```\n+\n+* Failure as first citizen. Some libraries or ecosystems hide failures through obscure APIs. Akka is usually deployed in distributed environments, therefore using unreliable resources like networks. That forces us to bring failure to the front page. Even in 'safer' environments as monoliths, failures are all around, so using toolkits like Akka is critical to create reliable and robust software.\n+\n+## Concurrency and parallelism\n+\n+With Akka we're not going to deal directly with threads, they're hidden under an abstraction layer. The backbone of an Akka app is the [Actor System](http://doc.akka.io/api/akka/2.0/akka/actor/ActorSystem.html):\n+\n+> An actor system is a hierarchical group of actors which share common configuration, e.g. dispatchers, deployments, remote capabilities and addresses. It is also the entry point for creating or looking up actors.\n+\n+A Dispatcher is also an Execution Context, so in the end is where the thread pool is located. Let's assume that your app uses a single dispatcher with 4 threads allocated. As you can see threads are a scarce resource, if we do blocking IO or heavy CPU work in some of the actors we'll use exclusively one of the threads, and you can see how quickly your service will run out of threads.","path":"_posts/2016-04-30-akka-basics.md","position":67,"original_position":67,"commit_id":"15f248486231b6e11fbcea5a43cbef30172a09e4","original_commit_id":"15f248486231b6e11fbcea5a43cbef30172a09e4","user":{"login":"neomatrix369","id":1570917,"avatar_url":"https://avatars.githubusercontent.com/u/1570917?v=3","gravatar_id":"","url":"https://api.github.com/users/neomatrix369","html_url":"https://github.com/neomatrix369","followers_url":"https://api.github.com/users/neomatrix369/followers","following_url":"https://api.github.com/users/neomatrix369/following{/other_user}","gists_url":"https://api.github.com/users/neomatrix369/gists{/gist_id}","starred_url":"https://api.github.com/users/neomatrix369/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/neomatrix369/subscriptions","organizations_url":"https://api.github.com/users/neomatrix369/orgs","repos_url":"https://api.github.com/users/neomatrix369/repos","events_url":"https://api.github.com/users/neomatrix369/events{/privacy}","received_events_url":"https://api.github.com/users/neomatrix369/received_events","type":"User","site_admin":false},"body":"Are you trying to say \"so in the end it is where the thread pool is located\" ?","created_at":"2016-05-04T12:44:21Z","updated_at":"2016-05-04T12:44:21Z","html_url":"https://github.com/codurance/site/pull/161#discussion_r62031637","pull_request_url":"https://api.github.com/repos/codurance/site/pulls/161","_links":{"self":{"href":"https://api.github.com/repos/codurance/site/pulls/comments/62031637"},"html":{"href":"https://github.com/codurance/site/pull/161#discussion_r62031637"},"pull_request":{"href":"https://api.github.com/repos/codurance/site/pulls/161"}}},"pull_request":{"url":"https://api.github.com/repos/codurance/site/pulls/161","id":68710754,"html_url":"https://github.com/codurance/site/pull/161","diff_url":"https://github.com/codurance/site/pull/161.diff","patch_url":"https://github.com/codurance/site/pull/161.patch","issue_url":"https://api.github.com/repos/codurance/site/issues/161","number":161,"state":"open","locked":false,"title":"Akka basics.","user":{"login":"felipefzdz","id":369379,"avatar_url":"https://avatars.githubusercontent.com/u/369379?v=3","gravatar_id":"","url":"https://api.github.com/users/felipefzdz","html_url":"https://github.com/felipefzdz","followers_url":"https://api.github.com/users/felipefzdz/followers","following_url":"https://api.github.com/users/felipefzdz/following{/other_user}","gists_url":"https://api.github.com/users/felipefzdz/gists{/gist_id}","starred_url":"https://api.github.com/users/felipefzdz/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/felipefzdz/subscriptions","organizations_url":"https://api.github.com/users/felipefzdz/orgs","repos_url":"https://api.github.com/users/felipefzdz/repos","events_url":"https://api.github.com/users/felipefzdz/events{/privacy}","received_events_url":"https://api.github.com/users/felipefzdz/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-05-03T14:04:44Z","updated_at":"2016-05-04T12:44:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ecd1178087861cc3b9ff1c453aae927312f3f929","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/codurance/site/pulls/161/commits","review_comments_url":"https://api.github.com/repos/codurance/site/pulls/161/comments","review_comment_url":"https://api.github.com/repos/codurance/site/pulls/comments{/number}","comments_url":"https://api.github.com/repos/codurance/site/issues/161/comments","statuses_url":"https://api.github.com/repos/codurance/site/statuses/15f248486231b6e11fbcea5a43cbef30172a09e4","head":{"label":"codurance:akka-basics","ref":"akka-basics","sha":"15f248486231b6e11fbcea5a43cbef30172a09e4","user":{"login":"codurance","id":5751452,"avatar_url":"https://avatars.githubusercontent.com/u/5751452?v=3","gravatar_id":"","url":"https://api.github.com/users/codurance","html_url":"https://github.com/codurance","followers_url":"https://api.github.com/users/codurance/followers","following_url":"https://api.github.com/users/codurance/following{/other_user}","gists_url":"https://api.github.com/users/codurance/gists{/gist_id}","starred_url":"https://api.github.com/users/codurance/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codurance/subscriptions","organizations_url":"https://api.github.com/users/codurance/orgs","repos_url":"https://api.github.com/users/codurance/repos","events_url":"https://api.github.com/users/codurance/events{/privacy}","received_events_url":"https://api.github.com/users/codurance/received_events","type":"Organization","site_admin":false},"repo":{"id":38424930,"name":"site","full_name":"codurance/site","owner":{"login":"codurance","id":5751452,"avatar_url":"https://avatars.githubusercontent.com/u/5751452?v=3","gravatar_id":"","url":"https://api.github.com/users/codurance","html_url":"https://github.com/codurance","followers_url":"https://api.github.com/users/codurance/followers","following_url":"https://api.github.com/users/codurance/following{/other_user}","gists_url":"https://api.github.com/users/codurance/gists{/gist_id}","starred_url":"https://api.github.com/users/codurance/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codurance/subscriptions","organizations_url":"https://api.github.com/users/codurance/orgs","repos_url":"https://api.github.com/users/codurance/repos","events_url":"https://api.github.com/users/codurance/events{/privacy}","received_events_url":"https://api.github.com/users/codurance/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/codurance/site","description":"","fork":false,"url":"https://api.github.com/repos/codurance/site","forks_url":"https://api.github.com/repos/codurance/site/forks","keys_url":"https://api.github.com/repos/codurance/site/keys{/key_id}","collaborators_url":"https://api.github.com/repos/codurance/site/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/codurance/site/teams","hooks_url":"https://api.github.com/repos/codurance/site/hooks","issue_events_url":"https://api.github.com/repos/codurance/site/issues/events{/number}","events_url":"https://api.github.com/repos/codurance/site/events","assignees_url":"https://api.github.com/repos/codurance/site/assignees{/user}","branches_url":"https://api.github.com/repos/codurance/site/branches{/branch}","tags_url":"https://api.github.com/repos/codurance/site/tags","blobs_url":"https://api.github.com/repos/codurance/site/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/codurance/site/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/codurance/site/git/refs{/sha}","trees_url":"https://api.github.com/repos/codurance/site/git/trees{/sha}","statuses_url":"https://api.github.com/repos/codurance/site/statuses/{sha}","languages_url":"https://api.github.com/repos/codurance/site/languages","stargazers_url":"https://api.github.com/repos/codurance/site/stargazers","contributors_url":"https://api.github.com/repos/codurance/site/contributors","subscribers_url":"https://api.github.com/repos/codurance/site/subscribers","subscription_url":"https://api.github.com/repos/codurance/site/subscription","commits_url":"https://api.github.com/repos/codurance/site/commits{/sha}","git_commits_url":"https://api.github.com/repos/codurance/site/git/commits{/sha}","comments_url":"https://api.github.com/repos/codurance/site/comments{/number}","issue_comment_url":"https://api.github.com/repos/codurance/site/issues/comments{/number}","contents_url":"https://api.github.com/repos/codurance/site/contents/{+path}","compare_url":"https://api.github.com/repos/codurance/site/compare/{base}...{head}","merges_url":"https://api.github.com/repos/codurance/site/merges","archive_url":"https://api.github.com/repos/codurance/site/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/codurance/site/downloads","issues_url":"https://api.github.com/repos/codurance/site/issues{/number}","pulls_url":"https://api.github.com/repos/codurance/site/pulls{/number}","milestones_url":"https://api.github.com/repos/codurance/site/milestones{/number}","notifications_url":"https://api.github.com/repos/codurance/site/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/codurance/site/labels{/name}","releases_url":"https://api.github.com/repos/codurance/site/releases{/id}","deployments_url":"https://api.github.com/repos/codurance/site/deployments","created_at":"2015-07-02T09:54:02Z","updated_at":"2016-03-14T09:39:20Z","pushed_at":"2016-05-03T16:33:41Z","git_url":"git://github.com/codurance/site.git","ssh_url":"git@github.com:codurance/site.git","clone_url":"https://github.com/codurance/site.git","svn_url":"https://github.com/codurance/site","homepage":null,"size":160243,"stargazers_count":1,"watchers_count":1,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2,"mirror_url":null,"open_issues_count":2,"forks":2,"open_issues":2,"watchers":1,"default_branch":"master"}},"base":{"label":"codurance:master","ref":"master","sha":"57eb422f8f12f9833146b938ddaf6c54eb76c4d2","user":{"login":"codurance","id":5751452,"avatar_url":"https://avatars.githubusercontent.com/u/5751452?v=3","gravatar_id":"","url":"https://api.github.com/users/codurance","html_url":"https://github.com/codurance","followers_url":"https://api.github.com/users/codurance/followers","following_url":"https://api.github.com/users/codurance/following{/other_user}","gists_url":"https://api.github.com/users/codurance/gists{/gist_id}","starred_url":"https://api.github.com/users/codurance/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codurance/subscriptions","organizations_url":"https://api.github.com/users/codurance/orgs","repos_url":"https://api.github.com/users/codurance/repos","events_url":"https://api.github.com/users/codurance/events{/privacy}","received_events_url":"https://api.github.com/users/codurance/received_events","type":"Organization","site_admin":false},"repo":{"id":38424930,"name":"site","full_name":"codurance/site","owner":{"login":"codurance","id":5751452,"avatar_url":"https://avatars.githubusercontent.com/u/5751452?v=3","gravatar_id":"","url":"https://api.github.com/users/codurance","html_url":"https://github.com/codurance","followers_url":"https://api.github.com/users/codurance/followers","following_url":"https://api.github.com/users/codurance/following{/other_user}","gists_url":"https://api.github.com/users/codurance/gists{/gist_id}","starred_url":"https://api.github.com/users/codurance/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codurance/subscriptions","organizations_url":"https://api.github.com/users/codurance/orgs","repos_url":"https://api.github.com/users/codurance/repos","events_url":"https://api.github.com/users/codurance/events{/privacy}","received_events_url":"https://api.github.com/users/codurance/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/codurance/site","description":"","fork":false,"url":"https://api.github.com/repos/codurance/site","forks_url":"https://api.github.com/repos/codurance/site/forks","keys_url":"https://api.github.com/repos/codurance/site/keys{/key_id}","collaborators_url":"https://api.github.com/repos/codurance/site/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/codurance/site/teams","hooks_url":"https://api.github.com/repos/codurance/site/hooks","issue_events_url":"https://api.github.com/repos/codurance/site/issues/events{/number}","events_url":"https://api.github.com/repos/codurance/site/events","assignees_url":"https://api.github.com/repos/codurance/site/assignees{/user}","branches_url":"https://api.github.com/repos/codurance/site/branches{/branch}","tags_url":"https://api.github.com/repos/codurance/site/tags","blobs_url":"https://api.github.com/repos/codurance/site/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/codurance/site/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/codurance/site/git/refs{/sha}","trees_url":"https://api.github.com/repos/codurance/site/git/trees{/sha}","statuses_url":"https://api.github.com/repos/codurance/site/statuses/{sha}","languages_url":"https://api.github.com/repos/codurance/site/languages","stargazers_url":"https://api.github.com/repos/codurance/site/stargazers","contributors_url":"https://api.github.com/repos/codurance/site/contributors","subscribers_url":"https://api.github.com/repos/codurance/site/subscribers","subscription_url":"https://api.github.com/repos/codurance/site/subscription","commits_url":"https://api.github.com/repos/codurance/site/commits{/sha}","git_commits_url":"https://api.github.com/repos/codurance/site/git/commits{/sha}","comments_url":"https://api.github.com/repos/codurance/site/comments{/number}","issue_comment_url":"https://api.github.com/repos/codurance/site/issues/comments{/number}","contents_url":"https://api.github.com/repos/codurance/site/contents/{+path}","compare_url":"https://api.github.com/repos/codurance/site/compare/{base}...{head}","merges_url":"https://api.github.com/repos/codurance/site/merges","archive_url":"https://api.github.com/repos/codurance/site/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/codurance/site/downloads","issues_url":"https://api.github.com/repos/codurance/site/issues{/number}","pulls_url":"https://api.github.com/repos/codurance/site/pulls{/number}","milestones_url":"https://api.github.com/repos/codurance/site/milestones{/number}","notifications_url":"https://api.github.com/repos/codurance/site/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/codurance/site/labels{/name}","releases_url":"https://api.github.com/repos/codurance/site/releases{/id}","deployments_url":"https://api.github.com/repos/codurance/site/deployments","created_at":"2015-07-02T09:54:02Z","updated_at":"2016-03-14T09:39:20Z","pushed_at":"2016-05-03T16:33:41Z","git_url":"git://github.com/codurance/site.git","ssh_url":"git@github.com:codurance/site.git","clone_url":"https://github.com/codurance/site.git","svn_url":"https://github.com/codurance/site","homepage":null,"size":160243,"stargazers_count":1,"watchers_count":1,"language":"CSS","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":2,"mirror_url":null,"open_issues_count":2,"forks":2,"open_issues":2,"watchers":1,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/codurance/site/pulls/161"},"html":{"href":"https://github.com/codurance/site/pull/161"},"issue":{"href":"https://api.github.com/repos/codurance/site/issues/161"},"comments":{"href":"https://api.github.com/repos/codurance/site/issues/161/comments"},"review_comments":{"href":"https://api.github.com/repos/codurance/site/pulls/161/comments"},"review_comment":{"href":"https://api.github.com/repos/codurance/site/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/codurance/site/pulls/161/commits"},"statuses":{"href":"https://api.github.com/repos/codurance/site/statuses/15f248486231b6e11fbcea5a43cbef30172a09e4"}}}}