CommandExecutionRuntimeException

This is a rough rendering of a page from the old Prevayler wiki. Please see the new wiki for current documentation.

When a RuntimeException is thrown during the execution of a command, the prevalent system enters an undefined, potentially inconsistent state.

"You will now have the means to actually write server code. It is the way object orientation was intended all along; but it is certainly not for wimps." -- PrevalenceSkepticalFAQ

It is clear that the quality requirements for prevalent server code are much higher that those for flaky client code. Although RuntimeExceptions are expected to be extremely rare, we must have some way of dealing with them.

KlausWuestefeld


A few directions some people started to explore:
#Using rollbackable "variables" and collections. See RollbackSupport.
#Halting all commands and queries while Prevayler recovers the last snapshot an applies the commands.

The first idea would be almost like using an OODBMS. The main impacts will be on simplicity, transparency and performance.

The second idea would have an impact on availability, unacceptable for many systems.

More ideas? -- KlausWuestefeld


This morning, while I was in the bathroom, a possible solution to this problem was given to me.

Basically, we can apply each command to the replicas only after it has executed successfully in the "hot" system, without throwing a RuntimeException. When a RuntimeException occurs, the "hot" system restarts and the replica takes over.

Of course, you will still have the same availability problem (waiting for restart) if your code throws so many RuntimeExceptions that your replicas cannot keep up.

Every RuntimeException will still have a cost but, it is no longer required that your code be 100% RuntimeException free. @;) -- KlausWuestefeld



Could a similar technique be used to maintain availability during a snapshot?

I think the whole RuntimeException argument boils down to the problem of HighAvailability. Where an RDBMS uses specialized hardware, limited operations, and rollback to get HighAvailablity, Prevayler uses redundancy, assuming the occasional crash is inevitable.

DarrinThompson



It looks like a forced solution to a problem wich could have a simplier one. Transactions are not something we must be afraid of! Sometime ago, Klaus and I, after a huge discussion on prevayler list (the portuguese one), agreed that prevayler in fact has transactions, but in a very special way. So my point is:

1)How does prevayler deal with a command that was written to disk and during its execution a RuntimeError (out of memory, Esgrinphos atacked, ...) occurs?
By your solution the replica server would not be aware of this command and therefore, prevayler would reestart and be doomed to restart ab aeterno, because the client would resend the command again and again since the error is not his.

2) What is the big deal with creating a Transaction class that each instance of it is treated exactly as a command, and therefore when a exception occurs all it's done is wiped?

EmilioFrancesquini

PS. Please try to convince me, but so far I don't think the absense of transactions is a marvelous thing as you preach



Some thoughts:

I thought reading some specifics would be helpful. So I checked the Javadocs for JDK 1.4 and looked up RuntimeException. The list of classes that extend it is disconcerting. Looks like a lot of stuff that really could happen, and really could doom a prevayler cluster.

Maybe that's Java's way of saying "Yes, there are bad commands."

What if we do what Klaus suggested but not actually pass the command on to replicas until it's safe?

[oops duh, that's what he said.]

Wouldn't a network protocol tell the client that the command it sent was bad? I don't think that anything but a malicious client would retry after it was told that it's command was rejected for a "RuntimeException" reason.

I like Klaus' idea because it's provably correct. The only problem with it is that it opens up a method for attack by a malicious client sending a lot of bad commands. I don't want to implement "undo" methods because I know I would sooner or later mess one up. That opens up the possiblity for the system to go into an inconsistent state silently.

DarrinThompson


Prevayler does have transactions, as Emílio ponted out, and as we can read from the TheFAQ (DontINeedTransactions?):

"In the prevalent design, every transaction is represented as a serializable object which is atomically written to the queue (a simple log file) and processed by the system. An object, or object graph, is enough to encapsulate the complexity of any business transaction."

What Prevayler does not have is:
#RollbackSupport
#DoItYourselfTransactions
I have, therefore, moved the discussion that was in TransactionSupport to RollbackSupport.

KlausWuestefeld