[erlang-questions] Additional question regarding: gen_server vs gen_fsm

David Budworth dbudworth@REDACTED
Wed Oct 10 03:27:59 CEST 2007


Hi folks,

YC's topic titled gen_server vs gen_fsm got me wondering

Note for the reader: Sorry, just realized this is really long, but I'm
really curious as to how/if this can be solved.  The last 3/4 of this is
more bouncing ideas off people.

I'm investigating writing an order routing system using erlang and can
imagine a few different ways to deal with it (also an erlang newbie)

in our case, the duration of a transaction can be months.
So I'm assuming we really do need to persist state via mnesia (which I'll
bug people about in upcoming messages, I'm sure).

aside from that, there's a natural state progression for an order on an
exchange, they tend to have states that go from:
new -> confirmed -> partial_fill -> filled
(and canceled, expired, etc depending on what really happens).

At first glance of gen_fsm vs gen_server, it seems like gen_fsm is really a
fancyish tracking mechanism built on top of (or really similar to)
gen_server to keep state transition plumbing out of the 'business logic'
area.


so basically, the idea is (just looking for confirmation):
Current State: confirmed

confirmed(FillEvent,StateData) -> signal_done, {done,DoneStateData};
confirmed(PartialFillEvent,StateData) -> {partial_fill,UpdatedStateData}.

partial_fill(FillEvent,StateData) -> signal_done(), {done,DoneStateData}.

something to that effect.

so the question is, it seems like I'd have to manually persist "StateData"
on each event handled to survive process/host failures and basically when
detecting a process failure I'd have to spawn a new gen_fsm and register it
(say with order id or something) passing in the most recently persisted
state.

Am I on the right track?

I guess the only thing odd here, or rather, what I'm not entirely sure how
it's handled is that with everything happening async in general, how does
one guarantee that a message isn't lost while in transit and a host fails?

coming from the JMS world, you receive a message in a TX, then do your work,
publish a new message in that TX then commit.  If you die in the middle, the
message is re-delivered to another listener sitting there.

in the OTP world, what is the equivalent to this?
meaning:
SomeProcessThatSendsAnEvent:

OrderHandlerPID ! MessageToProcess.

OrderHandler
   receive
     Msg ->  start_doing_stuff(), crash().

it seems like the only way to guarantee delivery is to make everything
Request/Response synchronized.
so you send a message then wait for an ack.  And if it doesn't come, you
lookup/respawn/whatever a pid to re-send to until it succeeds.

So if a process takes a long time, I'm blocking the sender.   Whereas in JMS
(or JavaSpaces really) I know that if I send a message, that the message
broker will Never(tm) lose the message and it will eventually be handled.

Only way I see to make fast senders and reliable delivery would be to send a
message to an intermediate process that persists/replicates to a buddy, and
have the consumers send "Message Consume Requests" to that same intermediate
process which will deliver the message and mark/delete it (still with a race
condition since I may have deleted before sending or sent before deleting)
giving me dups.

it's almost as though what I really need is to use mnesia as my message bus
so the "consumer" will do a select, process and submit an update.  This only
works if mnesia supports operations similar to:
begin tx
insert (response values) in to msg table
update (request row with DONE status) table where (request row) exists %% or
delete the row, either way
commit

so I can put the response back if and only if I'm the first to mark it
done.  This is in the event that 2 consumers attempt to process the same
message.

I'm basically trying to figure out if there's something similar to the
Once And Only Once delivery semantic you get with JMS, or if you have to be
willing to take a message loss.

now, our current stuff is all java based, and I'm expecting to use (haven't
tried yet) JInterface to bridge the gap between our java stuff and new
erlang stuff.

Is this type of thing just not what erlang is meant for?  Or am I just
missing the super_duper_jms_like module?


-David
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20071009/70781911/attachment.htm>


More information about the erlang-questions mailing list