Add LiftSession.onFunctionOwnersRemoved.#1709
Conversation
These functions are invoked with the set of function owners that had all of their remaining associated functions evicted from a session in a given run. A function owner is typically a page’s RenderVersion, though there are cases (e.g., comets) where this is not necessarily the case.
|
Cool! |
0.13.5 seems to be having alllll sorts of issues.
|
My thoughts was that one could, in a Snippet or comet, register a function for the given S.renderVersion, kind of like this: and that S.registerFunctionOwnersRemoved used S.renderVersion behind the scenes and sent that as the argument in to the registered function. When the function is executed it must also be removed from the list of registered functions, or else we accumulate lots of these and leak memory. I see that onFunctionOwnersRemoved has the following signature: Can you elaborate on how you think this should be used? Thanks! |
|
This is basically a lower-level version of that, and leaves management of which render versions to watch to the implementing function. Basic use: // Boot.scala
LiftSession.onFunctionOwnersRemoved ::= { removedOwners =>
println(removedOwners) // prints all owners who were removed for any session, when it happens
}The key here is that not all owners are render versions, and some owners have session lifetime. For example, inside a comet, function ownership is a little stranger, from my brief investigation while I did this work. Functions bound in comets may have session lifetime unless you explicitly instruct otherwise, if I'm not mistaken. The most straightforward way of achieving the thing you want to with the above API is: object pageIdWatchers extends java.util.concurrent.ConcurrentHashMap[String,()=>Unit]
// Boot.scala
LiftSession.onFunctionOwnersRemoved ::= { removedOwners =>
for {
owner <- removedOwners
watcher <- Option(pageIdWatchers.get(owner))
} yield {
watcher()
}
}
// ...
// snippet
def cleanupPage = {
cachedThingies.foreach(_.remove)
}
pageIdWatchers.put(S.renderVersion, cleanupPage) |
|
Cool, I'll try it out later. |
|
This is what I ended up with: object pageIdWatchers extends java.util.concurrent.ConcurrentHashMap[String,List[()=>Unit]] {
def addCleanupFunc(func: () => Unit): Unit = {
put(S.renderVersion, List(func) ::: pageIdWatchers.getOrDefault(S.renderVersion, Nil))
}
}In Boot: LiftSession.onFunctionOwnersRemoved ::= { removedOwners =>
for {
owner <- removedOwners
watcher <- Option(pageIdWatchers.get(owner))} {
watcher.foreach(_())
pageIdWatchers.remove(owner)
}
}In my snippet: def cleanupPage(): Unit = {
println(s"Running cleanupPage for ${S.renderVersion}.")
}
println(s"Adding cleanupFunc for ${S.renderVersion}")
pageIdWatchers.addCleanupFunc(cleanupPage)AFAICS this fully solves my use-case, thanks! |
|
A piece of advice to that: I would make That said, rock on! Another thing worth noting: I'm not sure what We'll give this a couple of days for feedback and then merge it into master, I think! |
|
As a developer might call In Comet S.renderVersion returns |
|
After testing more from CometActors, which doesn't bind AJAX-funcs using S.renderVersion, I found out that the AJAX-funcs' owner is the CometActor.uniqueId, so this is a better suited implementation for object pageIdWatchers extends java.util.concurrent.ConcurrentHashMap[String,List[()=>Unit]] {
def addCleanupFunc(func: () => Unit): Unit = {
S.currentCometActor.map(_.uniqueId).orElse(S.request.map(_ => S.renderVersion)).foreach(functionOwner =>
put(functionOwner, List(func) ::: pageIdWatchers.getOrDefault(functionOwner, Nil))
)
}
} |
|
Sweet, sounds good. I'm going to put a note on the relevant ML thread about all of this, it'd be cool if you mentioned your implementation of |
|
Thanks, I will. |
|
Merge-time? |
|
Yep yep, thanks for the reminder :) |
Add LiftSession.onFunctionOwnersRemoved.
These functions are invoked with the set of function owners that had
all of their remaining associated functions evicted from a session in a
given run. A function owner is typically a page’s RenderVersion, though
there are cases (e.g., comets) where this is not necessarily the case.
As a sample usage:
object pageIdWatchers extends java.util.concurrent.ConcurrentHashMap[String,List[()=>Unit]] {
def addCleanupFunc(func: () => Unit): Unit = {
put(S.renderVersion, List(func) ::: pageIdWatchers.getOrDefault(S.renderVersion, Nil))
}
}
In Boot:
LiftSession.onFunctionOwnersRemoved ::= { removedOwners =>
for {
owner <- removedOwners
watcher <- Option(pageIdWatchers.get(owner))} {
watcher.foreach(_())
pageIdWatchers.remove(owner)
}
}
In a snippet:
def cleanupPage(): Unit = {
println(s"Running cleanupPage for ${S.renderVersion}.")
}
println(s"Adding cleanupFunc for ${S.renderVersion}")
pageIdWatchers.addCleanupFunc(cleanupPage)
These functions are invoked with the set of function owners that had
all of their remaining associated functions evicted from a session in a
given run. A function owner is typically a page’s RenderVersion, though
there are cases (e.g., comets) where this is not necessarily the case.
@andreak have a first look and see what you think!