When using Coldfusion Sessions, FusionReactor rare...
# fusion-reactor
t
When using Coldfusion Sessions, FusionReactor rarely ever shows any as destroyed. The created count just seems to climb infinitely. I do have a long session time, but if the website visitor is not logged in, I delete the session at the end of each request. Here's the code from onRequestEnd:
Copy code
if(isNull(session.user.id)) {
    StructClear(session);
  }
Though doing this doesn't seem to end the session. Is this the official way or is there another way in Lucee to officially destroy the session in a way that FusionReactor would recognize?
b
@Tim Badolato That code is not "deleting" the session. It's simply clearing all keys from the struct. Use
sessionInvalidate()
to remove it
a
You could perhaps benefit from reading this - https://blog.adamcameron.me/2012/07/difference-between-events-and-event.html - re the difference between events and event handlers. Clearing the session scope is just that: clearing the session scope. It has nothing to do with the user's session, other than removing the data you had associated with said session.
sessionInvalidate
might help you - https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-s/sessioninvalidate.html - but there are some caveats as mentioned in the docs. I think on the whole keep yer session timeout short, and on any docs that the user might naturally idle on for a long time, ping back to the server periodically to keep their session alive. Or just let it timeout and have them reauthenticate and take them back to the same URL afterwards. Don't forget the sessiontimeout resets every request. Often ppl don't need as long a session timeout as they might think
b
I would recommend a shorter timeout. The session will stay alive so long as there is activity by that user.
a
haha, @bdw429s... snap.
😜 1
b
Also, check out external sessions stored in a cache or a DB. Lucee makes this pretty easy and • they persist across CF restarts • are shared between servers • don't consume as much heap
t
Thanks Brad/Adam! I had no idea about sessionInvalidate
šŸ‘ 1
I've considered moving sessions to the DB. But it's hard to give up the lightening fast memory access. Every request also checks the session. Wouldn't this require constantly hitting the DB?
a
See also:
applicationStop
instead of calling
onApplicationStart
, thinking that has anything to do with restarting the application. Another thing that ppl often get confused about.
b
Wouldn't this require constantly hitting the DB?
Not necessarily. It depends on whether you set
sessionCluster
to true or false šŸ™‚
It is a trade off, but a Redis call or a DB call can only be a few seconds depending on the amount of data. So it's a trade off if the burden of a large number of sessions is too much. I wouldn't assume external sessions are slow without testing it
šŸ‘ 1
a
Yeah I'd consider it premature optimisation to worry about it before testing. But def good to flag it up as a consideration though. So, like, do test it.
āœ… 1
t
Using
sessionInvalidate
in production but I'm still not seeing any destroyed sessions. šŸ¤”
a
Are you logging something in
onSessionEnd
so as to gauge how many destroyed sessions you'd be expecting to see?
t
sessionInvalidate
doesn't seem to be triggering
onSessionEnd
At least in my tests
b
That's too bad. A peek at the bug tracker reveals these two related tickets: https://luceeserver.atlassian.net/browse/LDEV-4166 https://luceeserver.atlassian.net/browse/LDEV-3248
t
Is this why FusionReactor isn't tracking destroyed sessions?
b
ĀÆ\_(惄)_/ĀÆ
šŸ˜… 1
I've not looked at Lucee's implementation of that BIF to know what it does. It may destroy the data in the session but leave the session container itself in memory. Anything is possible
I believe setting the sessionTimeout to 0 on a request is also touted at ending it. but I've never tested with FR's session tracking to know if FR tracks it actually going away or not.
a
Yeah just tested on Lucee and
sessionInvalidate
doesn't work. It... erm... does... on CF. Sorry for the bum steer there Tim.
😢 1
t
All good! Glad it's not just me šŸ˜…
b
Do try the timeout=0 trick. You should be able to conditionally do
Copy code
this.sessionTimeout=0;
in
Application.cfc
OR
Copy code
application action="update" sessionTimeout=0;
anywhere in your code. (which despite its appearance, will only affect the current request) And like Zac said in the channel, Lucee clears dead scopes async after a minute or so.
a
setting the
sessiontimeout
to
0
has odd behaviour on Lucee. I'm passing a URL param
sessionTimeoutSeconds
which I use thus:
Copy code
this.sessionTimeout = createTimespan(0, 0, 0, URL.sessionTimeoutSeconds)
I then make a request with that as default, then one with that
0
, and then a third with default. The first req starts a session. The third req starts a new session, and
onSessionEnd
is only ever called for that second session (identifying different sessions via
sessionId
). The session end doesn't seem to respect the timeout. I've run it a coupla times, and it seems to be called "within a minute" of when it was supposed to run.
(For the record, CF really does not like the
sessiontimeout
being set to zero. It seems to kill the session, but not start a new one before running
onRequestStart
:-S )
I get
Element SESSIONID is undefined in SESSION.
in
onRequestStart
for the req setting the timeout to
0
. Unless
0
means "disable sessions"? Which... erm... is not the same as setting the timeout to zero, but hey... is this at all surprising?
I guess your "Lucee clears dead scopes async after a minute or so" comment, @bdw429s explains the delay in running
onSessionEnd
. Not as good as it could be, but... I can see why.
b
Yeah, it's part of the controller thread
āœ… 1
a
b
One rather oddball part of that is when the session is created, Lucee stores the actual Application.cfc instance along with the session to call the
onSessionEnd()
method later since that happens outside of any web context
a
If I knew the correct jargon to use I'd update it, but... only got the vernacular version from you, so will leave it.
I could at least put "this might not happen for a minute or so after the session expiry due to how Lucee manages session tidy-up"? Does that sound too rubbish?
b
Seems ok to me
a
done.
šŸ‘ 1
Lucee stores the actual Application.cfc instance
Is that in case the handler needs any app settings or anything? Does seem... egregious.
I don't have a very good picture of what's going on, I guess.
b
I've assumed it was because the controller thread didn't have the information needed to know how to create the CFC later. I mean, it seems like that would be possible, and even easy, but what do I know.
āœ… 1
šŸ‘† Details
a
šŸ‘€
@Tim Badolato should read that too.
b
The thing about it that bit my client was that ALL VARIABLES from the app cfc's pseudoconstructor were kept in memory forever.
a
shit so... if like using
onRequest
then that could be a fuck-load of variables?
b
Potentially, yes
Variables which devs would have a reasonable expectation wouldn't live past the first request.
āœ… 1
a
that ain't good.
And when you say 5.3.7 specifically... ought we infer from that that in like 5.3.6 it didn't do that?
that is fuckin terrible!
isn't it?
b
I'm fairly sure 5.3.7 was simply the version my client was on. I assume Lucee's done that prior as well
a
gotcha
d
Am I right that none of this happens in reasonably current ACF? It's a Lucee-only entertainment? And once again gents, much appreciation for the digging and grokking. You keep the whole thing spinning:
a
CF behaved as I would expect with
sessionInvalidate
.
šŸ‘ 1
(CF2021)
The last version of the code I was using - checking the zero-ing-out of the
sessionTimeout
is here: https://github.com/adamcameron/cfml/tree/session_ivalidate/cfmlLanguage/scopes/session/invalidate
to test the
sessionInvalidate
stuff, uncomment it from
invalidate.cfm
a
I had an ave of about 50k sessions largely from bots until recently. I added something like this in app.cfc pseudo constructor. Setting it to zero didn't work for me
Copy code
if ( (variables.browserInfo.isBot)  &&! variables.sentCookie ) {this.sessionTimeout = createTimespan(0,0,0,5);
and session creation and destruction looks like this now after say a week of uptime. (IOW sessions stay under control).... should add that I am no expert on this, just that it has been working on 4 nodes for a month or so with no issues. (Lucee, 5.3.10)