Hi folks,<br><br>YC's topic titled gen_server vs gen_fsm got me wondering<br><br>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.
<br><br>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)
<br><br>in our case, the duration of a transaction can be months. <br>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).<br><br>aside from that, there's a natural state progression for an order on an exchange, they tend to have states that go from:
<br>new -> confirmed -> partial_fill -> filled<br>(and canceled, expired, etc depending on what really happens).<br><br>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.
<br><br><br>so basically, the idea is (just looking for confirmation):<br>Current State: confirmed<br><br>confirmed(FillEvent,StateData) -> signal_done, {done,DoneStateData};<br>confirmed(PartialFillEvent,StateData) -> {partial_fill,UpdatedStateData}.
<br><br>partial_fill(FillEvent,StateData) -> signal_done(), {done,DoneStateData}.<br><br>something to that effect.<br><br>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.
<br><br>Am I on the right track?<br><br>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?
<br><br>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.<br>
<br>in the OTP world, what is the equivalent to this?<br>meaning:<br>SomeProcessThatSendsAnEvent:<br><br>OrderHandlerPID ! MessageToProcess.<br><br>OrderHandler<br> receive<br> Msg -> start_doing_stuff(), crash().
<br><br>it seems like the only way to guarantee delivery is to make everything Request/Response synchronized. <br>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.
<br><br>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.
<br><br>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.
<br><br>it's almost as though what I really need is to use mnesia as my message bus<br>so the "consumer" will do a select, process and submit an update. This only works if mnesia supports operations similar to:
<br>begin tx<br>insert (response values) in to msg table<br>update (request row with DONE status) table where (request row) exists %% or delete the row, either way<br>commit<br><br>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.
<br><br>I'm basically trying to figure out if there's something similar to the<br>Once And Only Once delivery semantic you get with JMS, or if you have to be willing to take a message loss.<br><br>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.
<br><br>Is this type of thing just not what erlang is meant for? Or am I just missing the super_duper_jms_like module?<br><br><br>-David<br><br><br>