tags:

views:

161

answers:

2

I have a server application made in Erlang. In it I have an mnesia table that store some information on photos. In the spirit of "everything is a process" I decided to wrap that table in a gen_server module, so that the gen_server module is the only one that directly accesses the table. Querying and adding information to that table is done by sending messages to that process (which has a registered name). The idea is that there will be several client processes querying information from that table.

This works just fine, but that gen_server module has no state. Everything it requires is stored in the mnesia table. So, I wonder if a gen_server is perhaps not the best model for encapsulating that table?

Should I simply not make it a process, and instead only encapsulate the table through the functions in that module? In case of a bug in that module, that would cause the calling process to crash, which I think might be better, because it would only affect a single client, as opposed to now, when it would cause the gen_server process to crash, leaving everyone without access to the table (until the supervisor restarts it).

Any input is greatly appreciated.

+7  A: 

I guess according to Occam's razor there is no need for this gen_server to exist, especially since there is absolutely no state stored in it. Such process could be needed in situations when you need access to the table (or any other resource) to be strictly sequential (for example you might want to avoid any aborted transactions at cost of a bottleneck).

Encapsulating access to the table in a module is a good solution. It creates no additional complexity, while providing proper level of abstraction and encapsulation.

gleber
+5  A: 

I'm not sure I understand why you've decided to encapsulate a table with a process. Mnesia is designed to mediate multiple concurrent accesses to tables, both locally and distributed across a cluster.

Creating an API module that performs all the particular table access operations and updates is a good idea as the API functions will convey your intent better in the code that calls them. It will be more readable than putting the mnesia operations directly into the calling code.

An API module also gives you the option to switch from mnesia to some other storage system later if you need to. Using mnesia transactions inside your API module protects you from some programming errors as mnesia will roll-back operations that crash. The API module will always be available to callers and allows any number of callers to perform operations concurrently, whereas a gen_server based API has a point of failure, the process, that can render the API unavailable.

The only thing a gen_server based API gives you over a pure-functional API is to serialize access to the table - which is an unusual requirement and unless you specifically need it, it will be a performance killer.

archaelus