Hi,

I'm working on the EventSourcing library, and have a bit of trouble with the algorithm of UoW completion.

Basically, since the EventStore is my "single source of truth" I need to have it commit its events before the EntityStore is committed. That way, if the events are committed but the entities not, I can always replay the events to get the EntityStore up to date with "what really happened". Same with the index.

This is not possible right now, since the complete() algorithm looks like so:
    public void complete()
            throws UnitOfWorkCompletionException
    {
        checkOpen();

        // Copy list so that it cannot be modified during completion
List<UnitOfWorkCallback> currentCallbacks = callbacks == null ? null : new ArrayList<UnitOfWorkCallback>( callbacks );

        // Check callbacks
        notifyBeforeCompletion( currentCallbacks );

        // Commit state to EntityStores
        List<StateCommitter> committers = applyChanges();

        // Commit all changes
        for (StateCommitter committer : committers)
        {
            committer.commit();
        }

        close();

        // Call callbacks
        notifyAfterCompletion( currentCallbacks, COMPLETED );

        callbacks = currentCallbacks;
    }
----
The EntityStore needs to do two things: check for concurrency errors and store state. Concurrency checks happen in applyChanges() as it is now, and then state is committed on commit(). But since notifyBeforeCompletion() happens before applyChanges() I can't store events there, as there might be a concurrency failure from applyChanges(). So right now it happens in notifyAfterCompletion, which means that if the event-storing throws an exception there's nothing I can do to rollback the entity state. This only happens on system failures (e.g. write to disk failed), but is still an issue theoretically speaking.

So, to fix this I would suggest that notifyBeforeCompletion moves to after applyChanges, so that it can know that there won't be any concurrency exceptions later. If any callback then throws a UnitOfWorkCompletionException it would result in committer.cancel() being called on all EntityStores (which for most cases does nothing).

Is this an ok change to make, or do you see any issues with invoking callbacks after applyChanges()?

/Rickard

_______________________________________________
qi4j-dev mailing list
[email protected]
http://lists.ops4j.org/mailman/listinfo/qi4j-dev

Reply via email to