{"action":"created","issue":{"url":"https://api.github.com/repos/line/armeria/issues/124","repository_url":"https://api.github.com/repos/line/armeria","labels_url":"https://api.github.com/repos/line/armeria/issues/124/labels{/name}","comments_url":"https://api.github.com/repos/line/armeria/issues/124/comments","events_url":"https://api.github.com/repos/line/armeria/issues/124/events","html_url":"https://github.com/line/armeria/pull/124","id":141341082,"number":124,"title":"circuit breaker for armeria","user":{"login":"synk","id":543209,"avatar_url":"https://avatars.githubusercontent.com/u/543209?v=3","gravatar_id":"","url":"https://api.github.com/users/synk","html_url":"https://github.com/synk","followers_url":"https://api.github.com/users/synk/followers","following_url":"https://api.github.com/users/synk/following{/other_user}","gists_url":"https://api.github.com/users/synk/gists{/gist_id}","starred_url":"https://api.github.com/users/synk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/synk/subscriptions","organizations_url":"https://api.github.com/users/synk/orgs","repos_url":"https://api.github.com/users/synk/repos","events_url":"https://api.github.com/users/synk/events{/privacy}","received_events_url":"https://api.github.com/users/synk/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/line/armeria/labels/new%20feature","name":"new feature","color":"009800"}],"state":"open","locked":false,"assignee":{"login":"trustin","id":173918,"avatar_url":"https://avatars.githubusercontent.com/u/173918?v=3","gravatar_id":"","url":"https://api.github.com/users/trustin","html_url":"https://github.com/trustin","followers_url":"https://api.github.com/users/trustin/followers","following_url":"https://api.github.com/users/trustin/following{/other_user}","gists_url":"https://api.github.com/users/trustin/gists{/gist_id}","starred_url":"https://api.github.com/users/trustin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trustin/subscriptions","organizations_url":"https://api.github.com/users/trustin/orgs","repos_url":"https://api.github.com/users/trustin/repos","events_url":"https://api.github.com/users/trustin/events{/privacy}","received_events_url":"https://api.github.com/users/trustin/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/line/armeria/milestones/15","html_url":"https://github.com/line/armeria/milestones/0.13.0.Final","labels_url":"https://api.github.com/repos/line/armeria/milestones/15/labels","id":1663323,"number":15,"title":"0.13.0.Final","description":null,"creator":{"login":"trustin","id":173918,"avatar_url":"https://avatars.githubusercontent.com/u/173918?v=3","gravatar_id":"","url":"https://api.github.com/users/trustin","html_url":"https://github.com/trustin","followers_url":"https://api.github.com/users/trustin/followers","following_url":"https://api.github.com/users/trustin/following{/other_user}","gists_url":"https://api.github.com/users/trustin/gists{/gist_id}","starred_url":"https://api.github.com/users/trustin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trustin/subscriptions","organizations_url":"https://api.github.com/users/trustin/orgs","repos_url":"https://api.github.com/users/trustin/repos","events_url":"https://api.github.com/users/trustin/events{/privacy}","received_events_url":"https://api.github.com/users/trustin/received_events","type":"User","site_admin":false},"open_issues":1,"closed_issues":1,"state":"open","created_at":"2016-03-24T06:31:14Z","updated_at":"2016-03-24T06:47:57Z","due_on":null,"closed_at":null},"comments":8,"created_at":"2016-03-16T17:13:56Z","updated_at":"2016-03-29T10:51:50Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/line/armeria/pulls/124","html_url":"https://github.com/line/armeria/pull/124","diff_url":"https://github.com/line/armeria/pull/124.diff","patch_url":"https://github.com/line/armeria/pull/124.patch"},"body":"Provides a failure detection and fallback mechanism based of circuit breaker pattern.\r\n\r\n# Setup Client with Circuit Breaker\r\n### Example\r\n```java\r\nIface helloClient = new ClientBuilder(\"tbinary+http://127.0.0.1:8080/hello\")\r\n                    .decorator(\r\n                        CircuitBreakerClient.newDecorator(\r\n                            new CircuitBreakerBuilder(\"hello\").build()\r\n                        )\r\n                    )\r\n                    .build(Iface.class);\r\n```\r\n\r\n# A Unit of Failure Detection\r\nYou can specify a unit of failure detection from the following:\r\n* per remote service (as shown in the example above)\r\n* per method\r\n* per remote host\r\n* per remote host and method\r\n\r\n### Example\r\n```java\r\n// Setup with per-method failure detection\r\nAsyncIface helloClient = new ClientBuilder(\"tbinary+http://127.0.0.1:8080/hello\")\r\n                         .decorator(\r\n                             CircuitBreakerClient.newPerMethodDecorator(\r\n                                 method -> new CircuitBreakerBuilder(method).build()\r\n                             )\r\n                         )\r\n                         .build(AsyncIface.class);\r\n```\r\n\r\n# Fallback\r\nOnce a failure is detected, A `FailFastException` is thrown the client. You can write a fallback code by catching the exception.\r\n### Example\r\n```java\r\ntry {\r\n    helloClient.hello(\"line\");\r\n} catch (TException e) {\r\n    // error handling\r\n} catch (FailFastException e) {\r\n   // fallback code\r\n}\r\n```\r\n\r\n### Example in Async Client\r\n```java\r\nhelloClient.hello(\"line\", new AsyncMethodCallback() {\r\n    public void onComplete(Object response) {\r\n        // response handling\r\n    }\r\n    public void onError(Exception e) {\r\n        if (e instanceof TException) {\r\n            // error handling\r\n        } else if (e instanceof FailFastException) {\r\n            // fallback code\r\n        }\r\n    }\r\n});\r\n```\r\n\r\n# Circuit States and Transitions\r\nThe circuit breaker provided by this package is implemented as a finite state machine consisting of the\r\nfollowing states and transitions.\r\n\r\n### `CLOSED`\r\nThe initial state. All requests are sent to the remote service. If the failure rate exceeds\r\nthe specified threshold, the state turns into `OPEN`.\r\n\r\n### `OPEN`\r\nAll requests fail immediately without calling the remote service. After the specified time,\r\nthe state turns into `HALF_OPEN`.\r\n\r\n### `HALF_OPEN`\r\nOnly one trial request is sent at a time.\r\n* If it succeeds, the state turns into `CLOSED`.\r\n* If it fails, the state returns to `OPEN`.\r\n* If it doesn't complete within a certain time, another trial request will be sent again.\r\n\r\n# Circuit Breaker Configurations\r\nThe behavior of a circuit breaker can be modified via `CircuitBreakerConfigBuilder`.\r\n\r\n### `failureRateThreshold`\r\nThe threshold of failure rate(= failure/total) to detect a remote service fault.\r\n\r\n### `minimumRequestThreshold`\r\nThe minimum number of requests within the time window necessary to detect a remote service fault.\r\n\r\n### `circuitOpenWindow`\r\nThe duration of OPEN state.\r\n\r\n### `trialRequestInterval`\r\nThe interval of trial request in HALF_OPEN state.\r\n\r\n### `counterSlidingWindow`\r\nThe time length of sliding window to accumulate the count of events.\r\n\r\n### `counterUpdateInterval`\r\nThe interval that a circuit breaker can see the latest count of events.\r\n\r\n### `exceptionFilter`\r\n A filter that decides whether a circuit breaker should deal with a given error.\r\n"},"comment":{"url":"https://api.github.com/repos/line/armeria/issues/comments/202829482","html_url":"https://github.com/line/armeria/pull/124#issuecomment-202829482","issue_url":"https://api.github.com/repos/line/armeria/issues/124","id":202829482,"user":{"login":"synk","id":543209,"avatar_url":"https://avatars.githubusercontent.com/u/543209?v=3","gravatar_id":"","url":"https://api.github.com/users/synk","html_url":"https://github.com/synk","followers_url":"https://api.github.com/users/synk/followers","following_url":"https://api.github.com/users/synk/following{/other_user}","gists_url":"https://api.github.com/users/synk/gists{/gist_id}","starred_url":"https://api.github.com/users/synk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/synk/subscriptions","organizations_url":"https://api.github.com/users/synk/orgs","repos_url":"https://api.github.com/users/synk/repos","events_url":"https://api.github.com/users/synk/events{/privacy}","received_events_url":"https://api.github.com/users/synk/received_events","type":"User","site_admin":false},"created_at":"2016-03-29T10:51:50Z","updated_at":"2016-03-29T10:51:50Z","body":"@trustin I addressed your comments. And I replied to some of your comments."}}