FutureWithSession

35 views
Skip to first unread message

Joe Barnes

unread,
Nov 7, 2015, 10:27:07 AM11/7/15
to Lift
Last week I finally decided to address the fact that we constantly need to grab the current LiftSession and re-initialize it when mapping over futures produced by other libraries such as akka and dispatch.  Shortly after I began that effort, I remembered that as of 3.0 Lift only supports 2.11.x and up.  I figure the FutureWithSession wrapper I'm working on could just as well go into Lift itself to help others have smooth integration with scala's built in Future which has been in the language since 2.10.  

The idea is pretty simple.  I made an implicit conversion that allows you to ask for `withCurrentSession` or `withImplicitSession` on a Future.  This returns a future which will wrap all of your maps, flatMaps, etc in a S.initIfUninitted with your session so you no longer have to manage all that yourself.  

The test code below shows an example of how the functions passed to `map` now can access session variables.

object TestVar1 extends SessionVar[String]("test1")
object TestVar2 extends SessionVar[String]("test2")

"A FutureWithSession" should {
  "have access to session variables in map() chains" in {
    val session = new LiftSession("Test Session", "", Empty)

    val future:Future[String] = S.initIfUninitted(session) {
      TestVar1("map1")
      TestVar2("map2")
      Future("something").withCurrentSession
    }
    val actual:Future[String] = future
      .map(_+"-"+TestVar1.get)
      .map(_+"-"+TestVar2.get)
    val expected:Option[Try[String]] = Some(Success("something-map1-map2"))

    actual.value must eventually(beEqualTo(expected))
  }
}

What does everyone think about having this in Lift?  I have about half of it done in this PR.  I'll finish it out if everyone likes the idea.

Joe




Matt Farmer

unread,
Nov 7, 2015, 2:08:29 PM11/7/15
to Lift
Are there potential performance impacts to hitting the `initIfUninitted` pipeline each time? Should we consider leaving the regular methods alone and providing one like `mapWithSession` and so on?

Additionally, what’s the story on LAFuture? Should we provide similar behavior for those?


Matt Farmer | Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07

--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code

---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Joe Barnes

unread,
Nov 7, 2015, 2:14:31 PM11/7/15
to lif...@googlegroups.com
I assume hitting initIfUninitted isn't free, but if you don't want that you simply don't call `withCurrentSession` or `withImplicitSession`.  It's no less explicit than `mapWithSession`, except that you have to call it only once and subsequent futures are similarly sessionized. 

Not sure about LAFuture as I don't use those except when Lift hands me one. I figured there was a good chance that this already worked with them, but I haven't thought to check.  If we like this feature for Future, then it certainly makes sense to add it to LAFuture as well.

Joe


You received this message because you are subscribed to a topic in the Google Groups "Lift" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/liftweb/zgTQ8E8joOE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to liftweb+u...@googlegroups.com.

Matt Farmer

unread,
Nov 7, 2015, 2:16:47 PM11/7/15
to Lift
I’m not really going for less explicit. I’m more going for the “only turn it on when you need it” bonus. On maps that don’t need it, you don’t incur any associated cost. On maps where you do need it, you ask for it and get it pretty easily. :)


Matt Farmer | Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07

Joe Barnes

unread,
Nov 7, 2015, 2:22:52 PM11/7/15
to lif...@googlegroups.com
Oh, I see what you mean.  In that case, I would rather keep the interface as it is but not automatically call `withImplicitSession` on each resulting Future like I'm doing now.  Changing `map`, `flatMap`, and `filter` will make them not work in for-comprehensions and stuff like that.  I just figured that if you want session stuff in your future, it's like you want them everywhere.  That is certainly debatable.

Joe

Joe Barnes

unread,
Nov 7, 2015, 2:33:08 PM11/7/15
to lif...@googlegroups.com
I should also add that I frequently see other developers on my team bewildered when their SessionVars don't magically work. I would rather err on the side of keeping the code working as expected than avoiding performance costs. Wasting a few CPU cycles is better than wasting a developer's time.  Hence, that's why I my first thought is to keep all subsequent futures in the session scope once asked for.

Joe

Joe Barnes

unread,
Nov 7, 2015, 2:38:17 PM11/7/15
to lif...@googlegroups.com
So sorry I can't get all of my thoughts into a single email.  Football is pretty distracting, lol

Another thing is I don't think for comprehensions will always work if we didn't always return another FutureWithSession.  For instance, a `for` with an if guard desugars into a `flatMap` and `filter`.  I don't know how you could ask for the session in the middle of that.  Hence you couldn't access a SessionVar in the if guard.

Joe

Matt Farmer

unread,
Nov 7, 2015, 8:37:38 PM11/7/15
to Lift
Got it. Yeah, I think your original proposal works then.


Matt Farmer | Blog | Twitter
GPG: CD57 2E26 F60C 0A61 E6D8  FC72 4493 8917 D667 4D07

Reply all
Reply to author
Forward
0 new messages