{"action":"created","comment":{"url":"https://api.github.com/repos/lift/framework/pulls/comments/82551718","pull_request_review_id":3451318,"id":82551718,"diff_hunk":"@@ -406,5 +408,28 @@ object LAFuture {\n \n     ret\n   }\n-}\n \n+  private def inContext[T](f: () => T, context: Box[LAFuture.Context]): () => T = {\n+    context.map(_.around(f)) openOr f\n+  }\n+\n+  private def inContext[A, T](f: (A) => T, context: Box[LAFuture.Context]): (A) => T = {\n+    context.map(_.around(f)) openOr f\n+  }\n+\n+  /**\n+    * Allows to wrap function in another function providing some additional functionality.\n+    * It may choose to execute or not execute that functionality, but should not interpret\n+    * or change the returned value; instead, it should perform orthogonal actions that\n+    * need to occur around the given functionality. Typical example is setting up DB\n+    * transaction.","path":"core/actor/src/main/scala/net/liftweb/actor/LAFuture.scala","position":147,"original_position":147,"commit_id":"9b8de87bc25a04d0cacd4936f975b280ee4cfe26","original_commit_id":"9b8de87bc25a04d0cacd4936f975b280ee4cfe26","user":{"login":"pdyraga","id":4712360,"avatar_url":"https://avatars.githubusercontent.com/u/4712360?v=3","gravatar_id":"","url":"https://api.github.com/users/pdyraga","html_url":"https://github.com/pdyraga","followers_url":"https://api.github.com/users/pdyraga/followers","following_url":"https://api.github.com/users/pdyraga/following{/other_user}","gists_url":"https://api.github.com/users/pdyraga/gists{/gist_id}","starred_url":"https://api.github.com/users/pdyraga/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdyraga/subscriptions","organizations_url":"https://api.github.com/users/pdyraga/orgs","repos_url":"https://api.github.com/users/pdyraga/repos","events_url":"https://api.github.com/users/pdyraga/events{/privacy}","received_events_url":"https://api.github.com/users/pdyraga/received_events","type":"User","site_admin":false},"body":"I'm not a native speaker, so any improvement ideas for this scaladoc are very appreciated :) \r\n\r\nAs an \"orthogonal\" action, such as DB transaction I mean:\r\n\r\n```\r\ndef addNewUser(name: String, surname: String, email: String): Box[User] = {\r\n  try {\r\n    DB.createNewTransaction()\r\n    val user = User(name, surname, email)\r\n    repository.persist(user)\r\n    eventBus.publish(NewUserCreatedEvent(user.id))\r\n } finally {\r\n   DB.flushTransaction()\r\n }\r\n} \r\n```\r\n\r\n^ Here, that `try - finally` block with all `DB` calls is orthogonal to business logic of this method. It shouldn't be here together with business logic code. That's a typical case when we can use `Context` (or `CommonLoanWrapper`). In Java world, it would be probably just an annotation +  aspect.","created_at":"2016-10-10T07:08:48Z","updated_at":"2016-10-10T07:08:48Z","html_url":"https://github.com/lift/framework/pull/1813#discussion_r82551718","pull_request_url":"https://api.github.com/repos/lift/framework/pulls/1813","_links":{"self":{"href":"https://api.github.com/repos/lift/framework/pulls/comments/82551718"},"html":{"href":"https://github.com/lift/framework/pull/1813#discussion_r82551718"},"pull_request":{"href":"https://api.github.com/repos/lift/framework/pulls/1813"}}},"pull_request":{"url":"https://api.github.com/repos/lift/framework/pulls/1813","id":88542405,"html_url":"https://github.com/lift/framework/pull/1813","diff_url":"https://github.com/lift/framework/pull/1813.diff","patch_url":"https://github.com/lift/framework/pull/1813.patch","issue_url":"https://api.github.com/repos/lift/framework/issues/1813","number":1813,"state":"open","locked":false,"title":"Req and LiftSession - aware Futures / LAFutures","user":{"login":"pdyraga","id":4712360,"avatar_url":"https://avatars.githubusercontent.com/u/4712360?v=3","gravatar_id":"","url":"https://api.github.com/users/pdyraga","html_url":"https://github.com/pdyraga","followers_url":"https://api.github.com/users/pdyraga/followers","following_url":"https://api.github.com/users/pdyraga/following{/other_user}","gists_url":"https://api.github.com/users/pdyraga/gists{/gist_id}","starred_url":"https://api.github.com/users/pdyraga/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdyraga/subscriptions","organizations_url":"https://api.github.com/users/pdyraga/orgs","repos_url":"https://api.github.com/users/pdyraga/repos","events_url":"https://api.github.com/users/pdyraga/events{/privacy}","received_events_url":"https://api.github.com/users/pdyraga/received_events","type":"User","site_admin":false},"body":"Session-aware futures seems to be a recurring pain point in many projects. In the one I work, we often use `Future`s to lazy-load some part of a page, e.g. retrieve a list of users from a database and then apply Lift bindings on them. \r\n\r\nIn Lift3 `Future` template binding is straightforward but one thing is still missing: you can’t access session from them which is not so crazy as it might sound. \r\n\r\nContinuing with users from database example, say that we retrieved a `Future[Seq]` of users and now we want to `.map` it to produce bindings that will be later bound to element. In that bindings, we’d like to use `S.?` to render localised user type text. Currently it’s not possible, because session will not be available in thread doing `.map` call.\r\n\r\nWe already have a PR addressing this issue https://github.com/lift/framework/pull/1730 but there are few things missing there in my opinion:\r\n\r\n- lack of `ReqVar` access. I think that we should offer the same access scope as `LazyLoad` that we already have in Lift\r\n- lack of session access in `Future` / `LAFuture` body\r\n- We shouldn’t use `CommonLoanWrapper` for session context wrapping, because `CommonLoanWrapper` acts lazily which may lead to session wrapping to be done in separate thread which is too late. We need to enrich function with session access eagerly. \r\n\r\nSample usage of feature implemented in this PR can be:\r\n```\r\n<div id=\"main\" data-lift=\"HelloWorld.render\">\r\n  Future: <span id=\"scala-future\">Time goes here</span><br/>\r\n  LAFuture: <span id=\"lift-future\">Time goes here</span>\r\n</div>\r\n```\r\n\r\n```\r\nclass HelloWorld {\r\n\r\n  def render = {\r\n    \"#lift-future *\" #> LAFutureWithSession.withCurrentSession {\r\n      Thread.sleep(3000);\r\n      S ? (\"general-futureCompleted\", date)\r\n    }.map(s => s\"$s in request from = ${S.request.map(_.userAgent).openOrThrowException(\"No request!\")}\") &\r\n    \"#scala-future *\" #> FutureWithSession.withCurrentSession {\r\n      Thread.sleep(1000);\r\n      S ? (\"general-futureCompleted\", date)\r\n    }.map(s => s\"$s in request from = ${S.request.map(_.userAgent).openOrThrowException(\"No request!\")}\")\r\n  }\r\n\r\n  private def date: String = {\r\n    new SimpleDateFormat(\"yyyy/MM/dd HH:mm:ss\").format(new Date())\r\n  }\r\n}\r\n```\r\n\r\nMailing list reference: https://groups.google.com/forum/#!topic/liftweb/qXDBuSTfWnw","created_at":"2016-10-08T10:54:32Z","updated_at":"2016-10-10T07:08:48Z","closed_at":null,"merged_at":null,"merge_commit_sha":"d0e696e4ce33ebbe66ad5ca1e8cc91b125204ca3","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/lift/framework/pulls/1813/commits","review_comments_url":"https://api.github.com/repos/lift/framework/pulls/1813/comments","review_comment_url":"https://api.github.com/repos/lift/framework/pulls/comments{/number}","comments_url":"https://api.github.com/repos/lift/framework/issues/1813/comments","statuses_url":"https://api.github.com/repos/lift/framework/statuses/9b8de87bc25a04d0cacd4936f975b280ee4cfe26","head":{"label":"pdyraga:session-aware-futures","ref":"session-aware-futures","sha":"9b8de87bc25a04d0cacd4936f975b280ee4cfe26","user":{"login":"pdyraga","id":4712360,"avatar_url":"https://avatars.githubusercontent.com/u/4712360?v=3","gravatar_id":"","url":"https://api.github.com/users/pdyraga","html_url":"https://github.com/pdyraga","followers_url":"https://api.github.com/users/pdyraga/followers","following_url":"https://api.github.com/users/pdyraga/following{/other_user}","gists_url":"https://api.github.com/users/pdyraga/gists{/gist_id}","starred_url":"https://api.github.com/users/pdyraga/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdyraga/subscriptions","organizations_url":"https://api.github.com/users/pdyraga/orgs","repos_url":"https://api.github.com/users/pdyraga/repos","events_url":"https://api.github.com/users/pdyraga/events{/privacy}","received_events_url":"https://api.github.com/users/pdyraga/received_events","type":"User","site_admin":false},"repo":{"id":68476892,"name":"framework","full_name":"pdyraga/framework","owner":{"login":"pdyraga","id":4712360,"avatar_url":"https://avatars.githubusercontent.com/u/4712360?v=3","gravatar_id":"","url":"https://api.github.com/users/pdyraga","html_url":"https://github.com/pdyraga","followers_url":"https://api.github.com/users/pdyraga/followers","following_url":"https://api.github.com/users/pdyraga/following{/other_user}","gists_url":"https://api.github.com/users/pdyraga/gists{/gist_id}","starred_url":"https://api.github.com/users/pdyraga/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pdyraga/subscriptions","organizations_url":"https://api.github.com/users/pdyraga/orgs","repos_url":"https://api.github.com/users/pdyraga/repos","events_url":"https://api.github.com/users/pdyraga/events{/privacy}","received_events_url":"https://api.github.com/users/pdyraga/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/pdyraga/framework","description":"Lift Framework","fork":true,"url":"https://api.github.com/repos/pdyraga/framework","forks_url":"https://api.github.com/repos/pdyraga/framework/forks","keys_url":"https://api.github.com/repos/pdyraga/framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pdyraga/framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pdyraga/framework/teams","hooks_url":"https://api.github.com/repos/pdyraga/framework/hooks","issue_events_url":"https://api.github.com/repos/pdyraga/framework/issues/events{/number}","events_url":"https://api.github.com/repos/pdyraga/framework/events","assignees_url":"https://api.github.com/repos/pdyraga/framework/assignees{/user}","branches_url":"https://api.github.com/repos/pdyraga/framework/branches{/branch}","tags_url":"https://api.github.com/repos/pdyraga/framework/tags","blobs_url":"https://api.github.com/repos/pdyraga/framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pdyraga/framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pdyraga/framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/pdyraga/framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pdyraga/framework/statuses/{sha}","languages_url":"https://api.github.com/repos/pdyraga/framework/languages","stargazers_url":"https://api.github.com/repos/pdyraga/framework/stargazers","contributors_url":"https://api.github.com/repos/pdyraga/framework/contributors","subscribers_url":"https://api.github.com/repos/pdyraga/framework/subscribers","subscription_url":"https://api.github.com/repos/pdyraga/framework/subscription","commits_url":"https://api.github.com/repos/pdyraga/framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/pdyraga/framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/pdyraga/framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/pdyraga/framework/issues/comments{/number}","contents_url":"https://api.github.com/repos/pdyraga/framework/contents/{+path}","compare_url":"https://api.github.com/repos/pdyraga/framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pdyraga/framework/merges","archive_url":"https://api.github.com/repos/pdyraga/framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pdyraga/framework/downloads","issues_url":"https://api.github.com/repos/pdyraga/framework/issues{/number}","pulls_url":"https://api.github.com/repos/pdyraga/framework/pulls{/number}","milestones_url":"https://api.github.com/repos/pdyraga/framework/milestones{/number}","notifications_url":"https://api.github.com/repos/pdyraga/framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pdyraga/framework/labels{/name}","releases_url":"https://api.github.com/repos/pdyraga/framework/releases{/id}","deployments_url":"https://api.github.com/repos/pdyraga/framework/deployments","created_at":"2016-09-17T20:37:37Z","updated_at":"2016-09-17T20:37:40Z","pushed_at":"2016-10-07T14:09:29Z","git_url":"git://github.com/pdyraga/framework.git","ssh_url":"git@github.com:pdyraga/framework.git","clone_url":"https://github.com/pdyraga/framework.git","svn_url":"https://github.com/pdyraga/framework","homepage":"http://liftweb.net","size":15778,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"lift:master","ref":"master","sha":"c29eb0408966cd0542649fb0c62302364e7a7221","user":{"login":"lift","id":317975,"avatar_url":"https://avatars.githubusercontent.com/u/317975?v=3","gravatar_id":"","url":"https://api.github.com/users/lift","html_url":"https://github.com/lift","followers_url":"https://api.github.com/users/lift/followers","following_url":"https://api.github.com/users/lift/following{/other_user}","gists_url":"https://api.github.com/users/lift/gists{/gist_id}","starred_url":"https://api.github.com/users/lift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lift/subscriptions","organizations_url":"https://api.github.com/users/lift/orgs","repos_url":"https://api.github.com/users/lift/repos","events_url":"https://api.github.com/users/lift/events{/privacy}","received_events_url":"https://api.github.com/users/lift/received_events","type":"Organization","site_admin":false},"repo":{"id":1295197,"name":"framework","full_name":"lift/framework","owner":{"login":"lift","id":317975,"avatar_url":"https://avatars.githubusercontent.com/u/317975?v=3","gravatar_id":"","url":"https://api.github.com/users/lift","html_url":"https://github.com/lift","followers_url":"https://api.github.com/users/lift/followers","following_url":"https://api.github.com/users/lift/following{/other_user}","gists_url":"https://api.github.com/users/lift/gists{/gist_id}","starred_url":"https://api.github.com/users/lift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lift/subscriptions","organizations_url":"https://api.github.com/users/lift/orgs","repos_url":"https://api.github.com/users/lift/repos","events_url":"https://api.github.com/users/lift/events{/privacy}","received_events_url":"https://api.github.com/users/lift/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/lift/framework","description":"Lift Framework","fork":false,"url":"https://api.github.com/repos/lift/framework","forks_url":"https://api.github.com/repos/lift/framework/forks","keys_url":"https://api.github.com/repos/lift/framework/keys{/key_id}","collaborators_url":"https://api.github.com/repos/lift/framework/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/lift/framework/teams","hooks_url":"https://api.github.com/repos/lift/framework/hooks","issue_events_url":"https://api.github.com/repos/lift/framework/issues/events{/number}","events_url":"https://api.github.com/repos/lift/framework/events","assignees_url":"https://api.github.com/repos/lift/framework/assignees{/user}","branches_url":"https://api.github.com/repos/lift/framework/branches{/branch}","tags_url":"https://api.github.com/repos/lift/framework/tags","blobs_url":"https://api.github.com/repos/lift/framework/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/lift/framework/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/lift/framework/git/refs{/sha}","trees_url":"https://api.github.com/repos/lift/framework/git/trees{/sha}","statuses_url":"https://api.github.com/repos/lift/framework/statuses/{sha}","languages_url":"https://api.github.com/repos/lift/framework/languages","stargazers_url":"https://api.github.com/repos/lift/framework/stargazers","contributors_url":"https://api.github.com/repos/lift/framework/contributors","subscribers_url":"https://api.github.com/repos/lift/framework/subscribers","subscription_url":"https://api.github.com/repos/lift/framework/subscription","commits_url":"https://api.github.com/repos/lift/framework/commits{/sha}","git_commits_url":"https://api.github.com/repos/lift/framework/git/commits{/sha}","comments_url":"https://api.github.com/repos/lift/framework/comments{/number}","issue_comment_url":"https://api.github.com/repos/lift/framework/issues/comments{/number}","contents_url":"https://api.github.com/repos/lift/framework/contents/{+path}","compare_url":"https://api.github.com/repos/lift/framework/compare/{base}...{head}","merges_url":"https://api.github.com/repos/lift/framework/merges","archive_url":"https://api.github.com/repos/lift/framework/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/lift/framework/downloads","issues_url":"https://api.github.com/repos/lift/framework/issues{/number}","pulls_url":"https://api.github.com/repos/lift/framework/pulls{/number}","milestones_url":"https://api.github.com/repos/lift/framework/milestones{/number}","notifications_url":"https://api.github.com/repos/lift/framework/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/lift/framework/labels{/name}","releases_url":"https://api.github.com/repos/lift/framework/releases{/id}","deployments_url":"https://api.github.com/repos/lift/framework/deployments","created_at":"2011-01-26T13:25:28Z","updated_at":"2016-10-08T02:06:09Z","pushed_at":"2016-10-10T02:58:46Z","git_url":"git://github.com/lift/framework.git","ssh_url":"git@github.com:lift/framework.git","clone_url":"https://github.com/lift/framework.git","svn_url":"https://github.com/lift/framework","homepage":"http://liftweb.net","size":19290,"stargazers_count":1032,"watchers_count":1032,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":252,"mirror_url":null,"open_issues_count":156,"forks":252,"open_issues":156,"watchers":1032,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/lift/framework/pulls/1813"},"html":{"href":"https://github.com/lift/framework/pull/1813"},"issue":{"href":"https://api.github.com/repos/lift/framework/issues/1813"},"comments":{"href":"https://api.github.com/repos/lift/framework/issues/1813/comments"},"review_comments":{"href":"https://api.github.com/repos/lift/framework/pulls/1813/comments"},"review_comment":{"href":"https://api.github.com/repos/lift/framework/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/lift/framework/pulls/1813/commits"},"statuses":{"href":"https://api.github.com/repos/lift/framework/statuses/9b8de87bc25a04d0cacd4936f975b280ee4cfe26"}}}}
{"actor":{"display_login":"pdyraga"}}