Conditionally Ignoring Messages

Hypothetical Labs - kevin - February 16, 2009

This week I had a need to be able to put a gen_server into maintenance mode where it would temporarily ignore certain messages. I was able to use pattern matching and gen_server’s message handling to implement a simple and, I think, pretty elegant solution.

First, I added an element to the server’s state record to serve as a maintenance mode flag:

-record(state,
        {in_maint=false}).

Next, I added client and server-side functions to handle starting and ending maintenance mode:

%% Client API
start_maint(ServerPid) ->
  gen_server:call(ServerPid, start_maint).
%% Matching message handler
handle_call(start_maint, _From, State) ->
  {reply, ok, State#state{in_maint=true}};
%% Client API
end_maint(ServerPid) ->
  gen_server:call(ServerPid, end_maint).
%% Matching message handler
handle_call(end_maint, _From, State) ->
  {reply, ok, State#state{in_maint=false}};

These functions allow my client code to put the server into and take it out of maintenance mode. The final bit was to add a handle function which matches all call-style messages, ie messages sent via gen_server:call/2, but only when the server is in maintanence mode.

handle_call(_, _From, State) when State#state.in_maint =:= true ->
  {reply, {error, maintenance}, State};

The function intercepts messages and returns the tuple {error, maintenance} until the server is available again. The function comes after the two start/stop maintenance handlers and before any other handle_call/3 functions. Working out why is left as an exercise to the reader :)

Notice the guard for this function matches on the server’s state. It’s the guard which allows this function to be called only when the server is in maintenance mode. The rest of the function declaration matches all messages sent to the server via “_”  so I’m guaranteed this function will be called for messages, too.

Complete code for a module illustrating this technique can be found here.



Categories: Blogs  Hypothetical Labs  

Comments

No comments so far, you could be the first.

Add comment

Name:

Email:

URL:

Smileys

Remember my personal information

Notify me of follow-up comments?