Having a message driven bean 'fire' as the result of two events? - ejb-3.1

I would like to have an MDB that fires only after two independent states have been reached. For example:
Event A occurs
some time passes
Event B occurs
MDB onMessage is called as a result of both A and B event occurring
A and B events are cleared
So for example if Event B occurs but Event A has not occurred then I do not want the onMessage triggered. Similarly if Event A occurs but Event B has not occurred I do not want the onMessage to fire. I also want Event A and B to be correlated such that when onMessage is fired Events A and B are cleared.
One way to do this would be to have Event A produce a message and the message handler for that would check to see if Event B has occurred but it would have to block and loop until an Event B had fired. The polling scheme seems inefficient.
Functionally this would act like a CyclicBarrier but implemented with messaging.
Any thoughts as to whether or not something like this is possible with MDBs?

There is no builtin mechanism for this. I would recommend storing incremental state in a DB table (insert when the first event is received, update/delete when the second event is received).
I would definitely not recommend polling; there are far too many things that can go wrong (hung server threads, wasted CPU, transaction timeouts, etc.).

Related

How will ProcessingTimeoutTrigger in Flink work with nested Trigger which can fire on processing time?

I was looking at source code of ProcessingTimeoutTrigger which suppose to wrap any Trigger adding trigger-on-timeout functionality. I wonder how will it work with nestedTrigger that register, for example, its own Processing time timers.
According to implementation:
#Override
public TriggerResult onProcessingTime(long timestamp, W window, TriggerContext ctx) throws Exception {
TriggerResult triggerResult = this.nestedTrigger.onProcessingTime(timestamp, window, ctx);
if (shouldClearOnTimeout) {
this.clear(window, ctx);
}
return triggerResult.isPurge() ? TriggerResult.FIRE_AND_PURGE : TriggerResult.FIRE;
}
It will trigger WindowFunction no matter on nestedTrigger invocation result.
I wonder why? If this timer was registered with nestedTrigger and appears prior to the one registered with ProcessingTimeoutTrigger, why are we firing?
Same question goes to onEventTime implementation. ProcessingTimeoutTrigger does not register any eventTime timers. Which means that onEventTime will be called for a timer registered with nestedTrigger. Why, in this case, we are always firing?
Shouldn't we somehow check if current fired timer is actually the one registered by ProcessingTimeoutTrigger? What am I missing here?
I hadn't noticed the existence of ProcessingTimeoutTrigger before, so this is just my take based on reading the code and tests and FLINK-17058 (the ticket that added this feature).
testWindowPurgingWhenInnerTriggerIsPurging tests the case that I would be worried about with a nested ProcessingTimeTrigger, which is to test that the wrapping timeout trigger is purged when the nested trigger is purged. That way if the nested trigger fires and is purged before the outer one, the outer one will be purged. And if the inner trigger fires without purging, then the outer one should remain in place.
Looks to me like onEventTime is assuming that if the nested trigger registered an event time timer, then when that timer fires the window should FIRE. That feels a bit sloppy, but in practice is very unlikely to be wrong.

Libevent - Running the loop(event_base_loop)

Tell me please, here is a quote from reference section 3 ("Running an event loop") of Nick Mathewson's book on Libevent:
By default, the event_base_loop() function runs an event_base until
there are no more events registered in it.
Honestly, I just can't understand this phrase.
What means - "until there are no more events registered".
How does a loop know that there are no more new events ?? There can be a time interval between events - 1 second, 1 hour ...
How does Libevent know that events are over?
PS: I'm trying to compare the work of the event_base_loop () function with the GetQueuedCompletionStatus () function on windows and I don't get it. Because GetQueuedCompletionStatus works in an infinite loop - whether there are events or not - GetQueuedCompletionStatus waits for an infinitely new event and does not complete if there are none.
PS1:I was in a hurry and did not finish the chapter on "Working with an event loop".
It says that you can redefine the behavior of the event_base_loop () function by passing it a flag in the second parameter - EVLOOP_NO_EXIT_ON_EMPTY.
This will mean that the function will wait for new events indefinitely or until I want to exit the event_base_loop () loop manually via event_base_loopbreak / event_base_loopexit.
Note it says "no more events registered", rather than "no more events". By default, the event loop will exit when the event base runs empty, even though more events could happen later. This is restated in a different way both later in the chapter:
Ordinarily, the loop will exit as soon as it has no pending or active events.
and in the API documentation for event_base_loop():
By default, this loop will run the event base until either there are no more pending or active events, or until something calls event_base_loopbreak() or event_base_loopexit().
As noted in the question, EVLOOP_NO_EXIT_ON_EMPTY can change this behavior to work more like a typical event queue, waiting for events (unless EVLOOP_NONBLOCK was set) and dispatching them when they arrive.
"Running an event loop" contains pseudocode for event_base_loop() that should also help clarify the behavior.
In comparison, GetQueuedCompletionStatus will wait for and operate on a single packet (note: the wait is not likely a busyloop but based on some other multitasking technologies, such as interrupts and thread synchronization primitives; the exact method is an implementation detail, and shouldn't affect use). It's most similar to event_base_loop() with the flags EVLOOP_ONCE | EVLOOP_NO_EXIT_ON_EMPTY, though event_base_loop may process multiple events of the same priority if they happen to come in before the first event is fully handled. Coming from the other direction, if 0 is passed for the dwMilliseconds argument to GetQueuedCompletionStatus, it behaves like event_base_loop()'s default behavior, exiting immediately if there are no packets in the I/O completion queue.

Why is the IContentEvents.LoadedContent event fired multiple times for a page?

I've added an event handler for the LoadedContent event. I'm a bit surprised that the event seems to fire multiple times for a page during a single load. Why does that happen?
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
ServiceLocator.Current.GetInstance<IContentEvents>().LoadedContent += this.EPiServerApplication_LoadedContent;
}
EDIT
I'm using EPiserver 8.
With "a singe load" I mean going from DOPE mode to edit mode for a page that is a child but has no children. Last time I counted the event fired 17 times for that page.
The LoadedContent event is fired every time Get/TryGet on the IContentLoader (or IContentRepository) is called. This happens regardless if the data is loaded through from the cache or from the database.
As these APIs are used by many separate code branches, especially in edit mode, this event will be triggered multiple times just as you have found. Normally this should not be anything that you need to be worried about unless of course you are doing something resource intensive in your event handler.

SQLDependency - does not fire while being busy

Is it normal behavior that a SQLDependency onchange event is not fired if its thread is too busy?
private void NotificationOnChanged(...)
{
// get database results
// simulate long process
Thread.Sleep(10000);
}
During the sleep i add a new row and the notification is lost after the sleep expires.
Must I spawn a new single thread to do the work and use a flag to detect if new notifications arrived to restart the it?
This behavior is an artifact of the implementation on the ADO.net notification listener. See http://rusanu.com/2008/01/04/sqldependencyonchange-callback-timing/.
The SqlDependency internal thread that posts the WAITFOR(RECEIVE) is not going to post another one until the callback returns. So you have to do as little processing as possible and return in the OnChange event. Definetely nothing blocking.
Alternatively you can use the lower level SqlNotificationRequest that lets you manage everyting, including the notification handling. But you'll have to manage everything. See http://technet.microsoft.com/en-us/library/ms190270(v=sql.105).aspx

Stopping the publish flow in an event or disabling the publish button

I wondering if it's possible to stop the publish flow in an event.
I want to check some properties in the code-behind before I let the user publish the object.
You can use the static DataEvents<T> class which has a OnStoreChanged event you can hook into.
Example use from the api page:
DataEvents<IMyDataType>.OnStoreChanged += new StoreEventHandler(DataEvents_OnStoreChanged);
...
void DataEvents_OnStoreChanged(object sender, StoreEventArgs storeEventArgs)
{
if (!storeEventArgs.DataEventsFired)
{
// an external update event happened - DataEvents_OnBeforeAdd not fired
// here a complete cache flush could be done
}
}
If you care about page publishing you would have to use DataEvents<IPage> and check the StoreEventArgs for the PublicationScope which should tell you whether this was a publishing event or not.
From the documentation of DataEvents<T>.OnStoreChanged:
This event is fired after changes has happened to the Composite C1 data store. This may be atomic actions or a larger change to the underlying data store. The StoreEventArgs class describe the change in broad terms, including a flag indicating is detailed data event have been raised or not. You can use this event as a simple way to react to data changes (like clearing a cache) or you can mix this with atomic data events (add, delete, update) to make a build a more advanced cache. You should listen to this event in order to support scale out across multiple servers, since this event is meant to be signaled when changes happen on another server. In such situations detailed data events will not fire on other machines.
If you care about exactly what data was changed in the event, you have to use the other events of the DataEvents<T>class like OnAfterUpdate and get this information from the DataEventArgs.

Resources