Bela and Ben,
I'd like to put forward an idea for JBoss Cache. However, first let me describe what I'm doing.
I have a distributed application that uses JBoss Cache to distribute data to all nodes. I'm using AOP for all cache access, synchronous replication, transactions with read committed locking and separate file-based cache loaders. The application is also standalone, with no application server etc.
Now, to my current problem. The application is event-driven, so when updating an object I want to send an event to my event manager on each node. The ordering of events is also important, so each local event manager should receive events in the same order.
What I'd like to propose is that the cache have the ability to associate an event with a transaction, and on commit that event will be propagated by the replication manager, and then sent to some local class via an interface. Now, ordinarily I wouldn't propose this as something that a cache should do, but with the use of AOP it becomes more important. It's ultimately AOP that allows me to write my application the way I have (and it's a great mechanism for data distribution!), but the lack of object-based event handling, as opposed to Node-based events (ie. the TreeCacheListener) is limiting.
I've had a good look through the code, and have scraped together something that works, just to demonstrate to myself that it can be done. However, obviously it needs to be discussed with you guys in order to find an appropriate way to integrate it into the current structure (or even at all, although I'm really hoping that you guys allow this to happen! :-).
Here's a rough overview of what I did to get it working.
- Add an Event attribute that has associated set() and get() methods.
- Add set() method for Event.
- An interface defining eventReceived(Event) that is called when an event is generated after commit.
- Registers a synchronisation handler in invoke() if there's a transaction.
- In afterCompletion(), if we're committing then it retrieves the event and calls EventReceiver.eventReceived(Event).
- Add set() and get() methods for the EventReceiver
- Add the EventInterceptor into the chain just before CallInterceptor. It needs to be higher
than ReplicationInterceptor so that it gets called on the remote nodes.
- In beforeCompletion(), adds the event to the argument list of the remote prepare method.
- In replicate(), extracts the event and passes it to handlePrepare().
- In handlePrepare(), sets the event into the transaction entry.
Currently I just set the event by calling TreeCache.getTransactionTable().setEvent( treeCache.getCurrentTransaction(), myEvent ). This would obviously change.
So, what are your thoughts on this whole idea? I'm happy to take this offline if you want to discuss it further, although I guess this is actually the "development" forum :-)
Note that I'm also volunteering to write all of the code for this. I'm not asking you guys to do that :-)
If this proposal is just to get aop to emit an object-based event, then I am adding a new feature in TreeCacheAop (release 1.2.2) that allows customed dynamic interceptor. You can then add an EventIntecetor after the current CacheInterceptor to intercept and emit object level event based on the field RW ops.
Will this do what you want to do?
BTW, we also have a design forum called "Design of JBossCache". We should use that one more often. :-)
I'm happy for you to move this thread to the design forum. I saw it there, but it looks, well, very under-used :-)
As for your suggestion, I'm not sure that it'll do what I'm thinking. Sending an event on a field r/w is probably too limiting. Realistically I'm after a single user-defined event per transaction. Actually, it could be multiple events per transaction, but the idea is still the same.
I guess what I really want to do is be able to push around a user-defined bit of data within the cache transaction. If I do it outside of the cache (say using JGroups directly) then I end up with potential race conditions with events being received out of order etc. I need the guarantee that the transaction provides.
Any thoughts? Do you think this change (or something like it anyway) is reasonable?
I'm not sure I understand what you want to do. Do you want to get notified when a POJO has been modified, e.g.
pojoModified(p, "age", 80) notification ?
The change is quite intrusive, so I want to see the use case first. Also, what happens if you don't use transactions ?
When TreeCacheAop detects a field R/W, the EventInterceptor will send out an event of object modified (and potentially the mod. fields), not just the field event. So this is object level event.
I am not sure if I like the idea of transaction-based event sending out from JBossCache either.