[erlang-questions] advice needed: cleanup after a timeout (using gproc?)

Paul Rubin paul@REDACTED
Fri Jul 19 23:31:58 CEST 2013

I'm running a server that does something sort of similar to inetd.  It sits
there quietly until a client connection arrives on a certain socket, at
which point it starts up a service which handles client requests.  Starting
the service involves spinning up external database connections and some
other slightly expensive things.  While the service is running, more client
connections (potentially a lot of them arriving very fast) can come and
go.  When the last client connection closes, I'd like to keep the service
running for another minute or so (to avoid having to restart if new
connections arrive soon afterwards), then shut it off if things have stayed
quiet.  The 1 minute doesn't have to be precise: let's say anything between
1 and 5 minutes is fine.  There will actually be a lot of similar but
separate instances of these services, i.e. there will be maybe a dozen
active and a few thousand idle at any given moment.  Expecting clients to
update some global state before exiting isn't good, since per Erlang
tradition, they might crash ungracefully.

My thought is to use a gproc aggregated counter to track the number of
client connections.  Each new connection spawns a gen_server whose init
increments the counter by 1, and the counter automatically decrements when
the process terminates (through a monitor in the gproc server, I guess).  I
don't see an obvious way for my application to detect when the counter
reaches zero.  I can have a separate process waking up once a minute and
checking the counts, but that doesn't say that a count has stayed zero for
a full minute.  E.g. the count can reach zero at time T, then some
connections arrive and quickly exit, so the count is again zero at time
T+60.  I suppose I could update a timestamp in some ETS table whenever a
connection arrives, but that doesn't seem in Erlang's mutation-avoiding

Another idea is to add "zero-crossing detection" to gproc itself, but
before I ask Ulf whether he'd accept such a patch, I thought I'd ask here
if the idea is repulsive and if there are easier ways (it seems to me like
a pattern potentially common enough to be useful).  The notion is to pass
gproc a callback ({M,F,A}) to associate with the counter key, that would
get called whenever the aggregated count changes from zero to nonzero or
the reverse.  Then I'd supply a callback that starts a timer when the
counter reaches zero, and cancels it if the counter becomes nonzero again
before the timer expires.  I guess it would be ok for zero crossing to use
gproc:send despite the message passing overhead.

It looks like I can *almost* do this with the conditional publication stuff
in gproc_ps.  But I'd need a way to generate events when an aggregated
counter changes value, and the publish condition would have to know the
internal ETS table representation of the aggregated counter, which doesn't
seem good.

Thanks for any thoughts.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20130719/266e1e4d/attachment.htm>

More information about the erlang-questions mailing list