tags:

views:

266

answers:

4

I'm writing http session manager (gen_server based). That server creates and removes session from in-memory storage. I need to remove expired session on timeout. I have two solutions:

  1. Create one timer to remove expired sessions from manager
  2. Create timer for each session

First solution locks server while all sessions are not processed (lock issue). Second solution takes process for each session (memory issue).

Question is which solution is right?

Thank you!

+2  A: 

A low frequency event should be handle by a low frequency process IMO. You don't want to be "spending" too much resources on something that's not "generating" value.

The "clean-up" activity does not appear to require "locking-up" the server. Maybe you need to expand on this point.

Why do you need to "lock" something in your solution #1? What are your concerns here? Please detail your concerns a bit more so I can provide more suggestions.

jldupont
You want say the first solution makes sense. Right?
sinnus
Yes I am saying that the overall strategy of #1 is more inline with the value of the cleaning-up activity. What I don't understand is the "locking the server up".
jldupont
gen_server has State with sessions what can be created or removed with callback functions. To implement strategy #1 I will create new callback function like: handle_call({remove_expired_session} ...). When timer is calling that function, another calls will wait until remove_expired_session will be completed. It looks like lock.
sinnus
Looks more like a delay to me. At one point you'll have to do some clean-up processing no? If you are concerned about the duration of your activity in this particular process, you can always use other processes and split the job, no?
jldupont
Yeah. You right, I can split the job if clean-up routine will take a lot of time.
sinnus
+1  A: 

This is how I handle sessions in my pet "web framework".

Worker processes directly look up existing sessions and create new sessions into an ets table (without any server intervention). Also worker processes check after successful lookup if the session is dead. If so, it creates a new session, and deletes the old one. As the ets table need not be ordered, write concurrency can be enabled.

The role of the "session server" is to own the session table, and to spawn a cleanup process every now and then. This is a low prio process that goes through the ets table with ets:next() calls, and deletes expired sessions.

Note that there are no timers involved.

Zed
Why does worker process create session? In web application http request creates session.
sinnus
@Zed: this time around you are cryptic.
jldupont
By worker process I meant the process who is actually handling the http request itself. E.g. in mochiweb the one who is executing the registered loop function.
Zed
Anyway, my point is that there's no reason to use timers at all. Dead sessions do not cause extra system load or memory usage; then why bother with killing them so accurately with timers for each session?
Zed
@Zed: another part of application can depend on life cycle of session. For example, online information or messaging system based on http.
sinnus
What is the timeout value you use for your sessions?
Zed
@Zed: What do you mean?
sinnus
@sinnus: After how long inactivity do you treat a session as expired?
Zed
@Zed: It's configurable parameter. Default value is 5 minute.
sinnus
+3  A: 

Use timer:send_after, timer:exit_after or timer:kill_after. timer module uses ets for store timers and there is only one gen_server for whole VM. Store timer reference in each session record for timer restarting or so. It is simple and clean solution.

Hynek -Pichi- Vychodil
You right but each timer handler will be invoked withing new process. If many handlers are called at once, many processes will be created.
sinnus
Why use a machine gun to kill a fly?
jldupont
Sorry, send_after doesn't create process. I mean timer:apply_after function.
sinnus
A: 

You cant really go wrong with any of the suggested solutions as long as you dont have ginourmous numbers of sessions. And what im saying with that is that you should benchmark.

The timer module is implemented as an ordered ets table where ets:first can efficiently find the first timer that should expire and sleep until that happens. So there is no problem in adding many thousand timers through the timer module. One per session.

If you have very many sessions, then the problem of having a fail safe design is likely a larger issue. You would need to distribute your session database so requests can be load balanced and you're not vulnerable to any one web server machine going down.

And that is how specific I feel one can be without the functional requirements.

Christian