We have talked about making UnitOfWork more eventoriented, and indeed, the basic idea of a UnitOfWork is to create a "work log". But, this is not how it has been implemented so far. Instead a UoW has loaded snapshots (EntityState), updated those snapshots, and then sent them back to the EntityStore, but without any information about what happened. I have now realized that this is bad, for all sorts of reasons.

Here's what I suggest we do: on the EntityStore we create this method:
EntityStoreUnitOfWork newUnitOfWork()

This creates a new change tracker, and it is also from this that the UnitOfWork acquires EntityState's. This methods is called once for every EntityStore, for every UnitOfWork that needs it. The newEntityState/getEntityState methods are moved to EntityStoreUnitOfWork.

When EntityStates are updated, by calling setProperty/setAssociation/manyAssociationState.add etc. these changes are tracked in the EntityStoreUnitOfWork as events. The ESUOW in this way creates a series of UnitOfWorkChanges, which is kept internally.

The ESUOW can also optionally track read-events. This would help ensure that when the command is written we can check that the read state has not changed.

When the UnitOfWork commits the ESUOW is sent to the prepare() method of EntityStore, which hence changes to:
void prepare(EntityStoreUnitOfWork uow);

The implementation of ESUOW is custom for the EntityStore, and so the EntityStore can internally cast it to potentially get more information. Extra information that the EntityStore might want to keep includes the id of the UnitOfWork, the name of the Usecase, meta information from the UoW and Usecase, etc.

For transaction-wrapped UnitOfWorks (i.e. a transaction is created outside of the UnitOfWork), this abstraction also makes it possible for the EntityStore to keep the transaction reference in the ESUOW (Neo4j, I'm talking about you!).

Another possibility is that this makes it easier to do lazy-loading of state. So even if you have acquired an EntityState the actual state might not yet have been loaded from the underlying store.

It also makes it possible to do copy-on-write EntityStates, which could improve performance a LOT in read-intensive cases (i.e. load and cache one shared EntityState per identity.

Continued in part 3.

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

Reply via email to