Apache ignite listening to state change of objects in local nodes - ignite

I am investigating a use case where ignite has to listen to changes of a property of an object in the data grid and do some operations on that object. For performance, I want the processing to be done on the same node where the data is.
How can I get an event when the property of a object has changed to a specific value (eg. Object 'X' has a property 'state' which is set to 'scheduled' from 'created') and make sure that only events are taken from the node where the object lives in?
How can I make sure that when I got the event and start processing it, nobody else changes the object (only read is allowed) until processing is finished (in other words, a transaction starts as soon as the event is picked up)?
How can I make sure that the processing code is deployed to all nodes (processing is stateless) and that it only operates on local data (without having a hard link between data object and code, in other words, if the processing code is updated in the future, the objects stay untouched)
What I got from the docs is the following:
// Local listener that listenes to local events.
IgnitePredicate<CacheEvent> locLsnr = evt -> {
// CODE
return result;
};
// Subscribe to specified cache events occuring on local node.
ignite.events().localListen(locLsnr,
EventType.EVT_CACHE_OBJECT_PUT);
In the CODE block; I have to check for a state change on 'evt.newValue()', can't that be done earlier? Ie. as a paremeter to localListen somehow?
In the CODE block, is the Object locked until I return the result? In other words, is it in here that I am sure nobody can changes the object and that I can safely change my Object? IMO it is a strange place to do that in a 'Predicate' definition and not in a handler class.
Sven

Sven,
Your code looks correct and should work as you expect. Answering your questions:
Event listener is called right after the value is updated, so I think it's OK to check the field you're interested in inside the listener. If the field is not changed, just return right away.
The object is locked, because listener is called inside the sync block for the entry. You can modify the same object, but I would not recommend to execute any sync operations like cache updates inside the listener because it's error-prone and can affect performance. You should do this asynchronously, so that the lock is released as soon as possible.

Related

Circular (COM) reference when using IDispEventSimpleImpl

My question is about sinking COM events from a sub object properly, without creating a circular reference that would lead to memory leak(s).
There is an ActiveX control called CMyControl. This control creates an instance of an embedded web browser (IWebBrowser2) internally to display some HTML-content.
The web browser exposes an event source called DWebBrowserEvents2 that can deliver some interesting progress updates to CMyControl. Such as DocumentComplete when the HTML document has been fully loaded or when an error occurs etc.
And CMyControl will handle these events with the help of IDispEventSimpleImpl.
The issue I'm facing is that instances of CMyControl do not get destroyed when Release is called.
The direct reason for this is that the reference counter always ends up at 1 instead of 0.
Turns out that IDispEventSimpleImpl is indirectly responsible for this. This makes sense to me because the web browser needs the control's interface to sink the events, so it keeps a reference. Until you call the IDispEventSimpleImpl::DispEventUnadvise method, then the interface gets released.
But when Release gets called on IMyControl, the event source won't get disconnected.
I understand that: there is no reason why it would do that: Release doesn't even know about it.
Stumbled upon this post where they advise (pun intended) to create a custom "sink" object:
https://microsoft.public.vc.atl.narkive.com/4MgGRavd/dispeventadvise-dispeventunadvise-problem
The idea is that the sink object would see the events fired by the web browser first, before passing them on to CMyControl.
For this, an instance of this sink object would be stored inside CMyControl.
The sink object the connects to (and gets referenced by) the browser instead of the CMyControl instance itself. This breaks the circular reference.
Furthermore, the sink object gets passed a pointer to the "mothership" (the CMyControl instance) so it can perform a callback whenever an events occurs.
My question is: is this really how it should be done? isn't there a better/proper way to connect the events?

control moto's state transitions of EC2 instances?

To test that my application handles state transitions correctly, I'd like control over the lifecycle of moto's fake EC2 instances:
Rather than have instances start immediately in running, it would be nice to have them start in pending, let me confirm some things, and then explicitly transition them to running.
Relatedly, there are some actions I'd like to trigger in my tests when the instances switch to running.
Is any of this possible? I found InstanceBackend in moto's code -- is there a way for users to hook into or override methods there?
There are a few feature requests for more control over the transition cycle, but nothing has been implemented yet.
It is possible to use the internal API to set the status directly, as you said, using the InstanceBackend.
If you only have one instance, you can use the following code:
ec2_backend = moto.ec2.models.ec2_backends[my-region]
list(ec2_backend.reservations.values())[0].instances[0].state = "..."
If you have multiple reservations, you can use the reservation ID like this:
ec2_backend.reservations["r-7df1884b"].instances[0].state = "..."
Note that both AWS and Moto use two properties to track state, state and state_code. Only updating state may result in undefined behaviour, so you may want to update both to ensure they are in sync:
ec2_backend.reservations["r-7df1884b"].instances[0].state_code = ..
Note that this is an internal API, so changes to this data structure may occur without warning.

CacheEntryCreated event--again

Cross posted from JBoss Infinispan Discussions
I'm trying to implement some code that takes actions whenever an entry is created in one of my Infinispan caches. I realized quickly that the CacheEntryCreatedEvent object delieved to my #CacheEntryCreated method does not contain the newly created entry so I went searching for a solution.
I found various discussions about the problem with the solution being to catch the #CacheEntryModified event that is delivered after the #CacheEntryCreated event and take the object when the isPre()=false. However, I think I missed something because in all the disucssions none address the situation where you have a modification event that represent a elgitimate modification of an existing entry and not a creation.
Does this mean that my #Listener object has to maintain state information between the delivery of events? My #CacheEntryModified has to integate the event object, determine its a create event (i.e. getValue() == null && isPre() == true) and then wait for the next #CacheEntryModified event before grabbing the newly created object?
This bring up the obvious question of what to do if another #Listener object vetoes the modification before the second #CacheEntryModified (i.e. isPre() == false) event is delivered?
How do other peopel handle this situation?
I suppose the best way to do it now is with a ThreadLocal in your listener.
The future 5.3.0 release will improve this a lot, CacheEntryCreatedEvent will have a getValue() method and CacheEntryModifiedEvent will have a isCreated() method: https://github.com/infinispan/infinispan/commit/1aa2554e1c5ea46318402975de946f2e9ea44442#diff-22

Have mergeChangesFromContextDidSaveNotification: complete before listening NSFetchResultsControllers pounce and update themselves

I have an NSFetchedResultsController (FRC) backing a Table View. By definition, it's listening in for changes in it's managed object context (MOC) relevant to its defining fetch request.
While this table view is visible, I may have a small import (like ~ dozen records) I run, with managed objects that will be relevant to the watching FRC.
I run the import on a peer MOC to the one backing the table view. Both MOC's are NSMainQueueConcurrencyType, with a common parent MOC of NSPrivateQueueConcurrencyType.
As soon as the import completes with a save, my previously setup notification fires a handler, that simply does a mergeChangesFromContextDidSaveNotification:
- (void)scratchpadContextDidSave:(NSNotification *)saveNotification {
log4Info(#"Default Context now merging changes from Scratchpad Context save notification.");
[self.defaultContext mergeChangesFromContextDidSaveNotification:saveNotification];
}
Question:
How do I get the mergeChangesFromContextDidSaveNotification: to complete before any listening FRCs get notified?
Motivation
The FRC's new data coming in acts as a trigger of sorts in my application, which is fine, as long as all of the merged changes are available. My FRC acts immediately, not having complete information.
I'm going to remove logic needing the FRC to be patient this way, but it got me concerned that I'm not aware of a way to "lock" change notifications from going out until the entire merge operation is complete.
idStar,
A way to force a synchronous to all -save:s is to have them serialize their merges through a private serial queue where the last item actually performs the merge to the main MOC. Just because an item is saved to the persistent store, doesn't mean it has to be merged right away. You will have to merge the userInfo dictionaries yourself before submitting the dictionaries to the main MOC.
Andrew

NSManagedObject changed properties after save

Is it possible to find out which properties were saved on a managed object after the save occurs? For example, I have someone listening for managed object context saves, (NSManagedObjectContextDidSaveNotification) and I want to know which properties on the objects were saved.
The NSManagedObjectContextDidSaveNotification does contain all three bits of information you would need to sync with a server. Check the [notification userInfo] and you will find three sets inside: NSInsertedObjectsKey, NSUpdatedObjectsKey, and NSDeletedObjectsKey
If you want to know what properties on an entity have changed that would require that you track them yourself using KVO. I would recommend against this as the odds of that level of effort being worth it over just pushing the entire object up to a server are slim.
Update #2
On further poking around:
From the NSManagedObjectContextWillSaveNotification you could loop through each set and reference the changedValues method. You could keep a reference to that dictionary until after you receive the NSManagedObjectContextDidSaveNotification and then process the changes. Still sounds very heavy to me.
Update
What is your end goal?!?!
If you are trying to figure out what to push to a server then being at the attribute level is too low. You should be syncing at the entity level.
If you are just trying to keep some internal consistency inside of your application then you are thinking way, way too low level. This is a solved problem. Core Data solved it.
Why don't you get them when they are about to be saved. Subscribe to NSManagedObjectContextWillSaveNotification and check insertedObjects, updatedObjects and deletedObjects of the NSManagedObjectContext.
Update:
Even easier, get the user info of the NSManagedObjectContextDidSaveNotification
From the documentation:
Typically, on thread A you register for the managed object context
save notification, NSManagedObjectContextDidSaveNotification. When you
receive the notification, its user info dictionary contains arrays
with the managed objects that were inserted, deleted, and updated on
thread B.
http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/coredata/Articles/cdConcurrency.html#//apple_ref/doc/uid/TP40003385-SW1
Here's the solution I settled with. I have one singleton class that is notified when a context saves. The NSManagedObjectContextWillSave notification tells me which things have changed so I store them in a dictionary with the key being the context that saved. Then when I get the NSManagedObjectContextDidSave notification, I check the dictionary for the associated context. Finally, I remove that entry from the dictionary. Does that seem reasonable?