Getting current request in async context

33 views
Skip to first unread message

Flav Alex

unread,
Aug 3, 2015, 10:53:37 AM8/3/15
to Lift
Hi,

Both CurrentReq and S.request seem to share an interesting feature, namely everything is thread local. I don't know too much about the internals of Lift and certainly not enough to argue whether this is good or not, however there is currently no way whatsoever to fetch the context inside a Future. There are ways around things where requests can be manually passed around, however I'm hoping for a very clean way.

The use case is to check for an authentication cookie automatically, with no end user interaction, but everything else from db clients to end results is all done asynchronously and HTTP responses are using RestContinuation. Is there a way to make this work together properly?

Matt Farmer

unread,
Aug 3, 2015, 11:13:22 AM8/3/15
to Lift
Lift is stateful, meaning that you can keep track of state associated with a particular session on the server. So, for figuring out who the current user is, I typically use a SessionVar.

object currentUser extends SessionVar[Box[User]](Empty)

//When the user logs in
currentUser(loggedInUser)

//Get the user out
currentUser()

Have you tries something like that?

Let me know if that wasn’t clear. More than happy to elaborate, but I didn’t want to bore you if you had already seen this. :-)


Matt Farmer Blog | Twitter

--
--
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.

Andreas Joseph Krogh

unread,
Aug 3, 2015, 11:21:54 AM8/3/15
to lif...@googlegroups.com
I believe what you're after is RequestVar.generateSnapshotRestorer[T]
 
This generates a function which captures state (the state of the current RequestVar) so that you can run the generated function in some other thread as if it was running in the context of the initial RequestVar. We use this a lot so we can spawn jobs which can access the state captured in the scope of a request.
 
--
Andreas Joseph Krogh
CTO / Partner - Visena AS
Mobile: +47 909 56 963
 

Flav Alex

unread,
Aug 3, 2015, 11:55:45 AM8/3/15
to Lift
Lift is not inherently stateful, you are using it in stateful mode. This is true, but doesn't help me since the main point of my exercise is to be fully stateless.

Antonio Salazar Cardozo

unread,
Aug 3, 2015, 12:35:41 PM8/3/15
to Lift
Not quite following what you're looking for. RestHelpers take the Req instance that kicks off
the request, so you can refer to it in closures as needed, even if they're run asynchronously.
You can also pass it around to other functions as needed.
Thanks,
Antonio

Flav Alex

unread,
Aug 3, 2015, 2:05:24 PM8/3/15
to Lift
Hi Antonio,

Closures are the easy way yes, but under the circumstances I have a framework that I'm trying to integrate with Lift and I don't want to have to pass requests around all the time if it's avoidable. Sounds like it may not be though from what you are suggesting, I'm just trying to mask away framework internals and offer consistent interface of the framework across multiple web frameworks, and getting a reference to the Current request with ease would have been highly convenient.

Regards,

Antonio Salazar Cardozo

unread,
Aug 3, 2015, 7:15:34 PM8/3/15
to Lift
The problem is the “current request” from a thread other than the request thread isn't
really a meaningful thing. Say three simultaneous requests come in and the same code
runs for all three in three background threads—how would you figure out which current
request each one needs? Lift uses thread-locals so that code running in the request thread
can get to the current request without any additional plumbing, but it leans on the knowledge
that anything running in the request thread can only be referring to that request. As soon
as that guarantee ends, it becomes impossible to provide global-ish access to the “current”
request.

Hope that clarifies a little bit why it would be difficult for these to be implemented without
thread locality. If you have an idea on how we could improve that, I know I'd be interested—
it's not necessarily the most common use case, but could yield some interesting results.
Thanks,
Antonio

Flav Alex

unread,
Aug 5, 2015, 3:32:59 AM8/5/15
to Lift
Hi Andreak,

Many thanks for your suggestion, that does indeed look right however I am not able to find RequestVar.generateSnapshotRestorer[T]. Do you have a Gist or anything with a working example? Maybe we are using different Lift versions or something, I'm on 3.0-M2.

I would be very grateful for a simple working example to point me in the right direction.

Many thanks!

Andreas Joseph Krogh

unread,
Aug 5, 2015, 4:25:06 AM8/5/15
to lif...@googlegroups.com
På onsdag 05. august 2015 kl. 09:32:59, skrev Flav Alex <alexandru...@gmail.com>:
Hi Andreak,

Many thanks for your suggestion, that does indeed look right however I am not able to find RequestVar.generateSnapshotRestorer[T]. Do you have a Gist or anything with a working example? Maybe we are using different Lift versions or something, I'm on 3.0-M2.

I would be very grateful for a simple working example to point me in the right direction.

Many thanks!
 
You need a request-var for it to work.
 
Here's some code we use (simplified as this func doesn't do anything meaningful)
Note that the T in RequestVar[T] and generateSnapshotRestorer[T] are unrelated so they may represent two unrelated types. Both being () => JsCmd in the example below is just coincidence.
 
object DrusVar extends RequestVar[() => JsCmd](() => Noop)
val snapshotRestorer = DrusVar.generateSnapshotRestorer[() => JsCmd]()

DrusVar.set(() => Alert("No memoize set"))

val func = () => {
   val snapshotted = snapshotRestorer(() => DrusVar.get)
   DrusVar.set(snapshotted)
}

val funcMapKey = S.fmapFunc(func)(key => key + "=_")
 
Here funcMapKey may be appended to a URL (pointing to a Lift-page) so that the function "func" run on the "next page" is run in the RequestVar context of the previous page.
Reply all
Reply to author
Forward
0 new messages