{"action":"created","comment":{"url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/comments/189296106","pull_request_review_id":121453537,"id":189296106,"diff_hunk":"@@ -32,11 +34,29 @@ extension BackendService: BackendServiceProtocol {\n     public func execute<T: NetworkRequest>(request: T, completion: @escaping BackendServiceCompletion<T.ResponseType, T.ErrorType>) {\n         networkService.execute(request: request.urlRequest) { result in\n             switch result {\n-            case .success(let result):\n-                BackendServiceHelper.handleResponseData(result.data, for: request, completion: completion)\n-            case .failure(let result):\n-                DispatchQueue.main.async {\n-                    completion(.failure(T.ErrorType(networkServiceFailure: result)))\n+            case .success(let serviceSuccess):\n+                BackendServiceHelper.handleResponseData(serviceSuccess.data, for: request, completion: completion)\n+            case .failure(let serviceFailure):\n+                BackendServiceHelper.handleNetworkServiceFailure(serviceFailure, completion: completion)\n+            }\n+        }\n+    }\n+    \n+    public func execute<T: NetworkRequest & Recoverable>(recoverable request: T, completion: @escaping BackendServiceCompletion<T.ResponseType, T.ErrorType>) {\n+        execute(request: request) { [weak self] result in\n+            switch result {\n+            case .success(let response):\n+                BackendServiceHelper.handleResponse(response, completion: completion)\n+                \n+            case .failure(let error):\n+                guard let recoveryStrategy = self?.recoveryStrategy else { return completion(.failure(error)) }","path":"Sources/Hyperspace/Service/Backend/BackendService.swift","position":39,"original_position":39,"commit_id":"5619f7bbf8716fa64b5fdf2c4381835421d0e908","original_commit_id":"5619f7bbf8716fa64b5fdf2c4381835421d0e908","user":{"login":"wmcginty","id":7141301,"avatar_url":"https://avatars1.githubusercontent.com/u/7141301?v=4","gravatar_id":"","url":"https://api.github.com/users/wmcginty","html_url":"https://github.com/wmcginty","followers_url":"https://api.github.com/users/wmcginty/followers","following_url":"https://api.github.com/users/wmcginty/following{/other_user}","gists_url":"https://api.github.com/users/wmcginty/gists{/gist_id}","starred_url":"https://api.github.com/users/wmcginty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wmcginty/subscriptions","organizations_url":"https://api.github.com/users/wmcginty/orgs","repos_url":"https://api.github.com/users/wmcginty/repos","events_url":"https://api.github.com/users/wmcginty/events{/privacy}","received_events_url":"https://api.github.com/users/wmcginty/received_events","type":"User","site_admin":false},"body":"Good catch. We very much do. Will tweak that now.","created_at":"2018-05-18T14:55:30Z","updated_at":"2018-05-18T14:55:30Z","html_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace/pull/45#discussion_r189296106","pull_request_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/comments/189296106"},"html":{"href":"https://github.com/BottleRocketStudios/iOS-Hyperspace/pull/45#discussion_r189296106"},"pull_request":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45"}},"in_reply_to_id":189290722},"pull_request":{"url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45","id":188841179,"html_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace/pull/45","diff_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace/pull/45.diff","patch_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace/pull/45.patch","issue_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/45","number":45,"state":"open","locked":false,"title":"Automatic Error Recovery","user":{"login":"wmcginty","id":7141301,"avatar_url":"https://avatars1.githubusercontent.com/u/7141301?v=4","gravatar_id":"","url":"https://api.github.com/users/wmcginty","html_url":"https://github.com/wmcginty","followers_url":"https://api.github.com/users/wmcginty/followers","following_url":"https://api.github.com/users/wmcginty/following{/other_user}","gists_url":"https://api.github.com/users/wmcginty/gists{/gist_id}","starred_url":"https://api.github.com/users/wmcginty/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wmcginty/subscriptions","organizations_url":"https://api.github.com/users/wmcginty/orgs","repos_url":"https://api.github.com/users/wmcginty/repos","events_url":"https://api.github.com/users/wmcginty/events{/privacy}","received_events_url":"https://api.github.com/users/wmcginty/received_events","type":"User","site_admin":false},"body":"This is another large feature that I want to get in before 2.0 pre-release if possible. Essentially, this does the following:\r\n\r\n- Adds a protocol `Recoverable`, which dictates when an arbitrary operation can be recovered from and re-attempted. Also adds an extension on `Recoverable` for easily preparing subsequent attempts.\r\n- Adds an optional property to the default `BackendService` (should it be a part of the `BackendServiceProtocol`?) for a `RequestRecoveryStrategy`. This object allows for certain errors to be handled automatically by returning a specific `RecoveryDisposition` of `retry` or `fail`.\r\n\r\nFor example: If the error returned is a 401 unauthorized, the recovery strategy can add the appropriate authorization header to the request, and return `retry`. \r\n\r\nI can look into a subspec if we think that it belongs in one.","created_at":"2018-05-17T19:42:37Z","updated_at":"2018-05-18T14:55:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"68fb6b609fac5190cf470696a2222de2d6548ae0","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45/commits","review_comments_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45/comments","review_comment_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/comments{/number}","comments_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/45/comments","statuses_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/statuses/5619f7bbf8716fa64b5fdf2c4381835421d0e908","head":{"label":"BottleRocketStudios:errorRecovery","ref":"errorRecovery","sha":"5619f7bbf8716fa64b5fdf2c4381835421d0e908","user":{"login":"BottleRocketStudios","id":16840505,"avatar_url":"https://avatars3.githubusercontent.com/u/16840505?v=4","gravatar_id":"","url":"https://api.github.com/users/BottleRocketStudios","html_url":"https://github.com/BottleRocketStudios","followers_url":"https://api.github.com/users/BottleRocketStudios/followers","following_url":"https://api.github.com/users/BottleRocketStudios/following{/other_user}","gists_url":"https://api.github.com/users/BottleRocketStudios/gists{/gist_id}","starred_url":"https://api.github.com/users/BottleRocketStudios/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BottleRocketStudios/subscriptions","organizations_url":"https://api.github.com/users/BottleRocketStudios/orgs","repos_url":"https://api.github.com/users/BottleRocketStudios/repos","events_url":"https://api.github.com/users/BottleRocketStudios/events{/privacy}","received_events_url":"https://api.github.com/users/BottleRocketStudios/received_events","type":"Organization","site_admin":false},"repo":{"id":114586409,"name":"iOS-Hyperspace","full_name":"BottleRocketStudios/iOS-Hyperspace","owner":{"login":"BottleRocketStudios","id":16840505,"avatar_url":"https://avatars3.githubusercontent.com/u/16840505?v=4","gravatar_id":"","url":"https://api.github.com/users/BottleRocketStudios","html_url":"https://github.com/BottleRocketStudios","followers_url":"https://api.github.com/users/BottleRocketStudios/followers","following_url":"https://api.github.com/users/BottleRocketStudios/following{/other_user}","gists_url":"https://api.github.com/users/BottleRocketStudios/gists{/gist_id}","starred_url":"https://api.github.com/users/BottleRocketStudios/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BottleRocketStudios/subscriptions","organizations_url":"https://api.github.com/users/BottleRocketStudios/orgs","repos_url":"https://api.github.com/users/BottleRocketStudios/repos","events_url":"https://api.github.com/users/BottleRocketStudios/events{/privacy}","received_events_url":"https://api.github.com/users/BottleRocketStudios/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace","description":"An extremely lightweight wrapper around URLSession to make working with APIs a breeze.","fork":false,"url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace","forks_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/forks","keys_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/keys{/key_id}","collaborators_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/teams","hooks_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/hooks","issue_events_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/events{/number}","events_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/events","assignees_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/assignees{/user}","branches_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/branches{/branch}","tags_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/tags","blobs_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/refs{/sha}","trees_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/trees{/sha}","statuses_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/statuses/{sha}","languages_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/languages","stargazers_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/stargazers","contributors_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/contributors","subscribers_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/subscribers","subscription_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/subscription","commits_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/commits{/sha}","git_commits_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/commits{/sha}","comments_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/comments{/number}","issue_comment_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/comments{/number}","contents_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/contents/{+path}","compare_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/compare/{base}...{head}","merges_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/merges","archive_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/downloads","issues_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues{/number}","pulls_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls{/number}","milestones_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/milestones{/number}","notifications_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/labels{/name}","releases_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/releases{/id}","deployments_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/deployments","created_at":"2017-12-18T02:21:33Z","updated_at":"2018-05-14T15:18:23Z","pushed_at":"2018-05-18T14:47:44Z","git_url":"git://github.com/BottleRocketStudios/iOS-Hyperspace.git","ssh_url":"git@github.com:BottleRocketStudios/iOS-Hyperspace.git","clone_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace.git","svn_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace","homepage":null,"size":240,"stargazers_count":8,"watchers_count":8,"language":"Swift","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":7,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":1,"open_issues":7,"watchers":8,"default_branch":"master"}},"base":{"label":"BottleRocketStudios:release/2.0.0","ref":"release/2.0.0","sha":"a17e7555bd0a8c7abff09e5685f4fb52f5eee90e","user":{"login":"BottleRocketStudios","id":16840505,"avatar_url":"https://avatars3.githubusercontent.com/u/16840505?v=4","gravatar_id":"","url":"https://api.github.com/users/BottleRocketStudios","html_url":"https://github.com/BottleRocketStudios","followers_url":"https://api.github.com/users/BottleRocketStudios/followers","following_url":"https://api.github.com/users/BottleRocketStudios/following{/other_user}","gists_url":"https://api.github.com/users/BottleRocketStudios/gists{/gist_id}","starred_url":"https://api.github.com/users/BottleRocketStudios/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BottleRocketStudios/subscriptions","organizations_url":"https://api.github.com/users/BottleRocketStudios/orgs","repos_url":"https://api.github.com/users/BottleRocketStudios/repos","events_url":"https://api.github.com/users/BottleRocketStudios/events{/privacy}","received_events_url":"https://api.github.com/users/BottleRocketStudios/received_events","type":"Organization","site_admin":false},"repo":{"id":114586409,"name":"iOS-Hyperspace","full_name":"BottleRocketStudios/iOS-Hyperspace","owner":{"login":"BottleRocketStudios","id":16840505,"avatar_url":"https://avatars3.githubusercontent.com/u/16840505?v=4","gravatar_id":"","url":"https://api.github.com/users/BottleRocketStudios","html_url":"https://github.com/BottleRocketStudios","followers_url":"https://api.github.com/users/BottleRocketStudios/followers","following_url":"https://api.github.com/users/BottleRocketStudios/following{/other_user}","gists_url":"https://api.github.com/users/BottleRocketStudios/gists{/gist_id}","starred_url":"https://api.github.com/users/BottleRocketStudios/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/BottleRocketStudios/subscriptions","organizations_url":"https://api.github.com/users/BottleRocketStudios/orgs","repos_url":"https://api.github.com/users/BottleRocketStudios/repos","events_url":"https://api.github.com/users/BottleRocketStudios/events{/privacy}","received_events_url":"https://api.github.com/users/BottleRocketStudios/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace","description":"An extremely lightweight wrapper around URLSession to make working with APIs a breeze.","fork":false,"url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace","forks_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/forks","keys_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/keys{/key_id}","collaborators_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/teams","hooks_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/hooks","issue_events_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/events{/number}","events_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/events","assignees_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/assignees{/user}","branches_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/branches{/branch}","tags_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/tags","blobs_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/refs{/sha}","trees_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/trees{/sha}","statuses_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/statuses/{sha}","languages_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/languages","stargazers_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/stargazers","contributors_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/contributors","subscribers_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/subscribers","subscription_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/subscription","commits_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/commits{/sha}","git_commits_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/git/commits{/sha}","comments_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/comments{/number}","issue_comment_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/comments{/number}","contents_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/contents/{+path}","compare_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/compare/{base}...{head}","merges_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/merges","archive_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/downloads","issues_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues{/number}","pulls_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls{/number}","milestones_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/milestones{/number}","notifications_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/labels{/name}","releases_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/releases{/id}","deployments_url":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/deployments","created_at":"2017-12-18T02:21:33Z","updated_at":"2018-05-14T15:18:23Z","pushed_at":"2018-05-18T14:47:44Z","git_url":"git://github.com/BottleRocketStudios/iOS-Hyperspace.git","ssh_url":"git@github.com:BottleRocketStudios/iOS-Hyperspace.git","clone_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace.git","svn_url":"https://github.com/BottleRocketStudios/iOS-Hyperspace","homepage":null,"size":240,"stargazers_count":8,"watchers_count":8,"language":"Swift","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"archived":false,"open_issues_count":7,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0"},"forks":1,"open_issues":7,"watchers":8,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45"},"html":{"href":"https://github.com/BottleRocketStudios/iOS-Hyperspace/pull/45"},"issue":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/45"},"comments":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/issues/45/comments"},"review_comments":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45/comments"},"review_comment":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/pulls/45/commits"},"statuses":{"href":"https://api.github.com/repos/BottleRocketStudios/iOS-Hyperspace/statuses/5619f7bbf8716fa64b5fdf2c4381835421d0e908"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"wmcginty"}}