Refresh private queue when main queue changes in Core Data - objective-c

I have two managed object contexts in my application, one of type NSMainQueueConcurrencyType, the other a temporary NSPrivateQueueConcurrencyType for background work.
I couldn't find the official solution to the following situation: When the private queue is doing some background work while the main queue deletes an object, I get an uncaught exception "Core Data could not fulfill a fault" when accessing this object in the background queue since it was deleted.
This is an expected behavior, however I am wondering how to handle these cases without getting a fault exception. I'm thinking this can be fixed by listening to the "NSManagedObjectContextDidSaveNotification" notification and then merging the background context with the main context but is this really the best way to do?

Yes, observe the did-save notification, and merge the changes with
[context mergeChangesFromContextDidSaveNotification:notification];
Also, you want to make sure you have setup an appropriate merge policy.

Related

CQRS, EventStore and event sourcing: concurrency exceptions in SaveEvents use RPC?

I am implementing an event store. I have defined a SaveEventsConsumer that handles the storage of events in the event store. If I understand correctly CQRS commands should have no response. Nevertheless, there can be concurrency problems when saving events to the event store. I use RabbitMQ. Should the client be notified so it can notify the user for example? How should it be implemented? Using RPC and an error format?
My first approach is:
Client use RPC like style. SaveEventsConsumer notifies the client (success or failure). If an failure occurs (e.g. concurrency) return the exception to the client.
Is this solution aligned to the CQRS pattern? Is a good approach? Is there any other approach? Is there any improvement? Should I use any AMQP header or property to indicate the error (mimicking HTTP error codes)?
Example, in a cluster:
Two instances of the same application modify the same aggregate. These intances should coordinate (externally to the event-store) or is the event-store which has to detect and notify the response?
While it is true you don't return values from a command, an exception can still occur. A concurrency exception is one example. This implies the exception is thrown as part of the processing of a command. This makes sense when you think about it. You don't ever want events published which have not yet been committed to the event store. It follows then that concurrency conflict checking needs to happen as part of the overall command process.
I have a post which may help. You can find it here.

GPUImage gpus_ReturnNotPermittedKillClient crash using GPUImageFilter

I'm using GPUImageFilter in a chain, and most of the time it works OK. I've recently come across a few random crashes that match the symptoms in this github issue (albeit I'm using GPUImageFilter not live capture or video). I'm trying to find a suitable method that can ensure I've cleared the frame buffer and any other GPUImage-related activities in willResignActive.
Currently I have:
[[GPUImageContext sharedFramebufferCache] purgeAllUnassignedFramebuffers];
Is this sufficient? Should I use something else instead/in addition to?
As indicated there, seeing gpus_ReturnNotPermittedKillClient in a stack trace almost always is due to OpenGL ES operations being performed while your application is in the background or is just about to go to the background.
To deal with this, you need to guarantee that all GPUImage-related work is finished before your application heads to the background. You'll want to listen for delegate notifications that your application is heading to the background, and make sure all processing is complete before that delegate callback exits. The suggestion there by henryl is one way to ensure this. Add the following near the end of your delegate callback:
runSynchronouslyOnVideoProcessingQueue(^{
// Do some operation
});
What that will do is inject a synchronous block into the video processing pipeline (which runs on a background queue). Your delegate callback will block the main thread at that point until this block has a chance to execute, guaranteeing that all processing blocks before it have finished. That will make sure all pending operations are done (assuming you don't add new ones) before your application heads to the background.
There is a slight chance of this introducing a deadlock in your application, but I don't think any of my code in the processing pipeline calls back into the main queue. You might want to watch out for that, because if I do still have something in there that does that, this will lock your application. That internal code would need to be fixed if so.

Shared CoreData between apps

My question somewhat similar to How to have multiple apps - one Core Data?. But I am not unable to replicate as suggested in the answer.
I have two applications. One applications (1st App) allows user to do all sort of things and save in coredata.
Other application (2nd App) is a service application. Here I want the service to get notified everytime the coredata is updated(any changes like create, delete, update done).
If I use following notification in 2nd App, this notification does not get fired:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(modelUpdated)
name:NSManagedObjectContextDidSaveNotification
object:nil];
If I had an UI based application or even a background application in that case I can use NSDistributedNotification.
But I want something better than distributed notifications.
Please give me some hints so that I can move ahead.
NOTE: This app is not going through AppStore, so Sandboxing doesn't come under consideration.
If you are going to distribute your app yourself, you can do almost anything you want.
You can certainly attach a PSC in each application to the same SQLite file. No problem there.
As for knowing when the file has been modified, you can use kqueue or dispatch_source to monitor when the file has changed. However, just knowing that it has changed does not tell you what has changed, meaning your watcher process will need to refetch to get its MOC updated.
If this is sufficient, then it is probably the easiest route to take.
If you need more granular notification, then there is no getting around having to notify any interested parties what specifically has changed in the store. You can roll your own, use XPC, or simply use NSDistributedNotification (remember the latter is neither safe, nor guaranteed).
What you should do is observe NSManagedObjectContextDidSaveNotification on any MOC that is directly attached to the PSC. In that handler, you will create a notification similar to the one you received. Except, you should merely send sets of object IDs in URI representation.
Now, your observers can get detailed information about what objects were inserted, updated, and deleted.
Again, if you don't want to go through all this, you can use traditional OS mechanisms to observe that the file changed, and just refetch. If you choose this route, one thing you can do to help... Keep a "last modified" date for each object, and index on that attribute. Then, you can at least query objects that have changed since the last time you loaded the database. There are a number of other options to use here... the basic idea is that if you monitor via the OS, you only get told that something changed... you have to figure out what... if that matters.
For sandboxed apps, one of the few solutions available is to share data via an XPC launched daemon.
EDIT
distributedNotification I don't want to use, actually this wont work
for a deomon/service app. And your other point MOCDidSaveNoti is not
observed at all. I tried both before posting this question. – Anoop
Vaidya
Of course NSManagedObjectContextDidSaveNotification will not tell you what has changed in another process. It has no idea what changed, and has no idea about MOCs in other processes. I am sorry I wrote so poorly to make you think it would.
That notification is to be observed in any MOC that is changing the data store, for the sole purpose of propagating that information to other processes. The notification handler should then send a remote notification (however you want to do it... SHM, pipe, message queue, XPC, smoke signal, etc), with the object IDs of all the objects that have changed.
Any process that wants to know about the changed data store will then need to watch for the remote notification (however you choose to send it).
It really does not matter what you want to do... you are limited by what's available.
You have two basic choices:
observe a general change notification that the store has changed (kqueue, dispatch_source, etc). However, all you know is that the store changed, meaning that you will have to perform a complete refetch.
Send a remote notification whenever the store is saved, passing the object IDs of what has changed, and have other processes watch for that remote notification and update their MOC accordingly.

CoreData Multithreading Proper Store Deletion

Ok, here's my situation:
I've got an app which requires a user-account.
While you're doing stuff like writing new comments, creating new Posts or reading a thread, every call to the server runs on a separate thread.
More specifically: A new thread is created, makes a call to the server, gets an answer from the server and saves the items from the answer to the Core Data Store.
In order to do this, every thread creates his own insertionContext, but they all share the same storeCoordinator.
But there's one Problem:
When someone does a logout from his account, I have to delete the store,
so if he logs in with another account, the stuff from the other account isn't in the coreDataStorage anymore.
But in Order to delete the Store, I have to make sure that there aren't any background Threads running anymore, because once they try to to save their stuff, they are sure to crash the app, since the store isn't valid anymore.
To clarify: these background threads are NSOperations which are put in an NSOperationQueue and executed from there.
Now CoreData gives the NSOperationQueue a function called "cancelAllOperations" but according to the Documentation, running Operations aren't killed, but only send a cancel message...
How do I use this cancel Message o_O
So far i'm checking at some points whether my thread is canceled and if it is, I don't execute other stuff, but if I do stuff like:
NSError *saveError = nil;
if(!self.isCanceled)
[insertionContext save:&saveError];
There is still the possibility that the Thread is being canceled between the if-check and the save.
So my question:
How do I handle this properly? Is it a question of properly canceling the thread?
I think you should not cancel any operations since it does not kill the thread immediately. Why don't you manage all operations that are currently being executed? This way you can postpone persistent store deletion until all tasks complete (or delete it immediately if there are no operations in progress).

Matching CoreData save notifications for callbacks

I'd like to pick someone's brain on this. I have a dedicated save NSManagedObjectContext and GCD queue from which I operate on it. And whenever new data comes into my app I save it on that context and merge the changes into the main context. My problem arises in telling the main thread what just happened. Right after I call save my current context is now up-to-date, but if I fire a method in the main context it's context isn't. If I wait for the NSManagedObjectContextDidSave notification, and I save three times, I now have three queued delegate calls but no way to match them to the notifications coming in. Does anyone know of a good way to get around this?
EDIT
What I ended up doing was creating a new context for each save operation and attaching a block to be called when the save notification arrived. It looks like this, http://pastie.org/2068084
From your answer to my comment above, I see that you pass along the managedObjectContext in the notification. I'm not that confident about asynchronous stuff yet, but I do think that you're violating some concurrency rule, if I correctly interpret this quote from the NSManagedObjectContext Class Reference:
Concurrency
Core Data uses thread (or serialized queue) confinement to protect managed objects and managed object contexts (see “Concurrency with Core Data”). A consequence of this is that a context assumes the default owner is the thread or queue that allocated it—this is determined by the thread that calls its init method. You should not, therefore, initialize a context on one thread then pass it to a different thread. Instead, you should pass a reference to a persistent store coordinator and have the receiving thread/queue create a new context derived from that.
I'd say, try passing along the persistent store coordinator in the notification and recreate the managed object context in the block.
I'm not sure what you mean by, " ...if I fire a method in the main context it's context isn't. If I wait for the NSManagedObjectContextDidSave..." That implies that you are not waiting until the contexts have been merged. If so, that is why you can't access the data, it's just not in the front context.
Do you call mergeChangesFromContextDidSaveNotification: from the front context after it receives the notification?