The delete flag in the DB could be null or the date the delete was requested. You could batch the commit cleanup hourly giving a delete at least X hours before it's committed.
It depends on how you interpret “delete”. Most people seem to want to make it synonymous with “erase”, but it should really mean something like “forget”. In that case, it’s easy to see how you would implement “undo”: just drop all (root) references to the record(s) in question and collect as garbage at a certain time (in, say, 30 days).
Another standard way is with the command pattern, and using one "undo" stack, with another "redo stack". When you perform a command, a command object is pushed onto the "undo" stack. When you undo a command, it's popped off the stack, its undo() method is called, and it's pushed onto the "redo" stack. When you redo a command, it's popped off the redo stack, and executed. When you execute a new command (not an undo or redo) you push it onto the undo stack and clear out the redo stack.
There actually is another way. Event-Sourcing. I've never seen this technique in my limited experience though, but theoretically this would be the optimal way to implement such a feature, and obviously has to be a engineering decision from the get-go.
Alternatively you could also have a very primitive form of version control : recycle-bin (edit: actually this is the same as point 1 =) )
"Similarly, Joseph Gentle who is an ex Google Wave engineer and an author of the Share.JS library wrote: Unfortunately, implementing OT sucks. There's a million algorithms with different tradeoffs, mostly trapped in academic papers. The algorithms are really hard and time consuming to implement correctly. ... Wave took 2 years to write and if we rewrote it today, it would take almost as long to write a second time."
A useful analogy might be how accounting ledgers work. You never really delete anything; you just keep appending records saying what you've done. The balance is just the sum of all those operations. (Ledgers are a bit special in that usually all the operations in a ledger are commutative (+/-), but other than that it seems a pretty good analogy.)
First you start treating each event/operation as a fundamental part of your problem. Each Event can then have a opposite reverting Event. So if you want to reverse an action, you can just apply the opposite event. You can also display a list of recent events that have taken place easily:
- user X modified article Z
- user Y deleted article Z (revert?)
Note that I've only studied this in passing, and have never applied this in practice, so I can't answer just how effective this could be. Also not really sure how this works when other actions have already taken place, or how you can detect if an event cannot be recovered from (if there is such a thing).
I can think of two ways to implement undo.
1. Use flags in the database, this method has its own drawback since the entry is not really deleted but flagged as one.
2. Client side. Delay the actual delete request to the server.