**Thanks to Chandrashekhar who in the comments pointed out I could use mnesia:dirty_update_counter to do pretty much the same thing, I didn't know about this function but it looks perfect**
For a project I am working on I need to have a sequence number assigned to each record in an mnesia table. This is fairly simple in most databases but mnesia doesn't provide this option. The reason I need this number isn't just to be used as a unique identifier, if that was all I need there are other techniques that would make more sense in erlang like using a combination of the node() id and a timestamp: {node(), now()}.
I need the sequential number so I can perform reporting on the table and keep track of the last record I processed, so I needed the number to be sequential and easy to query on. (I wanted to avoid date parsing)
So I decided to build a very simple little gen_server, and since it is very self-contained, I decided to release it out on github. Hopefully someone else will find it useful and if nothing else its a good example of working with mnesia and writing a gen_server. (at least I hope its a good example, please let me know if there is something I could improve)
Using the server is dead simple:
Sequence = sequence_server:get_sequence(impression)
When you call get_sequence you pass it either a string or an atom and based on that value the server will return the next Id. If this is the first time you are passing in the atom or string then it will create a new record for that value and return 1.
Here is the meat of the server:
F = fun() ->
Return = mnesia:read(sequence, Id, write),
case Return of
[S] ->
Seq = S#sequence.sequence,
New = S#sequence{sequence = Seq + 1},
mnesia:write(New),
Seq;
[] ->
SequenceRecord = #sequence{id = Id, sequence = 2},
mnesia:write(SequenceRecord),
1
end
end,
{atomic, Seq} = mnesia:transaction(F),
The first line reads from the Mnesia table and gets a write lock. The first part of the case statement is if a record is found for this atom or string value in that case it increments the value, writes it back to the table, and returns it. The second part of the case statement is if there is no record, in which case it creates a new record and returns the number 1.
You can check out the full source code here.
-James